diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0b7f3999e8264fb9546411c0f6b36490f881b4ba..1340ec0f3b90d6636a50dbc3a1de137f6dcd0e74 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -285,7 +285,7 @@ IF(WIN32)
 
   SET(FFMPEG ${LIBDIR}/ffmpeg)
   SET(FFMPEG_INC ${FFMPEG}/include)
-  SET(FFMPEG_LIB avcodec-51 avformat-52 avdevice-52 avutil-49 swscale-0)
+  SET(FFMPEG_LIB avcodec-52 avformat-52 avdevice-52 avutil-50 swscale-0)
   SET(FFMPEG_LIBPATH ${FFMPEG}/lib)
 
   IF(CMAKE_CL_64)
diff --git a/Makefile b/Makefile
index b983779fb31827cb9f4d5ec0e98db9bca445eee0..42475dba31cc24eddb9b746a8bd32a63940fd753 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,5 @@
+# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
+# vim: tabstop=8
 # $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
@@ -31,12 +33,11 @@
 # If the user wants to override some of the build
 # vars they can put it in the file user-def.mk which
 # will get included if it exists (please do not commit
-# user-def.mk to cvs).
-
+# user-def.mk to the revision control server).
 sinclude user-def.mk
 
-# To build without openAL, uncomment the following line, or set it as
-# an environment variable, or put it uncommented in user-def.mk:
+# To build without openAL, set it as an environment variable,
+# or put it uncommented in user-def.mk:
 # export NAN_NO_OPENAL=true
 
 export NANBLENDERHOME=$(shell pwd)
@@ -44,13 +45,9 @@ MAKEFLAGS=-I$(NANBLENDERHOME)/source --no-print-directory
 
 SOURCEDIR = 
 ifeq ($(FREE_WINDOWS),true)
-    DIRS ?= dlltool extern intern source
-endif
-
-DIRS ?= extern intern source
-
-ifneq ($(INTERNATIONAL),false)
-    DIRS += po
+    DIRS ?= dlltool extern intern source po
+else
+    DIRS ?= extern intern source po
 endif
 
 include source/nan_subdirs.mk
diff --git a/SConstruct b/SConstruct
index 7366149c593721fceeb3d8673f146e1d4d4d6e8f..03aee18413c656bb20a02496be9007ee3fd4b03d 100644
--- a/SConstruct
+++ b/SConstruct
@@ -262,29 +262,35 @@ if 'blendernogame' in B.targets:
 	env['WITH_BF_GAMEENGINE'] = False
 
 if 'blenderlite' in B.targets:
-	env['WITH_BF_GAMEENGINE'] = False
-	env['WITH_BF_OPENAL'] = False
-	env['WITH_BF_OPENEXR'] = False
-	env['WITH_BF_ICONV'] = False
-	env['WITH_BF_INTERNATIONAL'] = False
-	env['WITH_BF_OPENJPEG'] = False
-	env['WITH_BF_FFMPEG'] = False
-	env['WITH_BF_QUICKTIME'] = False
-	env['WITH_BF_YAFRAY'] = False
-	env['WITH_BF_REDCODE'] = False
-	env['WITH_BF_FTGL'] = False
-	env['WITH_BF_DDS'] = False
-	env['WITH_BF_ZLIB'] = False
-	env['WITH_BF_SDL'] = False
-	env['WITH_BF_JPEG'] = False
-	env['WITH_BF_PNG'] = False
-	env['WITH_BF_ODE'] = False
-	env['WITH_BF_BULLET'] = False
-	env['WITH_BF_SOLID'] = False
-	env['WITH_BF_BINRELOC'] = False
-	env['BF_BUILDINFO'] = False
-	env['BF_NO_ELBEEM'] = True
-	env['WITH_BF_PYTHON'] = False
+	target_env_defs = {}
+	target_env_defs['WITH_BF_GAMEENGINE'] = False
+	target_env_defs['WITH_BF_OPENAL'] = False
+	target_env_defs['WITH_BF_OPENEXR'] = False
+	target_env_defs['WITH_BF_ICONV'] = False
+	target_env_defs['WITH_BF_INTERNATIONAL'] = False
+	target_env_defs['WITH_BF_OPENJPEG'] = False
+	target_env_defs['WITH_BF_FFMPEG'] = False
+	target_env_defs['WITH_BF_QUICKTIME'] = False
+	target_env_defs['WITH_BF_YAFRAY'] = False
+	target_env_defs['WITH_BF_REDCODE'] = False
+	target_env_defs['WITH_BF_FTGL'] = False
+	target_env_defs['WITH_BF_DDS'] = False
+	target_env_defs['WITH_BF_ZLIB'] = False
+	target_env_defs['WITH_BF_SDL'] = False
+	target_env_defs['WITH_BF_JPEG'] = False
+	target_env_defs['WITH_BF_PNG'] = False
+	target_env_defs['WITH_BF_ODE'] = False
+	target_env_defs['WITH_BF_BULLET'] = False
+	target_env_defs['WITH_BF_SOLID'] = False
+	target_env_defs['WITH_BF_BINRELOC'] = False
+	target_env_defs['BF_BUILDINFO'] = False
+	target_env_defs['BF_NO_ELBEEM'] = True
+	target_env_defs['WITH_BF_PYTHON'] = False
+	
+	# Merge blenderlite, let command line to override
+	for k,v in target_env_defs.iteritems():
+		if k not in B.arguments:
+			env[k] = v
 
 # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
 #B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep)
@@ -548,7 +554,9 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'):
 	if env['WITH_BF_SDL']:
 		dllsources.append('${BF_SDL_LIBPATH}/SDL.dll')
 	if env['WITH_BF_PYTHON']:
-		dllsources.append('#release/windows/extra/python25.zip')
+		ver = env["BF_PYTHON_VERSION"].replace(".", "")
+		
+		dllsources.append('#release/windows/extra/python' + ver + '.zip')
 		dllsources.append('#release/windows/extra/zlib.pyd')
 		if env['BF_DEBUG']:
 			dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_LIB}_d.dll')
@@ -608,6 +616,13 @@ if not env['WITHOUT_BF_INSTALL']:
 
 #------------ EPYDOC
 if env['WITH_BF_DOCS']:
-	SConscript('source/blender/python/api2_2x/doc/SConscript')
-	SConscript('source/gameengine/PyDoc/SConscript')
+	try:		import epydoc
+	except:	epydoc = None
+	
+	if epydoc:
+		SConscript('source/blender/python/api2_2x/doc/SConscript')
+		SConscript('source/gameengine/PyDoc/SConscript')
+	else:
+		print "No epydoc install detected, Python API and Gameengine API Docs will not be generated "
+	
 
diff --git a/config/linux2-config.py b/config/linux2-config.py
index 5bd9a4c80849eb94148eb4d84b7267ffe82ea345..6d207dc40e69e64e22aba41691f28e6c8d6beec5 100644
--- a/config/linux2-config.py
+++ b/config/linux2-config.py
@@ -4,8 +4,16 @@ LIBDIR = "${LCGDIR}"
 WITH_BF_VERSE = False
 BF_VERSE_INCLUDE = "#extern/verse/dist"
 
+def py_version_string():
+	'''
+	returns py version - "2.5", "2.6" etc
+	'''
+	import platform
+	ver = platform.python_version_tuple()
+	return '%d.%d' % (int(ver[0]), int(ver[1])) # py2.5 uses strings, 2.6 ints
+
 BF_PYTHON = '/usr'
-BF_PYTHON_VERSION = '2.5'
+BF_PYTHON_VERSION = py_version_string()
 WITH_BF_STATICPYTHON = False
 BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
 BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
@@ -78,7 +86,8 @@ BF_FTGL = '#extern/bFTGL'
 BF_FTGL_INC = '${BF_FTGL}/include'
 BF_FTGL_LIB = 'extern_ftgl'
 
-WITH_BF_GAMEENGINE=False
+WITH_BF_GAMEENGINE = True
+WITH_BF_PLAYER = True
 
 WITH_BF_ODE = False
 BF_ODE = LIBDIR + '/ode'
diff --git a/extern/Makefile b/extern/Makefile
index 38bec4b73dd0d649ba4b734322abc919af1ff050..29d7da5b82273a5fdb1641143d6720b7e5fe6deb 100644
--- a/extern/Makefile
+++ b/extern/Makefile
@@ -49,9 +49,10 @@ ifeq ($(WITH_VERSE), true)
    DIRS += verse
 endif
 
-ifneq ($(NAN_NO_KETSJI), true)
-    DIRS += bullet2
-endif
+# Cloth requires it
+#ifneq ($(NAN_NO_KETSJI), true)
+DIRS += bullet2
+#endif
 
 ifeq ($(WITH_BINRELOC), true)
     DIRS += binreloc
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
index ea2e0ad2a2ba97382ca3d62a77893269b5722fe9..b6231a8fda6ec3580264253c3a57fd457345f663 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
@@ -350,12 +350,13 @@ int	btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
 		for (int i=0;i<clampedSimulationSteps;i++)
 		{
 			internalSingleStepSimulation(fixedTimeStep);
-			synchronizeMotionStates();
+			//for Blender, no need to synchronize here, it is done in blender anyway
+			//synchronizeMotionStates();
 		}
 
 	} 
-
-	synchronizeMotionStates();
+	//else
+	//	synchronizeMotionStates();
 
 	clearForces();
 
@@ -725,9 +726,13 @@ void	btDiscreteDynamicsWorld::calculateSimulationIslands()
 			{
 				if (colObj0->isActive() || colObj1->isActive())
 				{
-
-					getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),
-						(colObj1)->getIslandTag());
+					if ((colObj0)->getIslandTag() != -1 && (colObj1)->getIslandTag() != -1)
+					{
+					
+						getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),
+							(colObj1)->getIslandTag());
+					}
+					
 				}
 			}
 		}
diff --git a/extern/libopenjpeg/opj_includes.h b/extern/libopenjpeg/opj_includes.h
index 80d43df990f85ec9d544cccf2e81a0470c20748c..3464cfcf9ed9d86231ec64cf43d785bf99fdbf09 100644
--- a/extern/libopenjpeg/opj_includes.h
+++ b/extern/libopenjpeg/opj_includes.h
@@ -88,6 +88,12 @@ Most compilers implement their own version of this keyword ...
 
 /* MSVC does not have lrintf */
 #ifdef _MSC_VER
+#ifdef _M_X64
+#include <emmintrin.h>
+static INLINE long lrintf(float f) {
+        return _mm_cvtss_si32(_mm_load_ss(&f));
+} 
+#else
 static INLINE long lrintf(float f){
 	int i;
 
@@ -99,6 +105,7 @@ static INLINE long lrintf(float f){
 	return i;
 }
 #endif
+#endif
 
 #include "j2k_lib.h"
 #include "opj_malloc.h"
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 02dfdc2e25ca49cf9c4961bf3a87012a523c992d..e7e47a6bf3830165b2f63401dac87478c8e5eae1 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -107,6 +107,15 @@ GHOST_SystemX11(
 
 	m_wm_protocols= XInternAtom(m_display, "WM_PROTOCOLS", False);
 	m_wm_take_focus= XInternAtom(m_display, "WM_TAKE_FOCUS", False);
+	m_targets= XInternAtom(m_display, "TARGETS", False);
+	m_string= XInternAtom(m_display, "STRING", False);
+	m_compound_text= XInternAtom(m_display, "COMPOUND_TEXT", False);
+	m_text= XInternAtom(m_display, "TEXT", False);
+	m_clipboard= XInternAtom(m_display, "CLIPBOARD", False);
+	m_primary= XInternAtom(m_display, "PRIMARY", False);
+	m_xclip_out= XInternAtom(m_display, "XCLIP_OUT", False);
+	m_incr= XInternAtom(m_display, "INCR", False);
+	m_utf8_string= XInternAtom(m_display, "UTF8_STRING", False);
 
 	// compute the initial time
 	timeval tv;
@@ -515,11 +524,28 @@ GHOST_SystemX11::processEvent(XEvent *xe)
 					                              window, data);
 				}
 			} else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
+				XWindowAttributes attr;
+				Window fwin;
+				int revert_to;
+
 				/* as ICCCM say, we need reply this event
 				 * with a SetInputFocus, the data[1] have
 				 * the valid timestamp (send by the wm).
+				 *
+				 * Some WM send this event before the
+				 * window is really mapped (for example
+				 * change from virtual desktop), so we need
+				 * to be sure that our windows is mapped
+				 * or this call fail and close blender.
 				 */
-				XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
+				if (XGetWindowAttributes(m_display, xcme.window, &attr) == True) {
+					if (XGetInputFocus(m_display, &fwin, &revert_to) == True) {
+						if (attr.map_state == IsViewable) {
+							if (fwin != xcme.window)
+								XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
+						}
+					}
+				}
 			} else {
 				/* Unknown client message, ignore */
 			}
@@ -975,144 +1001,299 @@ convertXKey(
 
 #undef GXMAP
 
-	GHOST_TUns8*
-GHOST_SystemX11::
-getClipboard(int flag
-) const {
-	//Flag 
-	//0 = Regular clipboard 1 = selection
-	static Atom Primary_atom, clip_String, compound_text, a_text, a_string;
-	Atom rtype;
-	Window m_window, owner;
-	unsigned char *data, *tmp_data;
-	int bits, count;
-	unsigned long len, bytes;
-	XEvent xevent;
-	
+
+/* from xclip.c xcout() v0.11 */
+
+#define XCLIB_XCOUT_NONE		0 /* no context */
+#define XCLIB_XCOUT_SENTCONVSEL		1 /* sent a request */
+#define XCLIB_XCOUT_INCR		2 /* in an incr loop */
+#define XCLIB_XCOUT_FALLBACK		3 /* STRING failed, need fallback to UTF8 */
+#define XCLIB_XCOUT_FALLBACK_UTF8	4 /* UTF8 failed, move to compouned */
+#define XCLIB_XCOUT_FALLBACK_COMP	5 /* compouned failed, move to text. */
+#define XCLIB_XCOUT_FALLBACK_TEXT	6
+
+// Retrieves the contents of a selections.
+void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
+	Atom sel, Atom target, unsigned char **txt,
+	unsigned long *len, unsigned int *context) const
+{
+	Atom pty_type;
+	int pty_format;
+	unsigned char *buffer;
+	unsigned long pty_size, pty_items;
+	unsigned char *ltxt= *txt;
+
 	vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
 	vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
 	GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
-	m_window = window->getXWindow();
+	Window win = window->getXWindow();
+
+	switch (*context) {
+		// There is no context, do an XConvertSelection()
+		case XCLIB_XCOUT_NONE:
+			// Initialise return length to 0
+			if (*len > 0) {
+				free(*txt);
+				*len = 0;
+			}
 
-	clip_String = XInternAtom(m_display, "_BLENDER_STRING", False);
-	compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
-	a_text= XInternAtom(m_display, "TEXT", False);
-	a_string= XInternAtom(m_display, "STRING", False);
-
-	//lets check the owner and if it is us then return the static buffer
-	if(flag == 0) {
-		Primary_atom = XInternAtom(m_display, "CLIPBOARD", False);
-		owner = XGetSelectionOwner(m_display, Primary_atom);
-		if (owner == m_window) {
-			data = (unsigned char*) malloc(strlen(txt_cut_buffer)+1);
-			strcpy((char*)data, txt_cut_buffer);
-			return (GHOST_TUns8*)data;
-		} else if (owner == None) {
-			return NULL;
-		}
-	} else {
-		Primary_atom = XInternAtom(m_display, "PRIMARY", False);
-		owner = XGetSelectionOwner(m_display, Primary_atom);
-		if (owner == m_window) {
-			data = (unsigned char*) malloc(strlen(txt_select_buffer)+1);
-			strcpy((char*)data, txt_select_buffer);
-			return (GHOST_TUns8*)data;
-		} else if (owner == None) {
-			return NULL;
-		}
-	}
+			// Send a selection request
+			XConvertSelection(m_display, sel, target, m_xclip_out, win, CurrentTime);
+			*context = XCLIB_XCOUT_SENTCONVSEL;
+			return;
 
-	if(!Primary_atom) {
-		return NULL;
-	}
-	
-	XDeleteProperty(m_display, m_window, Primary_atom);
-	XConvertSelection(m_display, Primary_atom, compound_text, clip_String, m_window, CurrentTime); //XA_STRING
-	XFlush(m_display);
+		case XCLIB_XCOUT_SENTCONVSEL:
+			if (evt.type != SelectionNotify)
+				return;
 
-	//This needs to change so we do not wait for ever or check owner first
-	count= 1;
-	while(1) {
-		XNextEvent(m_display, &xevent);
-		if(xevent.type == SelectionNotify) {
-			if (xevent.xselection.property == None) {
-				/* Ok, the client can't convert the property
-				 * to some that we can handle, try other types..
-				 */
-				if (count == 1) {
-					XConvertSelection(m_display, Primary_atom, a_text, clip_String, m_window, CurrentTime);
-					count++;
-				}
-				else if (count == 2) {
-					XConvertSelection(m_display, Primary_atom, a_string, clip_String, m_window, CurrentTime);
-					count++;
-				}
-				else {
-					/* Ok, the owner of the selection can't 
-					 * convert the data to something that we can
-					 * handle.
-					 */
-					return(NULL);
-				}
+			if (target == m_utf8_string && evt.xselection.property == None) {
+				*context= XCLIB_XCOUT_FALLBACK_UTF8;
+				return;
+			}
+			else if (target == m_compound_text && evt.xselection.property == None) {
+				*context= XCLIB_XCOUT_FALLBACK_COMP;
+				return;
+			}
+			else if (target == m_text && evt.xselection.property == None) {
+				*context= XCLIB_XCOUT_FALLBACK_TEXT;
+				return;
 			}
-			else {
-				if(XGetWindowProperty(m_display, m_window, xevent.xselection.property , 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) {
-					if (data) {
-						if (bits == 8 && (rtype == compound_text || rtype == a_text || rtype == a_string)) {
-							tmp_data = (unsigned char*) malloc(strlen((char*)data)+1);
-							strcpy((char*)tmp_data, (char*)data);
-						}
-						else
-							tmp_data= NULL;
 
-						XFree(data);
-						return (GHOST_TUns8*)tmp_data;
-					}
-				}
-				return(NULL);
+			// find the size and format of the data in property
+			XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
+				AnyPropertyType, &pty_type, &pty_format,
+				&pty_items, &pty_size, &buffer);
+			XFree(buffer);
+
+			if (pty_type == m_incr) {
+				// start INCR mechanism by deleting property
+				XDeleteProperty(m_display, win, m_xclip_out);
+				XFlush(m_display);
+				*context = XCLIB_XCOUT_INCR;
+				return;
 			}
-		}
+
+			// if it's not incr, and not format == 8, then there's
+			// nothing in the selection (that xclip understands, anyway)
+
+			if (pty_format != 8) {
+				*context = XCLIB_XCOUT_NONE;
+				return;
+			}
+
+			// not using INCR mechanism, just read the property
+			XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
+					False, AnyPropertyType, &pty_type,
+					&pty_format, &pty_items, &pty_size, &buffer);
+
+			// finished with property, delete it
+			XDeleteProperty(m_display, win, m_xclip_out);
+
+			// copy the buffer to the pointer for returned data
+			ltxt = (unsigned char *) malloc(pty_items);
+			memcpy(ltxt, buffer, pty_items);
+
+			// set the length of the returned data
+			*len = pty_items;
+			*txt = ltxt;
+
+			// free the buffer
+			XFree(buffer);
+
+			*context = XCLIB_XCOUT_NONE;
+
+			// complete contents of selection fetched, return 1
+			return;
+
+		case XCLIB_XCOUT_INCR:
+			// To use the INCR method, we basically delete the
+			// property with the selection in it, wait for an
+			// event indicating that the property has been created,
+			// then read it, delete it, etc.
+
+			// make sure that the event is relevant
+			if (evt.type != PropertyNotify)
+				return;
+
+			// skip unless the property has a new value
+			if (evt.xproperty.state != PropertyNewValue)
+				return;
+
+			// check size and format of the property
+			XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
+				AnyPropertyType, &pty_type, &pty_format,
+				&pty_items, &pty_size, (unsigned char **) &buffer);
+
+			if (pty_format != 8) {
+				// property does not contain text, delete it
+				// to tell the other X client that we have read	
+				// it and to send the next property
+				XFree(buffer);
+				XDeleteProperty(m_display, win, m_xclip_out);
+				return;
+			}
+
+			if (pty_size == 0) {
+				// no more data, exit from loop
+				XFree(buffer);
+				XDeleteProperty(m_display, win, m_xclip_out);
+				*context = XCLIB_XCOUT_NONE;
+
+				// this means that an INCR transfer is now
+				// complete, return 1
+				return;
+			}
+
+			XFree(buffer);
+
+			// if we have come this far, the propery contains
+			// text, we know the size.
+			XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
+				False, AnyPropertyType, &pty_type, &pty_format,
+				&pty_items, &pty_size, (unsigned char **) &buffer);
+
+			// allocate memory to accommodate data in *txt
+			if (*len == 0) {
+				*len = pty_items;
+				ltxt = (unsigned char *) malloc(*len);
+			}
+			else {
+				*len += pty_items;
+				ltxt = (unsigned char *) realloc(ltxt, *len);
+			}
+
+			// add data to ltxt
+			memcpy(&ltxt[*len - pty_items], buffer, pty_items);
+
+			*txt = ltxt;
+			XFree(buffer);
+
+			// delete property to get the next item
+			XDeleteProperty(m_display, win, m_xclip_out);
+			XFlush(m_display);
+			return;
 	}
+	return;
 }
 
-	void
-GHOST_SystemX11::
-putClipboard(
-GHOST_TInt8 *buffer, int flag) const
+GHOST_TUns8 *GHOST_SystemX11::getClipboard(int flag) const
 {
-	static Atom Primary_atom;
-	Window m_window, owner;
-	
-	if(!buffer) {return;}
+	//Flag 
+	//0 = Regular clipboard 1 = selection
 	
-	if(flag == 0) {
-		Primary_atom = XInternAtom(m_display, "CLIPBOARD", False);
-		if(txt_cut_buffer) { free((void*)txt_cut_buffer); }
+	// Options for where to get the selection from
+	Atom sseln= flag ? m_primary : m_clipboard;
+	Atom target= m_string;
+	Window owner;
+
+	// from xclip.c doOut() v0.11
+	unsigned char *sel_buf;
+	unsigned long sel_len= 0;
+	XEvent evt;
+	unsigned int context= XCLIB_XCOUT_NONE;
+
+	vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+	vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+	GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
+	Window win = window->getXWindow();
+
+	/* check if we are the owner. */
+	owner= XGetSelectionOwner(m_display, sseln);
+	if (owner == win) {
+		if (sseln == m_clipboard) {
+			sel_buf= (unsigned char *)malloc(strlen(txt_cut_buffer)+1);
+			strcpy((char *)sel_buf, txt_cut_buffer);
+			return((GHOST_TUns8*)sel_buf);
+		}
+		else {
+			sel_buf= (unsigned char *)malloc(strlen(txt_select_buffer)+1);
+			strcpy((char *)sel_buf, txt_select_buffer);
+			return((GHOST_TUns8*)sel_buf);
+		}
+	}
+	else if (owner == None)
+		return(NULL);
+
+	while (1) {
+		/* only get an event if xcout() is doing something */
+		if (context != XCLIB_XCOUT_NONE)
+			XNextEvent(m_display, &evt);
+
+		/* fetch the selection, or part of it */
+		getClipboard_xcout(evt, sseln, target, &sel_buf, &sel_len, &context);
+
+		/* fallback is needed. set XA_STRING to target and restart the loop. */
+		if (context == XCLIB_XCOUT_FALLBACK) {
+			context= XCLIB_XCOUT_NONE;
+			target= m_string;
+			continue;
+		}
+		else if (context == XCLIB_XCOUT_FALLBACK_UTF8) {
+			/* utf8 fail, move to compouned text. */
+			context= XCLIB_XCOUT_NONE;
+			target= m_compound_text;
+			continue;
+		}
+		else if (context == XCLIB_XCOUT_FALLBACK_COMP) {
+			/* compouned text faile, move to text. */
+			context= XCLIB_XCOUT_NONE;
+			target= m_text;
+			continue;
+		}
+
+		/* only continue if xcout() is doing something */
+		if (context == XCLIB_XCOUT_NONE)
+			break;
+	}
+
+	if (sel_len) {
+		/* only print the buffer out, and free it, if it's not
+		 * empty
+		 */
+		unsigned char *tmp_data = (unsigned char*) malloc(sel_len+1);
+		memcpy((char*)tmp_data, (char*)sel_buf, sel_len);
+		tmp_data[sel_len] = '\0';
 		
-		txt_cut_buffer = (char*) malloc(strlen(buffer)+1);
-		strcpy(txt_cut_buffer, buffer);
-	} else {
-		Primary_atom = XInternAtom(m_display, "PRIMARY", False);
-		if(txt_select_buffer) { free((void*)txt_select_buffer); }
+		if (sseln == m_string)
+			XFree(sel_buf);
+		else
+			free(sel_buf);
 		
-		txt_select_buffer = (char*) malloc(strlen(buffer)+1);
-		strcpy(txt_select_buffer, buffer);
+		return (GHOST_TUns8*)tmp_data;
 	}
-	
-	vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+	return(NULL);
+}
+
+void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, int flag) const
+{
+	Window m_window, owner;
+
+	vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();	
 	vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
 	GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
 	m_window = window->getXWindow();
 
-	if(!Primary_atom) {
-		return;
-	}
-	
-	XSetSelectionOwner(m_display, Primary_atom, m_window, CurrentTime);
-	owner = XGetSelectionOwner(m_display, Primary_atom);
-	if (owner != m_window)
-		fprintf(stderr, "failed to own primary\n");
+	if (buffer) {
+		if (flag == 0) {
+			XSetSelectionOwner(m_display, m_clipboard, m_window, CurrentTime);
+			owner= XGetSelectionOwner(m_display, m_clipboard);
+			if (txt_cut_buffer)
+				free((void*)txt_cut_buffer);
+
+			txt_cut_buffer = (char*) malloc(strlen(buffer)+1);
+			strcpy(txt_cut_buffer, buffer);
+		} else {
+			XSetSelectionOwner(m_display, m_primary, m_window, CurrentTime);
+			owner= XGetSelectionOwner(m_display, m_primary);
+			if (txt_select_buffer)
+				free((void*)txt_select_buffer);
+
+			txt_select_buffer = (char*) malloc(strlen(buffer)+1);
+			strcpy(txt_select_buffer, buffer);
+		}
 	
-	return;
+		if (owner != m_window)
+			fprintf(stderr, "failed to own primary\n");
+	}
 }
 
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 576577917ba67c0b2c6e172367733340afc9cf87..6a2c81c09a78dac1ce15d34a13db3ea877f02fcb 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -199,14 +199,18 @@ public:
 	prepareNdofInfo(
 		volatile GHOST_TEventNDOFData *current_values
 	);
-		
+
+	/* Helped function for get data from the clipboard. */
+	void getClipboard_xcout(XEvent evt, Atom sel, Atom target,
+			 unsigned char **txt, unsigned long *len,
+			 unsigned int *context) const;
+
 	/**
 	 * Returns unsinged char from CUT_BUFFER0
 	 * @param flag		Flag indicates which buffer to return 0 for clipboard 1 for selection
 	 * @return		Returns the Clipboard indicated by Flag
 	 */
-		GHOST_TUns8*
-	getClipboard(int flag) const;
+	GHOST_TUns8 *getClipboard(int flag) const;
 	
 	/**
 	 * Puts buffer to system clipboard
@@ -220,6 +224,17 @@ public:
 	Atom m_wm_protocols;
 	Atom m_delete_window_atom;
 
+	/* Atoms for Selection, copy & paste. */
+	Atom m_targets;
+	Atom m_string;
+	Atom m_compound_text;
+	Atom m_text;
+	Atom m_clipboard;
+	Atom m_primary;
+	Atom m_xclip_out;
+	Atom m_incr;
+	Atom m_utf8_string;
+
 private :
 
 	Display * m_display;
diff --git a/intern/moto/include/MT_Quaternion.inl b/intern/moto/include/MT_Quaternion.inl
index ecfd6699f67eafc23d34f3b23bdebce851116f9a..ec747c453d3d6426fc546ca24fd08e1ff9218385 100644
--- a/intern/moto/include/MT_Quaternion.inl
+++ b/intern/moto/include/MT_Quaternion.inl
@@ -74,19 +74,27 @@ GEN_INLINE MT_Scalar MT_Quaternion::angle(const MT_Quaternion& q) const
 
 GEN_INLINE MT_Quaternion MT_Quaternion::slerp(const MT_Quaternion& q, const MT_Scalar& t) const
 {
-	MT_Scalar theta = angle(q);
-	
-	if (!MT_fuzzyZero(theta))
+	MT_Scalar d, s0, s1;
+	MT_Scalar s = dot(q);
+	bool neg = (s < 0.0);
+
+	if (neg)
+		s = -s;
+	if ((1.0 - s) > 0.0001) 
 	{
-		MT_Scalar d = MT_Scalar(1.0) / sin(theta);
-		MT_Scalar s0 = sin((MT_Scalar(1.0) - t) * theta);
-		MT_Scalar s1 = sin(t * theta);
-		
-		return d*(*this * s0 + q * s1);
+		MT_Scalar theta = acos(s);
+		d = MT_Scalar(1.0) / sin(theta);
+		s0 = sin((MT_Scalar(1.0) - t) * theta);
+		s1 = sin(t * theta);
 	}
 	else
 	{
-		return *this;
+		d = MT_Scalar(1.0);
+		s0 = MT_Scalar(1.0) - t;
+		s1 = t;
 	}
+	if (neg)
+		s1 = -s1;
+	return d*(*this * s0 + q * s1);
 }
 
diff --git a/po/Makefile b/po/Makefile
index 4bafba8a6e63accbf326e6223350c47ef72520e6..425efbc08b3a99b3ce4295ad196a44704bb8e560 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -1,3 +1,5 @@
+# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
+# vim: tabstop=8
 # $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
@@ -9,47 +11,51 @@
 #
 # 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
+# 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, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# Inc., 59 Temple Place - Suite 330, Boston, MA	 02111-1307, USA.
 #
 # The Original Code is Copyright (C) 2002 by Stichting Blender Foundation,
 # Amsterdam, the Netherlands.
 # All rights reserved.
 #
-# The Original Code is: revision 1.1
+# The Original Code is: revision 1.3
 #
-# Contributor(s): Wouter van Heyst
+# Contributor(s): Wouter van Heyst, GSR
 #
 # ***** END GPL LICENSE BLOCK *****
 #
-# po Makefile for blender. Compiles the translations and places them
+# po Makefile for blender. Compiles the translations in the place
 # where release can pick them up.
 
+PO_FILES = $(wildcard *.po)
+
+LINGUAS = $(basename $(PO_FILES))
+
 SOURCEDIR = blender/po
 
 include nan_definitions.mk
 
-LINGUAS = ar bg ca cs de el es fi fr hr it ja ko nl pl pt_BR ro ru sr sr@Latn sv uk zh_CN
-
 ifeq ($(OS), darwin)
-DIR = $(OCGDIR)/bin/blender.app/Contents/Resources/locale/$@/LC_MESSAGES/
+  DIR = $(OCGDIR)/bin/blender.app/Contents/Resources/locale/
 else
-DIR = $(OCGDIR)/bin/.blender/locale/$@/LC_MESSAGES/
+  DIR = $(OCGDIR)/bin/.blender/locale/
 endif
 
-all debug:: $(LINGUAS)
+LINGUAS_DEST= $(foreach LINGUA, $(LINGUAS),$(DIR)$(LINGUA)/LC_MESSAGES/blender.mo)
 
-clean::
-ifeq ($(OS), darwin)
-	rm -rf $(OCGDIR)/bin/blender.app/Contents/Resources/locale/
-else
-	rm -rf $(OCGDIR)/bin/.blender/locale/
-endif
+$(DIR)%/LC_MESSAGES/blender.mo: %.po
+	mkdir -p $(@D)
+	msgfmt -o $@ $<
+	@cmp $@ $(NANBLENDERHOME)/bin/.blender/locale/$(basename $<)/LC_MESSAGES/blender.mo \
+          || ( echo Mismatch between generated and commited $(basename $<).mo catalog && \
+               rm -f $@ && false )
 
-$(LINGUAS):
-	mkdir -p $(DIR)
-	msgfmt -o $(DIR)/blender.mo $@.po
+all debug:: $(LINGUAS_DEST)
+#	Just trigger the deps
+
+clean::
+	rm -rf $(DIR)
diff --git a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
index 2ffc9afa67caa427a1ef8781042c1a42fceec643..55ef074178bf9a8c37ea27c8d94b4c67fd8b2ea1 100644
--- a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
+++ b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
@@ -358,6 +358,10 @@
 				RelativePath="..\..\..\source\blender\python\api2_2x\bpy_data.c"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\blender\python\api2_2x\bpy_internal_import.c"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\blender\python\api2_2x\Camera.c"
 				>
@@ -585,10 +589,6 @@
 					RelativePath="..\..\..\source\blender\python\api2_2x\Particle.c"
 					>
 				</File>
-				<File
-					RelativePath="..\..\..\source\blender\python\api2_2x\point.c"
-					>
-				</File>
 				<File
 					RelativePath="..\..\..\source\blender\python\api2_2x\quat.c"
 					>
@@ -643,6 +643,10 @@
 				RelativePath="..\..\..\source\blender\python\api2_2x\bpy_data.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\blender\python\api2_2x\bpy_internal_import.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\blender\python\api2_2x\Camera.h"
 				>
@@ -874,10 +878,6 @@
 					RelativePath="..\..\..\source\blender\python\api2_2x\Particle.h"
 					>
 				</File>
-				<File
-					RelativePath="..\..\..\source\blender\python\api2_2x\point.h"
-					>
-				</File>
 				<File
 					RelativePath="..\..\..\source\blender\python\api2_2x\quat.h"
 					>
diff --git a/projectfiles_vc9/blender/blender.vcproj b/projectfiles_vc9/blender/blender.vcproj
index 03f57a90c441abdc95ccb03f82590d6b0eaffb90..2f1bf468219fc81bb7e3259eb2953511075352e2 100644
--- a/projectfiles_vc9/blender/blender.vcproj
+++ b/projectfiles_vc9/blender/blender.vcproj
@@ -81,6 +81,7 @@
 				AdditionalLibraryDirectories="..\..\..\lib\windows\sdl\lib;..\..\..\lib\windows\ode\lib;..\..\..\lib\windows\zlib\lib;..\..\..\lib\windows\png\lib;..\..\..\lib\windows\jpeg\lib;..\..\..\lib\windows\gettext\lib;..\..\..\lib\windows\python\lib\lib25_vs2008;..\..\..\lib\windows\freetype\lib;..\..\..\lib\windows\tiff\lib;..\..\..\lib\windows\pthreads\lib;..\..\..\lib\windows\openal\lib;..\..\..\lib\windows\openexr\lib_vs2008;..\..\..\lib\windows\QTDevWin\Libraries;..\..\..\build\msvc_9\libs\intern;..\..\..\build\msvc_9\libs\extern;..\..\..\lib\windows\ffmpeg\lib"
 				IgnoreAllDefaultLibraries="false"
 				IgnoreDefaultLibraryNames="msvcprt.lib;glut32.lib;libc.lib;libcd.lib;libcpd.lib;libcp.lib;libcmtd.lib;odbc32.lib;odbccp32.lib"
+				GenerateDebugInformation="true"
 				ProgramDatabaseFile="..\..\..\build\msvc_9\libs\blender.pdb"
 				SubSystem="1"
 				RandomizedBaseAddress="1"
@@ -167,7 +168,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386&#x0D;&#x0A;"
-				AdditionalDependencies="SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib openal_static.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half.lib Iex.lib Imath.lib IlmImf.lib IlmThread.lib avcodec-52.lib avformat-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib"
+				AdditionalDependencies="SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib openal_static.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half_d.lib Iex_d.lib Imath_d.lib IlmImf_d.lib IlmThread_d.lib avcodec-52.lib avformat-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib"
 				ShowProgress="0"
 				OutputFile="..\..\bin\debug\blender.exe"
 				LinkIncremental="2"
diff --git a/projectfiles_vc9/gameengine/converter/KX_converter.vcproj b/projectfiles_vc9/gameengine/converter/KX_converter.vcproj
index 53a628ed5ee7372f56c3e10a9c7f02111c6973c3..4f5b34485cf9c676c974488a81128864dc4f44ae 100644
--- a/projectfiles_vc9/gameengine/converter/KX_converter.vcproj
+++ b/projectfiles_vc9/gameengine/converter/KX_converter.vcproj
@@ -479,10 +479,6 @@
 				RelativePath="..\..\..\source\gameengine\Converter\BL_ActionActuator.cpp"
 				>
 			</File>
-			<File
-				RelativePath="..\..\..\source\gameengine\Converter\BL_ArmatureObject.cpp"
-				>
-			</File>
 			<File
 				RelativePath="..\..\..\source\gameengine\Converter\BL_BlenderDataConversion.cpp"
 				>
@@ -495,6 +491,10 @@
 				RelativePath="..\..\..\source\gameengine\Converter\BL_MeshDeformer.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\gameengine\Converter\BL_ModifierDeformer.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\gameengine\Converter\BL_ShapeActionActuator.cpp"
 				>
@@ -552,6 +552,10 @@
 				RelativePath="..\..\..\source\gameengine\Converter\BL_ActionActuator.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\gameengine\Converter\BL_ArmatureObject.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\gameengine\Converter\BL_ArmatureObject.h"
 				>
@@ -568,6 +572,10 @@
 				RelativePath="..\..\..\source\gameengine\Converter\BL_MeshDeformer.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\gameengine\Converter\BL_ModifierDeformer.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\gameengine\Converter\BL_ShapeActionActuator.h"
 				>
diff --git a/projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj b/projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj
index 436a007dffb6332e9bf630cabc43291fa3355e16..a8b94c3f4a0276c796ffa95dc07764a0ef81bc1f 100644
--- a/projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj
+++ b/projectfiles_vc9/gameengine/expression/EXP_expressions.vcproj
@@ -4,6 +4,7 @@
 	Version="9,00"
 	Name="EXP_expressions"
 	ProjectGUID="{EADC3C5A-6C51-4F03-8038-1553E7D7F740}"
+	RootNamespace="EXP_expressions"
 	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
@@ -42,7 +43,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
 				PreprocessorDefinitions="WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -117,7 +118,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
 				PreprocessorDefinitions="WIN32,_LIB,EXP_PYTHON_EMBEDDING,_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
@@ -192,7 +193,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
 				StringPooling="true"
 				RuntimeLibrary="2"
@@ -267,7 +268,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
 				StringPooling="true"
 				RuntimeLibrary="0"
@@ -342,7 +343,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
 				PreprocessorDefinitions="WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -417,7 +418,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\SceneGraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
 				StringPooling="true"
 				RuntimeLibrary="0"
diff --git a/projectfiles_vc9/gameengine/gamelogic/SCA_GameLogic.vcproj b/projectfiles_vc9/gameengine/gamelogic/SCA_GameLogic.vcproj
index e350db5dad8ac2ee68c0e0b27d8a3f88824ef485..e4d41824fb14281bf480e394cde69a8907cb1cfd 100644
--- a/projectfiles_vc9/gameengine/gamelogic/SCA_GameLogic.vcproj
+++ b/projectfiles_vc9/gameengine/gamelogic/SCA_GameLogic.vcproj
@@ -4,6 +4,7 @@
 	Version="9,00"
 	Name="SCA_GameLogic"
 	ProjectGUID="{32CC75E2-EE85-45E6-8E3D-513F58464F43}"
+	RootNamespace="SCA_GameLogic"
 	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
@@ -42,7 +43,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -117,7 +118,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
 				StringPooling="true"
 				RuntimeLibrary="0"
@@ -192,7 +193,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
 				StringPooling="true"
 				RuntimeLibrary="2"
@@ -267,7 +268,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="WIN32,_LIB,EXP_PYTHON_EMBEDDING,_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
@@ -342,7 +343,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -417,7 +418,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Rasterizer;..\..\..\source\blender\makesdna;..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB,EXP_PYTHON_EMBEDDING"
 				StringPooling="true"
 				RuntimeLibrary="0"
diff --git a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj
index 9fa3751c43612afa43c30a661f15167e7b6b3f13..5cd8a9c469b5b54a3484479177e9c5dd7b26ec07 100644
--- a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj
+++ b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj
@@ -72,7 +72,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386&#x0D;&#x0A;"
-				AdditionalDependencies="odelib.lib fmodvc.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-52.lib avformat-52.lib avutil-50.lib swscale-0.lib avdevice-52.lib"
+				AdditionalDependencies="odelib.lib fmodvc.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib Half_d.lib Iex_d.lib IlmImf_d.lib IlmThread_d.lib Imath_d.lib avcodec-52.lib avformat-52.lib avutil-50.lib swscale-0.lib avdevice-52.lib"
 				ShowProgress="0"
 				OutputFile="..\..\..\..\bin\debug\blenderplayer.exe"
 				LinkIncremental="2"
@@ -166,12 +166,13 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odelib.lib fmodvc.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-52.lib avformat-52.lib avutil-50.lib swscale-0.lib avdevice-52.lib"
+				AdditionalDependencies="odelib.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-52.lib avformat-52.lib avutil-50.lib swscale-0.lib avdevice-52.lib"
 				OutputFile="..\..\..\..\bin\blenderplayer.exe"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
 				AdditionalLibraryDirectories="..\..\..\..\..\lib\windows\sdl\lib;..\..\..\..\..\lib\windows\zlib\lib;..\..\..\..\..\lib\windows\ode\lib;..\..\..\..\..\lib\windows\png\lib;..\..\..\..\..\lib\windows\jpeg\lib;..\..\..\..\..\lib\windows\fmod\lib;..\..\..\..\..\lib\windows\openal\lib;..\..\..\..\..\lib\windows\freetype\lib;..\..\..\..\..\lib\windows\openexr\lib_vs2008;..\..\..\..\..\lib\windows\python\lib\lib25_vs2008;..\..\..\..\..\lib\windows\openssl\lib;..\..\..\..\..\lib\windows\QTDevWin\Libraries;..\..\..\..\..\lib\windows\pthreads\lib;..\..\..\..\..\lib\windows\ffmpeg\lib"
 				IgnoreDefaultLibraryNames="libc.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib"
+				GenerateDebugInformation="true"
 				ProgramDatabaseFile="..\..\..\..\..\build\msvc_9\libs\blenderplayer.pdb"
 				SubSystem="1"
 				RandomizedBaseAddress="1"
diff --git a/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj b/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
index 80c34bef2238cc847cfdc28aa2de7871644ce586..fb812c02f4432bff7b08c63c7d29fadd4bce61d6 100644
--- a/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
+++ b/projectfiles_vc9/gameengine/ketsji/KX_ketsji.vcproj
@@ -581,6 +581,10 @@
 				RelativePath="..\..\..\source\gameengine\Ketsji\KX_PythonInitTypes.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\gameengine\Ketsji\KX_PythonSeq.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\gameengine\Ketsji\KX_RayCast.cpp"
 				>
@@ -890,6 +894,10 @@
 				RelativePath="..\..\..\source\gameengine\Ketsji\KX_PythonInitTypes.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\gameengine\Ketsji\KX_PythonSeq.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\gameengine\Ketsji\KX_RayCast.h"
 				>
diff --git a/projectfiles_vc9/gameengine/ketsji/network/KX_network.vcproj b/projectfiles_vc9/gameengine/ketsji/network/KX_network.vcproj
index a3f43b01763a3632cc36eef2e011305f64408c11..fc197d0d1f4c20d1e32f82e9b9e0121c73fd5be5 100644
--- a/projectfiles_vc9/gameengine/ketsji/network/KX_network.vcproj
+++ b/projectfiles_vc9/gameengine/ketsji/network/KX_network.vcproj
@@ -4,6 +4,7 @@
 	Version="9,00"
 	Name="KX_network"
 	ProjectGUID="{6E24BF09-9653-4166-A871-F65CC9E98A9B}"
+	RootNamespace="KX_network"
 	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
@@ -42,7 +43,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic;..\..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
 				StringPooling="true"
 				RuntimeLibrary="0"
@@ -117,7 +118,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic;..\..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="WIN32,_LIB,_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -192,7 +193,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic;..\..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
 				StringPooling="true"
 				RuntimeLibrary="2"
@@ -267,7 +268,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic;..\..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="WIN32,_LIB,_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
@@ -342,7 +343,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic;..\..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="WIN32,_LIB,_DEBUG"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -417,7 +418,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Network;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\GameLogic;..\..\..\..\source\gameengine\Scenegraph"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
 				StringPooling="true"
 				RuntimeLibrary="0"
diff --git a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj
index 8c22733b4e94a4f2ff176bcab0ac3cb92925710f..e6991592d4028f1500219b694ac8a7d9c26cdaa7 100644
--- a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj
+++ b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj
@@ -42,7 +42,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\gameengine\Ketsji;..\..\..\..\..\source\gameengine\Expressions;..\..\..\..\..\source\gameengine\GameLogic;..\..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
 				MinimalRebuild="false"
 				BasicRuntimeChecks="3"
@@ -110,7 +110,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\gameengine\Ketsji;..\..\..\..\..\source\gameengine\Expressions;..\..\..\..\..\source\gameengine\GameLogic;..\..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
 				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
@@ -176,7 +176,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\gameengine\Ketsji;..\..\..\..\..\source\gameengine\Expressions;..\..\..\..\..\source\gameengine\GameLogic;..\..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
 				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
@@ -243,7 +243,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\gameengine\Ketsji;..\..\..\..\..\source\gameengine\Expressions;..\..\..\..\..\source\gameengine\GameLogic;..\..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
 				MinimalRebuild="false"
 				BasicRuntimeChecks="3"
@@ -312,7 +312,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\gameengine\Ketsji;..\..\..\..\..\source\gameengine\Expressions;..\..\..\..\..\source\gameengine\GameLogic;..\..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
 				MinimalRebuild="false"
 				BasicRuntimeChecks="3"
@@ -380,7 +380,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
+				AdditionalIncludeDirectories="..\..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\gameengine\Ketsji;..\..\..\..\..\source\gameengine\Expressions;..\..\..\..\..\source\gameengine\GameLogic;..\..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
 				RuntimeLibrary="2"
 				UsePrecompiledHeader="0"
@@ -430,6 +430,10 @@
 			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
+			<File
+				RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdGraphicController.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdPhysicsController.cpp"
 				>
@@ -444,6 +448,10 @@
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
+			<File
+				RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdGraphicController.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\..\..\source\gameengine\Physics\Bullet\CcdPhysicsController.h"
 				>
diff --git a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj
index 582aed500acedcf56daa236698130ec887b8ba13..5441c5bd4f1147518c49510eec163baaeee1af8a 100644
--- a/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj
+++ b/projectfiles_vc9/gameengine/physics/PHY_Physics/PHY_Physics.vcproj
@@ -4,6 +4,7 @@
 	Version="9,00"
 	Name="PHY_Physics"
 	ProjectGUID="{E109F1A5-FDD3-4F56-A1C4-96867EEA4C5B}"
+	RootNamespace="PHY_Physics"
 	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
@@ -469,6 +470,14 @@
 			Name="Source Files"
 			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
 			>
+			<File
+				RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IController.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IGraphicController.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IMotionState.cpp"
 				>
@@ -494,6 +503,14 @@
 				RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_DynamicTypes.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IController.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IGraphicController.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\..\source\gameengine\Physics\common\PHY_IMotionState.h"
 				>
diff --git a/projectfiles_vc9/gameengine/rasterizer/RAS_rasterizer.vcproj b/projectfiles_vc9/gameengine/rasterizer/RAS_rasterizer.vcproj
index 924babfbd2159989b5a60c87ad54259ebdc6aaef..dde8714507a63cf25e0a483ae17933994a1d4aad 100644
--- a/projectfiles_vc9/gameengine/rasterizer/RAS_rasterizer.vcproj
+++ b/projectfiles_vc9/gameengine/rasterizer/RAS_rasterizer.vcproj
@@ -4,6 +4,7 @@
 	Version="9,00"
 	Name="RAS_rasterizer"
 	ProjectGUID="{51FB3D48-2467-4BFA-A321-D848252B437E}"
+	RootNamespace="RAS_rasterizer"
 	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
@@ -42,7 +43,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\..\lib\windows\python\include\python2.5"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\SceneGraph;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_GLEXT"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -117,7 +118,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\SceneGraph;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
 				StringPooling="true"
 				RuntimeLibrary="2"
@@ -192,7 +193,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\..\lib\windows\python\include\python2.5"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\SceneGraph;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_GLEXT"
 				StringPooling="true"
 				RuntimeLibrary="0"
@@ -267,7 +268,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\SceneGraph;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
@@ -342,7 +343,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\..\lib\windows\python\include\python2.5"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\SceneGraph;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_GLEXT"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -417,7 +418,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\..\lib\windows\python\include\python2.5"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\SceneGraph;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\makesdna"
 				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_GLEXT"
 				StringPooling="true"
 				RuntimeLibrary="0"
diff --git a/projectfiles_vc9/gameengine/rasterizer/openglrasterizer/RAS_openglrasterizer.vcproj b/projectfiles_vc9/gameengine/rasterizer/openglrasterizer/RAS_openglrasterizer.vcproj
index 155290e5e391e2888d9c3f0627dc69033df0b2e8..09b87f41ddf7c4c3d189a86c110deabe3ba68672 100644
--- a/projectfiles_vc9/gameengine/rasterizer/openglrasterizer/RAS_openglrasterizer.vcproj
+++ b/projectfiles_vc9/gameengine/rasterizer/openglrasterizer/RAS_openglrasterizer.vcproj
@@ -4,6 +4,7 @@
 	Version="9,00"
 	Name="RAS_openglrasterizer"
 	ProjectGUID="{AB590CED-F71F-4A17-A89B-18583ECD633D}"
+	RootNamespace="RAS_openglrasterizer"
 	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
@@ -42,7 +43,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\blender\gpu"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\source\blender\gpu;..\..\..\..\source\gameengine\Ketsji;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\blenlib"
 				PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
@@ -117,7 +118,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\blender\gpu"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\source\blender\gpu;..\..\..\..\source\gameengine\Ketsji;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\blenlib"
 				PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_GLEXT"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -192,7 +193,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\blender\gpu"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\source\blender\gpu;..\..\..\..\source\gameengine\Ketsji;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\blenlib"
 				PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
 				StringPooling="true"
 				RuntimeLibrary="2"
@@ -267,7 +268,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\blender\gpu"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\source\blender\gpu;..\..\..\..\source\gameengine\Ketsji;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\blenlib"
 				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_GLEXT"
 				StringPooling="true"
 				RuntimeLibrary="0"
@@ -342,7 +343,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\blender\gpu"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\source\blender\gpu;..\..\..\..\source\gameengine\Ketsji;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\blenlib"
 				PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_GLEXT"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -417,7 +418,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\blender\gpu"
+				AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\source\gameengine\SceneGraph;..\..\..\..\source\blender\gpu;..\..\..\..\source\gameengine\Ketsji;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\blenlib"
 				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_GLEXT"
 				StringPooling="true"
 				RuntimeLibrary="0"
diff --git a/projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj b/projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj
index 9c63f6258202e0afcef354abdbfaa45f83e36e8f..95e61cc4af894513a256b11c940979c48e7b49ea 100644
--- a/projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj
+++ b/projectfiles_vc9/gameengine/scenegraph/SG_SceneGraph.vcproj
@@ -4,6 +4,7 @@
 	Version="9,00"
 	Name="SG_SceneGraph"
 	ProjectGUID="{09222F5E-1625-4FF3-A89A-384D16875EE5}"
+	RootNamespace="SG_SceneGraph"
 	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
@@ -509,6 +510,10 @@
 				RelativePath="..\..\..\source\gameengine\SceneGraph\SG_Controller.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\gameengine\SceneGraph\SG_DList.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\gameengine\SceneGraph\SG_IObject.h"
 				>
@@ -521,6 +526,10 @@
 				RelativePath="..\..\..\source\gameengine\SceneGraph\SG_ParentRelation.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\..\source\gameengine\SceneGraph\SG_QList.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\..\source\gameengine\SceneGraph\SG_Spatial.h"
 				>
diff --git a/projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj b/projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj
index 232001c1012854d17bbfb0a2dce02049217afc27..a248e20481a84362a873b65c4074f4aff1eb6992 100644
--- a/projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj
+++ b/projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj
@@ -126,7 +126,6 @@
 				ProgramDataBaseFileName="..\..\..\..\build\msvc_9\source\gameengine\videotexture\"
 				WarningLevel="2"
 				Detect64BitPortabilityProblems="false"
-				DebugInformationFormat="0"
 				CompileAs="0"
 				ShowIncludes="false"
 			/>
diff --git a/release/scripts/3ds_export.py b/release/scripts/3ds_export.py
index 54e1ea3db331c39853c5f35c5c96d3da3cf70802..87680bce1b0cb0b236c1180b54ddb2b53c7a2326 100644
--- a/release/scripts/3ds_export.py
+++ b/release/scripts/3ds_export.py
@@ -7,7 +7,7 @@ Group: 'Export'
 Tooltip: 'Export to 3DS file format (.3ds).'
 """
 
-__author__ = ["Campbell Barton", "Bob Holcomb", "Richard L�rk�ng", "Damien McGinnes", "Mark Stijnman"]
+__author__ = ["Campbell Barton", "Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Mark Stijnman"]
 __url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/")
 __version__ = "0.90a"
 __bpydoc__ = """\
@@ -50,7 +50,10 @@ import Blender
 import bpy
 from BPyMesh import getMeshFromObject
 from BPyObject import getDerivedObjects
-import struct
+try: 
+    import struct
+except: 
+    struct = None
 
 # So 3ds max can open files, limit names to 12 in length
 # this is verry annoying for filenames!
@@ -1009,5 +1012,8 @@ def save_3ds(filename):
 
 
 if __name__=='__main__':
-	Blender.Window.FileSelector(save_3ds, "Export 3DS", Blender.sys.makename(ext='.3ds'))
+    if struct:
+        Blender.Window.FileSelector(save_3ds, "Export 3DS", Blender.sys.makename(ext='.3ds'))
+    else:
+        Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
 # save_3ds('/test_b.3ds')
diff --git a/release/scripts/3ds_import.py b/release/scripts/3ds_import.py
index 028b96336068c81514dfc148415fe7c3ef31615a..bcde82c486958250a82f24231adcf26fa9925ae3 100644
--- a/release/scripts/3ds_import.py
+++ b/release/scripts/3ds_import.py
@@ -133,10 +133,12 @@ import BPyImage
 
 import BPyMessages
 
-import struct
-from struct import calcsize, unpack
+try:
+	from struct import calcsize, unpack
+except:
+	calcsize= unpack= None
+
 
-import os
 
 # If python version is less than 2.4, try to get set stuff from module
 try:
@@ -844,11 +846,13 @@ def load_3ds(filename, PREF_UI= True):
 	# IMPORT_AS_INSTANCE= Blender.Draw.Create(0)
 	IMPORT_CONSTRAIN_BOUNDS= Blender.Draw.Create(10.0)
 	IMAGE_SEARCH= Blender.Draw.Create(1)
+	APPLY_MATRIX= Blender.Draw.Create(0)
 	
 	# Get USER Options
 	pup_block= [\
 	('Size Constraint:', IMPORT_CONSTRAIN_BOUNDS, 0.0, 1000.0, 'Scale the model by 10 until it reacehs the size constraint. Zero Disables.'),\
 	('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\
+	('Transform Fix', APPLY_MATRIX, 'Workaround for object transformations importing incorrectly'),\
 	#('Group Instance', IMPORT_AS_INSTANCE, 'Import objects into a new scene and group, creating an instance in the current scene.'),\
 	]
 	
@@ -861,6 +865,7 @@ def load_3ds(filename, PREF_UI= True):
 	IMPORT_CONSTRAIN_BOUNDS= IMPORT_CONSTRAIN_BOUNDS.val
 	# IMPORT_AS_INSTANCE= IMPORT_AS_INSTANCE.val
 	IMAGE_SEARCH = IMAGE_SEARCH.val
+	APPLY_MATRIX = APPLY_MATRIX.val
 	
 	if IMPORT_CONSTRAIN_BOUNDS:
 		BOUNDS_3DS[:]= [1<<30, 1<<30, 1<<30, -1<<30, -1<<30, -1<<30]
@@ -887,6 +892,8 @@ def load_3ds(filename, PREF_UI= True):
 		if ob.type=='Mesh':
 			me= ob.getData(mesh=1)
 			me.verts.delete([me.verts[0],])
+			if not APPLY_MATRIX:
+				me.transform(ob.matrixWorld.copy().invert())
 	
 	# Done DUMMYVERT
 	"""
@@ -953,7 +960,10 @@ def load_3ds(filename, PREF_UI= True):
 
 DEBUG= False
 if __name__=='__main__' and not DEBUG:
-	Blender.Window.FileSelector(load_3ds, 'Import 3DS', '*.3ds')
+	if calcsize==None:
+		Blender.Draw.PupMenu('Error%t|a full python installation not found') 
+	else:
+		Blender.Window.FileSelector(load_3ds, 'Import 3DS', '*.3ds')
 
 # For testing compatibility
 #load_3ds('/metavr/convert/vehicle/truck_002/TruckTanker1.3DS', False)
@@ -961,6 +971,7 @@ if __name__=='__main__' and not DEBUG:
 '''
 
 else:
+	import os
 	# DEBUG ONLY
 	TIME= Blender.sys.time()
 	import os
diff --git a/release/scripts/DirectX8Exporter.py b/release/scripts/DirectX8Exporter.py
index b8bdae4de2b5e66f2156e60cb35dbae6de7ebc95..8a0ecaf0eb7641da7d3cf1144a66b9639b5c4c03 100644
--- a/release/scripts/DirectX8Exporter.py
+++ b/release/scripts/DirectX8Exporter.py
@@ -45,7 +45,8 @@ from Blender import Types, Object, NMesh, Material,Armature,Mesh
 from Blender.Mathutils import *
 from Blender import Draw, BGL
 from Blender.BGL import *
-import math
+try: import math
+except: math = None
 
 global mat_flip,index_list,space,bone_list,mat_dict
 global anim,flip_norm,swap_zy,flip_z,speed,ticks,no_light,recalc_norm,Bl_norm
diff --git a/release/scripts/add_mesh_torus.py b/release/scripts/add_mesh_torus.py
index 4f759256497b66dfe9f26c5a545667f9df9bf75f..2941c56420e43555e97e3e822d38a11fa1ad4b68 100644
--- a/release/scripts/add_mesh_torus.py
+++ b/release/scripts/add_mesh_torus.py
@@ -6,7 +6,8 @@ Group: 'AddMesh'
 """
 import BPyAddMesh
 import Blender
-from math import cos, sin, pi
+try: from math import cos, sin, pi
+except: math = None
 
 def add_torus(PREF_MAJOR_RAD, PREF_MINOR_RAD, PREF_MAJOR_SEG, PREF_MINOR_SEG):
 	Vector = Blender.Mathutils.Vector
@@ -61,5 +62,8 @@ def main():
 	
 	BPyAddMesh.add_mesh_simple('Torus', verts, [], faces)
 
-main()
+if cos and sin and pi:
+    main()
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
 
diff --git a/release/scripts/bevel_center.py b/release/scripts/bevel_center.py
index 063c6380483e48e0795d0529ed9db40cf5cf242f..637ed08127fb62e08a8bf7c622589220bf1ac769 100644
--- a/release/scripts/bevel_center.py
+++ b/release/scripts/bevel_center.py
@@ -1,5 +1,5 @@
 #!BPY
-# coding: utf-8
+# -*- coding: utf-8 -*-
 """ Registration info for Blender menus
 Name: 'Bevel Center'
 Blender: 243
diff --git a/release/scripts/bpymodules/dxfLibrary.py b/release/scripts/bpymodules/dxfLibrary.py
index 96caa50cc416af9d777c644f8c1f7bb7a0dc0349..55907e03bc13c63d76061bc95eb1b9aef260ee37 100644
--- a/release/scripts/bpymodules/dxfLibrary.py
+++ b/release/scripts/bpymodules/dxfLibrary.py
@@ -1,6 +1,6 @@
 #dxfLibrary.py : provides functions for generating DXF files
 # --------------------------------------------------------------------------
-__version__ = "v1.28beta - 2008.12.13"
+__version__ = "v1.29beta - 2008.12.28"
 __author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
 __license__ = "GPL"
 __url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
@@ -18,9 +18,11 @@ IDEAs:
 -
 
 TODO:
-- add support for SPLINEs
+- add support for SPLINEs, (bad idea, cause DXF r14 object :(
 
 History
+v1.29 - 2008.12.28 by Yorik
+- modif POLYLINE to support bulge segments
 v1.28 - 2008.12.13 by Steeve/BlenderArtists
 - bugfix for EXTMIN/EXTMAX to suit Cycas-CAD
 v1.27 - 2008.10.07 by migius
@@ -297,41 +299,64 @@ class Line(_Entity):
 #-----------------------------------------------
 class PolyLine(_Entity):
 	def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common):
+		#width = number, or width = list [width_start=None, width_end=None]
+		#for 2d-polyline: points = [ [x, y, z, width_start=None, width_end=None, bulge=0 or None], ...]
+		#for 3d-polyline: points = [ [x, y, z], ...]
+		#for polyface: points = [points_list, faces_list]
 		_Entity.__init__(self,**common)
 		self.points=points
 		self.org_point=org_point
 		self.flag=flag
-		if self.flag==64:
+		self.polyface = False
+		self.polyline2d = False
+		self.faces = [] # dummy value
+		self.width= None # dummy value
+		if self.flag & POLYFACE_MESH:
+			self.polyface=True
 			self.points=points[0]
 			self.faces=points[1]
 			self.p_count=len(self.points)
 			self.f_count=len(self.faces)
-		self.width=width
+		elif not self.flag & POLYLINE_3D:
+			self.polyline2d = True
+			if width:
+				if type(width)!='list':
+					width=[width,width]
+				self.width=width
 
 	def __str__(self):
 		result= '  0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.flag)
 		#print 'deb: self._common()', self._common() #----------
 		result+=' 66\n1\n'
 		result+='%s\n' %_point(self.org_point)
-		if self.flag==64:
+		if self.polyface:
 			result+=' 71\n%s\n' %self.p_count
 			result+=' 72\n%s\n' %self.f_count
+		elif self.polyline2d:
+			if self.width!=None: result+=' 40\n%s\n 41\n%s\n' %(self.width[0],self.width[1])
 		for point in self.points:
 			result+='  0\nVERTEX\n'
 			result+='  8\n%s\n' %self.layer
-			result+='%s\n' %_point(point)
-			if self.flag==64: result+=' 70\n192\n'
-			if self.width: result+=' 40\n%s\n 41\n%s\n' %(self.width,self.width)
-		if self.flag==64:
-			for face in self.faces:
-				result+='  0\nVERTEX\n'
-				result+='  8\n%s\n' %self.layer
-				result+='%s\n' %_point(self.org_point)
-				result+=' 70\n128\n'
-				result+=' 71\n%s\n' %face[0]
-				result+=' 72\n%s\n' %face[1]
-				result+=' 73\n%s\n' %face[2]
-				if len(face)==4: result+=' 74\n%s\n' %face[3]
+			result+='%s\n' %_point(point[0:2])
+			if self.polyface:
+				result+=' 70\n192\n'
+			elif self.polyline2d:
+				if len(point)>4:
+					width1, width2 = point[3], point[4]
+					if width1!=None: result+=' 40\n%s\n' %width1
+					if width2!=None: result+=' 41\n%s\n' %width2
+				if len(point)==6:
+					bulge = point[5]
+					if bulge: result+=' 42\n%s\n' %bulge
+		for face in self.faces:
+			result+='  0\nVERTEX\n'
+			result+='  8\n%s\n' %self.layer
+			result+='%s\n' %_point(self.org_point)
+			result+=' 70\n128\n'
+			result+=' 71\n%s\n' %face[0]
+			result+=' 72\n%s\n' %face[1]
+			result+=' 73\n%s\n' %face[2]
+			if len(face)==4: result+=' 74\n%s\n' %face[3]
 		result+='  0\nSEQEND\n'
 		result+='  8\n%s\n' %self.layer
 		return result
@@ -711,5 +736,5 @@ def test():
 if __name__=='__main__':
 	if not copy:
 		Draw.PupMenu('Error%t|This script requires a full python install')
-	main()
+	else: main()
 	
\ No newline at end of file
diff --git a/release/scripts/bpymodules/paths_svg2obj.py b/release/scripts/bpymodules/paths_svg2obj.py
index d51fe74190d44216e7345481796515dde963889a..6bab6dcbfd8b0086f6e44454e3403a9b3f710fb4 100644
--- a/release/scripts/bpymodules/paths_svg2obj.py
+++ b/release/scripts/bpymodules/paths_svg2obj.py
@@ -1,7 +1,7 @@
 # -*- coding: latin-1 -*-
 """
-SVG 2 OBJ translater, 0.5.9n
-Copyright (c) jm soler juillet/novembre 2004-february 2009, 
+SVG 2 OBJ translater, 0.5.9o
+Copyright (c) jm soler juillet/novembre 2004-april 2009, 
 # ---------------------------------------------------------------
     released under GNU Licence 
     for the Blender 2.42 Python Scripts Bundle.
@@ -255,7 +255,7 @@ Changelog:
               - removed  all debug statements
               - correction of a zero division error in the calc_arc function.
 
-		  0.5.9f: - 2007/15/7 
+     0.5.9f: - 2007/15/7 
               - Correction de plusieurs bugs sur l'attributions des couleurs et le nommage 
                 des courbes
 
@@ -266,6 +266,8 @@ Changelog:
      0.5.9k : - 14/01/2009 
      0.5.9l : - 31/01/2009 
      0.5.9n : - 01/02/2009
+     0.5.9o : - 04/04/2009, remove pattern if it made with path.
+
 
 ==================================================================================   
 =================================================================================="""
@@ -280,6 +282,7 @@ LAST_ID=''
 LAST_COLOR=[0.0,0.0,0.0,0.0]
 SEPARATE_CURVES=0
 USE_COLORS=0
+PATTERN=0
 
 SVGCOLORNAMELIST={ 'aliceblue':[240, 248, 255] ,'antiquewhite':[250, 235, 215]
 ,'aqua':[ 0, 255, 255], 'aquamarine':[127, 255, 212]
@@ -787,6 +790,7 @@ def polygon(prp):
 		D.append('Z')
 	return D
 
+
 #--------------------
 # 0.5.8, to remove exec 
 #--------------------
@@ -1462,13 +1466,13 @@ def collect_ATTRIBUTS(data):
 # --------------------------------------------
 def build_HIERARCHY(t):
 	global CP, curves, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
-	global LAST_ID
+	global LAST_ID, PATTERN
 	TRANSFORM=0
 	t=t.replace('\t',' ')
 	while t.find('  ')!=-1: t=t.replace('  ',' ')
 	n0=0      
 	t0=t1=0
-	baliste=[]
+	#baliste=[]
 	balisetype=['?','?','/','/','!','!']
 	BALISES=['D',  #DECL_TEXTE',
 						'D',  #DECL_TEXTE',
@@ -1490,26 +1494,37 @@ def build_HIERARCHY(t):
 		if t0>-1 and t1>-1:
 			if t[t0+1] in balisetype:
 				b=balisetype.index(t[t0+1])
+				
 				if t[t0+2]=='-': 
 					b=balisetype.index(t[t0+1])+1
+					
 				balise=BALISES[b]
+				
 				if b==2:
 					parent=STACK.pop(-1)
 					if parent!=None and TRANSFORM>0:
 						TRANSFORM-=1
+						
 			elif t[t1-1] in balisetype:
 				balise=BALISES[balisetype.index(t[t1-1])+1]
+				
 			else:
 				t2=t.find(' ',t0)  
 				if t2>t1: t2=t1
 				ouvrante=1
 				NOM=t[t0+1:t2]
+				
+					
 				if '</'+NOM in t: #.find('</'+NOM)>-1:
 					balise=BALISES[-1]
+					if NOM=='pattern' and not PATTERN:
+						t1=t.find('</'+NOM+'>',t0)+len('</'+NOM+'>')
+						balise=BALISES[-3]
 				else:
 					balise=BALISES[-2]
 					
 			if balise=='E' or balise=='O':
+					
 				proprietes=collect_ATTRIBUTS(t[t0:t1+ouvrante])
 				
 				if  'id' in proprietes:
@@ -1532,6 +1547,11 @@ def build_HIERARCHY(t):
 					# 0.5.8, to remove exec 
 					#--------------------
 					D=OTHERSSHAPES[proprietes['TYPE']](proprietes)
+					
+				#elif proprietes['TYPE'] in ['pattern']:
+				#	print 'pattern'	
+				#	D=''
+					
 				CP=[0.0,0.0]	
 				if len(D)>0:
 					cursor=0
@@ -1567,7 +1587,7 @@ def build_HIERARCHY(t):
 
 def scan_FILE(nom):
 	global CP, curves, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
-	global SEPARATE_CURVES, USE_COLORS
+	global SEPARATE_CURVES, USE_COLORS, PATTERN
 	
 	dir,name=split(nom)
 	name=name.split('.')
@@ -1583,13 +1603,14 @@ def scan_FILE(nom):
 			togAS = Blender.Draw.Create(0)
 			togSP = Blender.Draw.Create(0)
 			togCOL = Blender.Draw.Create(0)
+			Pattern= Blender.Draw.Create(0)
 			block=[\
 				("Clamp Width 1",	togW,  "Rescale the import with a Width of one unit"),\
 				("Clamp Height 1",	togH,  "Rescale the import with a Heightof one unit"),\
 				("No Rescaling",	togAS, "No rescaling, the result can be very large"),\
 				("Separate Curves", togSP, "Create an object for each curve, Slower. May manage colors"),\
-				("Import Colors",	togCOL, "try to import color if the path is set as 'fill'. Only With separate option")]
-
+				("Import Colors",	togCOL, "try to import color if the path is set as 'fill'. Only With separate option"),\
+ 				("Import Patterns",	Pattern, "import pattern content if it is made with paths.")]
 			retval = Blender.Draw.PupBlock("Import Options", block)
 			if  togW.val: scale_=1
 			elif togH.val: 	scale_=2
@@ -1598,6 +1619,8 @@ def scan_FILE(nom):
 			if  togSP.val: SEPARATE_CURVES=1	
 
 			if  togCOL.val and SEPARATE_CURVES : USE_COLORS=1	
+				
+			if	Pattern.val : PATTERN =1
 											
 		t1=Blender.sys.time()
 		# 0.4.1 : to avoid to use sax and the xml  
@@ -1625,4 +1648,4 @@ def functionSELECT(nom):
 
 
 if __name__=='__main__':
-	Blender.Window.FileSelector (functionSELECT, 'SELECT an .SVG FILE', '*.svg')
+	Blender.Window.FileSelector (functionSELECT, 'SELECT an .SVG FILE', '*.svg')
\ No newline at end of file
diff --git a/release/scripts/console.py b/release/scripts/console.py
index 0e46f41f581be7cee12bf2a5e6f8d9123c6ec3b5..c6ae22a86f57dd0d5a9c18e83700dc004ed75a8b 100644
--- a/release/scripts/console.py
+++ b/release/scripts/console.py
@@ -708,20 +708,23 @@ def draw_gui():
 	# Fixed margin. use a margin since 0 margin can be hard to seewhen close to a crt's edge.
 	margin = 4
 	
+	# Convenience
+	FNT_NAME, FNT_HEIGHT = __FONT_SIZES__[__FONT_SIZE__]
+	
 	# Draw cursor location colour
 	if __CONSOLE_LINE_OFFSET__ == 0:
-		cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], __FONT_SIZES__[__FONT_SIZE__][0])
+		cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], FNT_NAME)
 		BGL.glColor3f(0.8, 0.2, 0.2)
 		if cmd2curWidth == 0:
-			BGL.glRecti(margin,2,margin+2, __FONT_SIZES__[__FONT_SIZE__][1]+2)
+			BGL.glRecti(margin,2,margin+2, FNT_HEIGHT+2)
 		else:
-			BGL.glRecti(margin + cmd2curWidth-2,2, margin+cmd2curWidth, __FONT_SIZES__[__FONT_SIZE__][1]+2)
+			BGL.glRecti(margin + cmd2curWidth-2,2, margin+cmd2curWidth, FNT_HEIGHT+2)
 	
 	BGL.glColor3f(1,1,1)
 	# Draw the set of cammands to the buffer
 	consoleLineIdx = __CONSOLE_LINE_OFFSET__ + 1
 	wrapLineIndex = 0
-	while consoleLineIdx < len(cmdBuffer) and  __CONSOLE_RECT__[3] > (consoleLineIdx - __CONSOLE_LINE_OFFSET__) * __FONT_SIZES__[__FONT_SIZE__][1]:
+	while consoleLineIdx < len(cmdBuffer) and  __CONSOLE_RECT__[3] > (consoleLineIdx - __CONSOLE_LINE_OFFSET__) * FNT_HEIGHT:
 		if cmdBuffer[-consoleLineIdx].type == 0:
 			BGL.glColor3f(1, 1, 1)
 		elif cmdBuffer[-consoleLineIdx].type == 1:
@@ -734,53 +737,41 @@ def draw_gui():
 			BGL.glColor3f(1, 1, 0)
 		
 		if consoleLineIdx == 1: # user input
-			BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
-			Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])		
-		else:
-			BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
-			Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
-
-		# Wrapping is totally slow, can even hang blender - dont do it!
-		'''
-		if consoleLineIdx == 1: # NEVER WRAP THE USER INPUT
-			BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
-			# BUG, LARGE TEXT DOSENT DISPLAY
-			Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
-			
-		
-		else: # WRAP?
-			# LINE WRAP
-			if Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0]) >  __CONSOLE_RECT__[2]:
+			BGL.glRasterPos2i(margin, (FNT_HEIGHT * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
+			Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)		
+		else: # WRAP
+			lwid = Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)
+			if margin + lwid >  __CONSOLE_RECT__[2]:
 				wrapLineList = []
-				copyCmd = [cmdBuffer[-consoleLineIdx].cmd, '']
-				while copyCmd != ['','']:
-					while margin + Draw.GetStringWidth(copyCmd[0], __FONT_SIZES__[__FONT_SIZE__][0]) > __CONSOLE_RECT__[2]:
-						#print copyCmd
-						copyCmd[1] = '%s%s'% (copyCmd[0][-1], copyCmd[1]) # Add the char on the end
-						copyCmd[0] = copyCmd[0][:-1]# remove last chat
-					
-					# Now we have copyCmd[0] at a good length we can print it.					
-					if copyCmd[0] != '':
-						wrapLineList.append(copyCmd[0])
-					
-					copyCmd[0]=''
-					copyCmd = [copyCmd[1], copyCmd[0]]
-				
+				wtext = cmdBuffer[-consoleLineIdx].cmd
+				wlimit = len(wtext)
+				chunksz = int(( __CONSOLE_RECT__[2] - margin ) / (lwid / len(wtext)))
+				lstart = 0
+				fsize = FNT_NAME
+				while lstart < wlimit:
+					lend = min(lstart+chunksz,wlimit)
+					ttext = wtext[lstart:lend]
+					while lend < wlimit and Draw.GetStringWidth(ttext, fsize) + margin < __CONSOLE_RECT__[2]:
+						lend += 1
+						ttext = wtext[lstart:lend]
+					while lend > lstart+1 and Draw.GetStringWidth(ttext, fsize) + margin > __CONSOLE_RECT__[2]:
+						lend -= 1
+						ttext = wtext[lstart:lend]
+					wrapLineList.append(ttext)
+					lstart = lend 
 				# Now we have a list of lines, draw them (OpenGLs reverse ordering requires this odd change)
 				wrapLineList.reverse()
 				for wline in wrapLineList:
-					BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1]*((consoleLineIdx-__CONSOLE_LINE_OFFSET__) + wrapLineIndex)) - 8)
-					Draw.Text(wline, __FONT_SIZES__[__FONT_SIZE__][0])
+					BGL.glRasterPos2i(margin, (FNT_HEIGHT*((consoleLineIdx-__CONSOLE_LINE_OFFSET__) + wrapLineIndex)) - 8)
+					Draw.Text(wline, FNT_NAME)
 					wrapLineIndex += 1
-				wrapLineIndex-=1 # otherwise we get a silly extra line.
+				wrapLineIndex-=1 # otherwise we get a silly extra line.	
 				
 			else: # no wrapping.
 				
-				BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
-				Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
-		'''
+				BGL.glRasterPos2i(margin, (FNT_HEIGHT * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
+				Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)
 		consoleLineIdx += 1
-			
 
 # This recieves the event index, call a function from here depending on the event.
 def handle_button_event(evt):
diff --git a/release/scripts/export_dxf.py b/release/scripts/export_dxf.py
index 061e29b81c79c4f5f3a4a886c15ed32a20a8fbe7..84a173c1e7de8b950d60da328cf8acdc055a934b 100644
--- a/release/scripts/export_dxf.py
+++ b/release/scripts/export_dxf.py
@@ -1,14 +1,14 @@
 #!BPY
 
 """
- Name: 'Autodesk DXF (.dxf)'
+ Name: 'Autodesk (.dxf .dwg)'
  Blender: 247
  Group: 'Export'
- Tooltip: 'Export geometry to DXF-r12 (Drawing eXchange Format).'
+ Tooltip: 'Export geometry to Autocad DXF/DWG-r12 (Drawing eXchange Format).'
 """
 
-__version__ = "v1.27beta - 2008.10.07"
-__author__  = "Remigiusz Fiedler (AKA migius)"
+__version__ = "v1.29 - 2009.04.11"
+__author__  = "Remigiusz Fiedler (AKA migius), Alexandros Sigalas (AKA alxarch), Stani Michiels"
 __license__ = "GPL"
 __url__	 = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
 __bpydoc__ ="""The script exports Blender geometry to DXF format r12 version.
@@ -25,8 +25,9 @@ url: %s
 IDEAs:
  - correct normals for POLYLINE-POLYFACE via proper point-order
  - HPGL output for 2d and flattened 3d content
-		
+
 TODO:
+- export dupligroups and dupliverts as blocks ( option for the user to decide ) 
 - optimize back-faces removal (probably needs matrix transform)
 - optimize POLYFACE routine: remove double-vertices
 - optimize POLYFACE routine: remove unused vertices
@@ -36,6 +37,11 @@ TODO:
 - write drawing extends for automatic view positioning in CAD
 
 History
+v1.29 - 2009.04.11 by migius
+- added DWG support, Stani Michiels idea for binding an extern DXF-DWG-converter 
+v1.28 - 2009.02.05 by alxarch
+- added option to apply modifiers on exported meshes
+- added option to also export duplicates (from dupliverts etc)
 v1.27 - 2008.10.07 by migius
 - exclude Stani's DXF-Library to extern module
 v1.26 - 2008.10.05 by migius
@@ -86,14 +92,98 @@ ______________________________________________________________
 
 
 import Blender
-from Blender import Mathutils, Window, Scene, sys, Draw
+from Blender import Mathutils, Window, Scene, sys, Draw, Mesh
 import BPyMessages
+try: import os
+except: os = None
+try: import subprocess
+except: subprocess = None
+try: import copy
+except: copy = None
+
+#print os.sys.platform
+#print dir(os.sys.version)
 
 #import dxfLibrary
 #reload(dxfLibrary)
-from  dxfLibrary import *
+if copy and os:
+    from  dxfLibrary import *
+    #-------- DWG support ------------------------------------------
+    extCONV_OK = True
+    extCONV = 'DConvertCon.exe'
+    extCONV_PATH = os.path.join(Blender.Get('scriptsdir'),extCONV)
+    if not os.path.isfile(extCONV_PATH):
+        extCONV_OK = False
+        extCONV_TEXT = 'DWG-Exporter: Abort, nothing done!|\
+    Copy first %s into Blender script directory.|\
+    More details in online Help.' %extCONV
+    else:
+        if not os.sys.platform.startswith('win'):
+            # check if Wine installed:   
+            if subprocess.Popen(('which', 'winepath'), stdout=subprocess.PIPE).stdout.read().strip():
+                extCONV_PATH    = 'wine %s'%extCONV_PATH
+            else: 
+                extCONV_OK = False
+                extCONV_TEXT = 'DWG-Exporter: Abort, nothing done!|\
+    The external DWG-converter (%s) needs Wine installed on your system.|\
+    More details in online Help.' %extCONV
+    #print 'extCONV_PATH = ', extCONV_PATH
+
 
 
+#-----------------------------------------------------
+def dupTest(object):
+	"""
+	Checks objects for duplicates enabled (any type)
+	object: Blender Object.
+	Returns: Boolean - True if object has any kind of duplicates enabled.
+	"""
+	if (object.enableDupFrames or \
+		object.enableDupGroup or \
+		object.enableDupVerts):
+		return True
+	else:
+		return False
+
+def getObjectsAndDuplis(oblist,MATRICES=False,HACK=False):
+	"""
+	Return a list of real objects and duplicates and optionally their matrices
+	oblist: List of Blender Objects
+	MATRICES: Boolean - Check to also get the objects matrices default=False
+	HACK: Boolean - See note default=False
+	Returns: List of objects or
+			 List of tuples of the form:(ob,matrix) if MATRICES is set to True
+	NOTE: There is an ugly hack here that excludes all objects whose name
+	starts with "dpl_" to exclude objects that are parented to a duplicating
+	object, User must name objects properly if hack is used.
+	"""
+
+	result = []
+	for ob in oblist:
+		if dupTest(ob):
+			dup_obs=ob.DupObjects
+			if len(dup_obs):
+				for dup_ob, dup_mx in dup_obs:
+					if MATRICES:
+						result.append((dup_ob,dup_mx))
+					else:
+						result.append(dup_ob)
+		else:
+			if HACK:
+				if ob.getName()[0:4] != "dpl_":
+					if MATRICES:
+						mx = ob.mat
+						result.append((ob,mx))
+					else:
+						result.append(ob)
+			else:
+				if MATRICES:
+					mx = ob.mat
+					result.append((ob,mx))
+				else:
+					result.append(ob)
+	return result
+
 #-----------------------------------------------------
 def hidden_status(faces, mx_n):
 	#print 'HIDDEN_MODE: caution! not full implemented yet'
@@ -146,9 +236,13 @@ def flatten(points, mw):
 	return points
 
 #-----------------------------------------------------
-def	exportMesh(ob, mx, mx_n):
+def	exportMesh(ob, mx, mx_n,me=None):
 	entities = []
-	me = ob.getData(mesh=1)
+	global APPLY_MODIFIERS
+	if me is None:
+		me = ob.getData(mesh=1)
+	else:
+		me.getFromObject(ob)
 	#me.transform(mx)
 	# above is eventualy faster, but bad, cause
 	# directly transforms origin geometry and write back rounding errors
@@ -209,7 +303,7 @@ def	exportMesh(ob, mx, mx_n):
 				points = [ me_verts[key].co[:3] for key in e]
 				dxfLINE = Line(points)
 				entities.append(dxfLINE)
-				
+
 		else:
 			for e in me.edges:
 				#print 'deb: edge=', e #---------
@@ -257,7 +351,7 @@ def exportCurve(ob, mx):
 	return entities
 
 #-----------------------------------------------------
-def do_export(sel_group, filepath):
+def do_export(export_list, filepath):
 	Window.WaitCursor(1)
 	t = sys.time()
 
@@ -281,22 +375,27 @@ def do_export(sel_group, filepath):
 		m0[2][2]=0.0
 		mw *= m0 #flatten ViewMatrix
 
-	for ob in sel_group:
+	if APPLY_MODIFIERS:
+		tmp_me = Mesh.New('tmp')
+	else:
+		tmp_me = None
+
+	for ob,mx in export_list:
 		entities = []
-		mx = ob.matrix.copy()
+		#mx = ob.matrix.copy()
 		mb = mx.copy()
 		#print 'deb: mb    =\n', mb     #---------
 		#print 'deb: mw0    =\n', mw0     #---------
 		mx_n = mx.rotationPart() * mw0.rotationPart() #trans-matrix for normal_vectors
 		if SCALE_FACTOR!=1.0: mx *= SCALE_FACTOR
 		if FLATTEN:	mx *= mw
-			
+
 		#mx_inv = mx.copy().invert()
 		#print 'deb: mx    =\n', mx     #---------
 		#print 'deb: mx_inv=\n', mx_inv #---------
 
 		if (ob.type == 'Mesh'):
-			entities = exportMesh(ob, mx, mx_n)
+			entities = exportMesh(ob, mx, mx_n,tmp_me)
 		elif (ob.type == 'Curve'):
 			entities = exportCurve(ob, mx)
 
@@ -305,11 +404,30 @@ def do_export(sel_group, filepath):
 			something_ready = True
 
 	if something_ready:
-		d.saveas(filepath)
-		Window.WaitCursor(0)
-		#Draw.PupMenu('DXF Exporter: job finished')
-		print 'exported to %s' % filepath
-		print 'finished in %.2f seconds' % (sys.time()-t)
+		if not OUTPUT_DWG:
+			print 'exporting to %s' % filepath
+			d.saveas(filepath)
+			Window.WaitCursor(0)
+			#Draw.PupMenu('DXF Exporter: job finished')
+			print '  finished in %.2f seconds. -----DONE-----' % (sys.time()-t)
+		else:
+			if not extCONV_OK:
+				Draw.PupMenu(extCONV_TEXT)
+				Window.WaitCursor(False)
+			else:
+				print 'temp. exporting to %s' % filepath
+				d.saveas(filepath)
+				#Draw.PupMenu('DXF Exporter: job finished')
+				#print 'exported to %s' % filepath
+				#print 'finished in %.2f seconds' % (sys.time()-t)
+				filedwg = filepath[:-3]+'dwg'
+				print 'exporting to %s' % filedwg
+				os.system('%s %s  -acad13 -dwg' %(extCONV_PATH,filepath))
+				#os.chdir(cwd)
+				os.remove(filepath)
+				Window.WaitCursor(0)
+				print '  finished in %.2f seconds. -----DONE-----' % (sys.time()-t)
+		
 	else:
 		Window.WaitCursor(0)
 		print "Abort: selected objects dont mach choosen export option, nothing exported!"
@@ -323,8 +441,9 @@ POLYFACES = 1
 FLATTEN = 0
 HIDDEN_MODE = False #filter out hidden lines
 SCALE_FACTOR = 1.0 #optional, can be done later in CAD too
-
-
+APPLY_MODIFIERS = True
+INCLUDE_DUPLIS = False
+OUTPUT_DWG = False #optional save to DWG with extern converter
 
 #-----------------------------------------------------
 def dxf_export_ui(filepath):
@@ -334,9 +453,12 @@ def dxf_export_ui(filepath):
 	POLYFACES,\
 	FLATTEN,\
 	HIDDEN_MODE,\
-	SCALE_FACTOR
+	SCALE_FACTOR,\
+	APPLY_MODIFIERS,\
+	OUTPUT_DWG,\
+	INCLUDE_DUPLIS
 
-	print '\n\nDXF-Export %s -----------------------' %__version__
+	print '\n\nDXF-Export %s -----------START-----------' %__version__
 	#filepath = 'blend_test.dxf'
 	# Dont overwrite
 	if not BPyMessages.Warning_SaveOver(filepath):
@@ -352,19 +474,26 @@ def dxf_export_ui(filepath):
 	PREF_FLATTEN= Draw.Create(FLATTEN)
 	PREF_HIDDEN_MODE= Draw.Create(HIDDEN_MODE)
 	PREF_SCALE_FACTOR= Draw.Create(SCALE_FACTOR)
+	PREF_APPLY_MODIFIERS= Draw.Create(APPLY_MODIFIERS)
+	PREF_INCLUDE_DUPLIS= Draw.Create(INCLUDE_DUPLIS)
 	PREF_HELP= Draw.Create(0)
+	PREF_DWG= Draw.Create(OUTPUT_DWG)
 	block = [\
 	("only selected", PREF_ONLYSELECTED, "export only selected geometry"),\
+	("Apply Modifiers", PREF_APPLY_MODIFIERS, "Apply modifier stack to mesh objects before export"),\
+	("Include Duplis", PREF_INCLUDE_DUPLIS, "Export also Duplicates (dupliverts, dupliframes etc)"),\
 	("global Scale:", PREF_SCALE_FACTOR, 0.001, 1000, "set global Scale factor for exporting geometry"),\
-	("only faces", PREF_ONLYFACES, "from mesh-objects export only faces, otherwise only edges"),\
-	("write POLYFACE", PREF_POLYFACES, "export mesh to POLYFACE, otherwise to 3DFACEs"),\
-	("write POLYLINEs", PREF_POLYLINES, "export curve to POLYLINE, otherwise to LINEs"),\
+	(''),\
+	("export to 3DFaces", PREF_ONLYFACES, "from mesh-objects export only faces, otherwise only edges"),\
+	("mesh to POLYFACE", PREF_POLYFACES, "export mesh to POLYFACE, otherwise to 3DFACEs"),\
+	("curves to POLYLINEs", PREF_POLYLINES, "export curve to POLYLINE, otherwise to LINEs"),\
 	("3D-View to Flat", PREF_FLATTEN, "flatten geometry according current 3d-View"),\
 	("Hidden Mode", PREF_HIDDEN_MODE, "filter out hidden lines"),\
-	#(''),\
 	("online Help", PREF_HELP, "calls DXF-Exporter Manual Page on Wiki.Blender.org"),\
+	(''),\
+	("DXF->DWG", PREF_DWG, "writes DWG with extern converter"),\
 	]
-	
+
 	if not Draw.PupBlock("DXF-Exporter %s" %__version__[:10], block): return
 
 	if PREF_HELP.val!=0:
@@ -372,7 +501,7 @@ def dxf_export_ui(filepath):
 			import webbrowser
 			webbrowser.open('http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf')
 		except:
-			Draw.PupMenu('DXF Exporter: %t|no connection to manual-page on Blender-Wiki!	try:|\
+			Draw.PupMenu('DXF Exporter: %t|no connection to manual-page on Blender-Wiki! try:|\
 http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf')
 		return
 
@@ -383,12 +512,14 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf')
 	FLATTEN = PREF_FLATTEN.val
 	HIDDEN_MODE = PREF_HIDDEN_MODE.val
 	SCALE_FACTOR = PREF_SCALE_FACTOR.val
-
+	OUTPUT_DWG = PREF_DWG.val
+	
 	sce = Scene.GetCurrent()
 	if ONLYSELECTED: sel_group = sce.objects.selected
 	else: sel_group = sce.objects
+	export_list = getObjectsAndDuplis(sel_group,MATRICES=True)
 
-	if sel_group: do_export(sel_group, filepath)
+	if export_list: do_export(export_list, filepath)
 	else:
 		print "Abort: selection was empty, no object to export!"
 		Draw.PupMenu('DXF Exporter:   nothing exported!|empty selection!')
@@ -398,10 +529,8 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf')
 
 #-----------------------------------------------------
 if __name__=='__main__':
-	#main()
-	if not copy:
-		Draw.PupMenu('Error%t|This script requires a full python install')
-	Window.FileSelector(dxf_export_ui, 'EXPORT DXF', sys.makename(ext='.dxf'))
-	
-	
-	
\ No newline at end of file
+    #main()
+    if copy and os and subprocess:
+        Window.FileSelector(dxf_export_ui, 'EXPORT DXF', sys.makename(ext='.dxf'))
+    else:
+        Draw.PupMenu('Error%t|This script requires a full python install')
diff --git a/release/scripts/export_fbx.py b/release/scripts/export_fbx.py
index 730776bf1b8ff9a2c0a6fd02f069456e2045bc1b..707ab9ebbb731b9bd39754d38748da3e053851a4 100644
--- a/release/scripts/export_fbx.py
+++ b/release/scripts/export_fbx.py
@@ -1,13 +1,13 @@
 #!BPY
 """
 Name: 'Autodesk FBX (.fbx)...'
-Blender: 244
+Blender: 249
 Group: 'Export'
 Tooltip: 'Selection to an ASCII Autodesk FBX '
 """
 __author__ = "Campbell Barton"
 __url__ = ['www.blender.org', 'blenderartists.org']
-__version__ = "1.1"
+__version__ = "1.2"
 
 __bpydoc__ = """\
 This script is an exporter to the FBX file format.
@@ -93,8 +93,8 @@ def copy_images(dest_dir, textures):
 		dest_dir += Blender.sys.sep
 	
 	image_paths = set()
-	for img in textures:
-		image_paths.add(Blender.sys.expandpath(img.filename))
+	for tex in textures:
+		image_paths.add(Blender.sys.expandpath(tex.filename))
 	
 	# Now copy images
 	copyCount = 0
@@ -157,14 +157,29 @@ def increment_string(t):
 # todo - Disallow the name 'Scene' and 'blend_root' - it will bugger things up.
 def sane_name(data, dct):
 	#if not data: return None
-	name = data.name
+	
+	if type(data)==tuple: # materials are paired up with images
+		data, other = data
+		use_other = True
+	else:
+		other = None
+		use_other = False
+	
+	if data:	name = data.name
+	else:		name = None
+	orig_name = name
+	
+	if other:
+		orig_name_other = other.name
+		name = '%s #%s' % (name, orig_name_other)
+	else:
+		orig_name_other = None
 	
 	# dont cache, only ever call once for each data type now,
 	# so as to avoid namespace collision between types - like with objects <-> bones
 	#try:		return dct[name]
 	#except:		pass
 	
-	orig_name = name
 	if not name:
 		name = 'unnamed' # blank string, ASKING FOR TROUBLE!
 	else:
@@ -173,7 +188,11 @@ def sane_name(data, dct):
 	
 	while name in dct.itervalues():	name = increment_string(name)
 	
-	dct[orig_name] = name
+	if use_other: # even if other is None - orig_name_other will be a string or None
+		dct[orig_name, orig_name_other] = name
+	else:
+		dct[orig_name] = name
+		
 	return name
 
 def sane_obname(data):		return sane_name(data, sane_name_mapping_ob)
@@ -511,7 +530,7 @@ def write(filename, batch_objects = None, \
 	if time:
 		curtime = time.localtime()[0:6]
 	else:
-		curtime = [0,0,0,0,0,0]
+		curtime = (0,0,0,0,0,0)
 	# 
 	file.write(\
 '''FBXHeaderExtension:  {
@@ -983,7 +1002,7 @@ def write(filename, batch_objects = None, \
 		#eDIRECTIONAL
 		#eSPOT
 		light_type = light.type
-		if light_type > 3: light_type = 0
+		if light_type > 2: light_type = 1 # hemi and area lights become directional
 		
 		mode = light.mode
 		if mode & Blender.Lamp.Modes.RayShadow or mode & Blender.Lamp.Modes.Shadows:
@@ -1333,11 +1352,13 @@ def write(filename, batch_objects = None, \
 		me = my_mesh.blenData
 		
 		# if there are non NULL materials on this mesh
-		if [mat for mat in my_mesh.blenMaterials if mat]: 	do_materials = True
-		else:												do_materials = False
+		if my_mesh.blenMaterials:	do_materials = True
+		else:						do_materials = False
 		
 		if my_mesh.blenTextures:	do_textures = True
-		else:						do_textures = False			
+		else:						do_textures = False	
+		
+		do_uvs = me.faceUV
 		
 		
 		file.write('\n\tModel: "Model::%s", "Mesh" {' % my_mesh.fbxName)
@@ -1385,22 +1406,18 @@ def write(filename, batch_objects = None, \
 				else:				file.write(',%i,%i,%i,%i' % fi )
 			i+=1
 		
-		ed_val = [None, None]
-		LOOSE = Blender.Mesh.EdgeFlags.LOOSE
+		file.write('\n\t\tEdges: ')
+		i=-1
 		for ed in me.edges:
-			if ed.flag & LOOSE:
-				ed_val[0] = ed.v1.index
-				ed_val[1] = -(ed.v2.index+1)
 				if i==-1:
-					file.write('%i,%i' % tuple(ed_val) )
+					file.write('%i,%i' % (ed.v1.index, ed.v2.index))
 					i=0
 				else:
 					if i==13:
 						file.write('\n\t\t')
 						i=0
-					file.write(',%i,%i' % tuple(ed_val) )
+					file.write(',%i,%i' % (ed.v1.index, ed.v2.index))
 				i+=1
-		del LOOSE
 		
 		file.write('\n\t\tGeometryVersion: 124')
 		
@@ -1423,6 +1440,51 @@ def write(filename, batch_objects = None, \
 			i+=1
 		file.write('\n\t\t}')
 		
+		# Write Face Smoothing
+		file.write('''
+		LayerElementSmoothing: 0 {
+			Version: 102
+			Name: ""
+			MappingInformationType: "ByPolygon"
+			ReferenceInformationType: "Direct"
+			Smoothing: ''')
+		
+		i=-1
+		for f in me.faces:
+			if i==-1:
+				file.write('%i' % f.smooth);	i=0
+			else:
+				if i==54:
+					file.write('\n			 ');	i=0
+				file.write(',%i' % f.smooth)
+			i+=1
+		
+		file.write('\n\t\t}')
+		
+		# Write Edge Smoothing
+		file.write('''
+		LayerElementSmoothing: 0 {
+			Version: 101
+			Name: ""
+			MappingInformationType: "ByEdge"
+			ReferenceInformationType: "Direct"
+			Smoothing: ''')
+		
+		SHARP = Blender.Mesh.EdgeFlags.SHARP
+		i=-1
+		for ed in me.edges:
+			if i==-1:
+				file.write('%i' % ((ed.flag&SHARP)!=0));	i=0
+			else:
+				if i==54:
+					file.write('\n			 ');	i=0
+				file.write(',%i' % ((ed.flag&SHARP)!=0))
+			i+=1
+		
+		file.write('\n\t\t}')
+		del SHARP
+		
+		
 		# Write VertexColor Layers
 		# note, no programs seem to use this info :/
 		collayers = []
@@ -1475,7 +1537,7 @@ def write(filename, batch_objects = None, \
 		
 		# Write UV and texture layers.
 		uvlayers = []
-		if me.faceUV:
+		if do_uvs:
 			uvlayers = me.getUVLayerNames()
 			uvlayer_orig = me.activeUVLayer
 			for uvindex, uvlayer in enumerate(uvlayers):
@@ -1538,13 +1600,13 @@ def write(filename, batch_objects = None, \
 					if len(my_mesh.blenTextures) == 1:
 						file.write('0')
 					else:
-						#texture_mapping_local = {None:0}
 						texture_mapping_local = {None:-1}
 						
 						i = 0 # 1 for dummy
 						for tex in my_mesh.blenTextures:
-							texture_mapping_local[tex] = i
-							i+=1
+							if tex: # None is set above
+								texture_mapping_local[tex] = i
+								i+=1
 						
 						i=-1
 						for f in me.faces:
@@ -1594,32 +1656,32 @@ def write(filename, batch_objects = None, \
 				file.write('0')
 			else:
 				# Build a material mapping for this 
-				#material_mapping_local = [0] * 16 # local-index : global index.
-				material_mapping_local = [-1] * 16 # local-index : global index.
-				i= 0 # 1
-				for j, mat in enumerate(my_mesh.blenMaterials):
-					if mat:
-						material_mapping_local[j] = i
-						i+=1
-					# else leave as -1
+				material_mapping_local = {} # local-mat & tex : global index.
+				
+				for j, mat_tex_pair in enumerate(my_mesh.blenMaterials):
+					material_mapping_local[mat_tex_pair] = j
 				
 				len_material_mapping_local = len(material_mapping_local)
 				
+				mats = my_mesh.blenMaterialList
+				
 				i=-1
 				for f in me.faces:
-					f_mat = f.mat
-					if f_mat >= len_material_mapping_local:
-						f_mat = 0
+					try:	mat = mats[f.mat]
+					except:mat = None
+					
+					if do_uvs: tex = f.image # WARNING - MULTI UV LAYER IMAGES NOT SUPPORTED :/
+					else: tex = None
 					
 					if i==-1:
 						i=0
-						file.write( '%s' % (material_mapping_local[f_mat]))
+						file.write( '%s' % (material_mapping_local[mat, tex])) # None for mat or tex is ok
 					else:
 						if i==55:
 							file.write('\n\t\t\t\t')
 							i=0
 						
-						file.write(',%s' % (material_mapping_local[f_mat]))
+						file.write(',%s' % (material_mapping_local[mat, tex]))
 					i+=1
 			
 			file.write('\n\t\t}')
@@ -1654,7 +1716,7 @@ def write(filename, batch_objects = None, \
 				TypedIndex: 0
 			}''')
 		
-		if me.faceUV:
+		if do_uvs: # same as me.faceUV
 			file.write('''
 			LayerElement:  {
 				Type: "LayerElementUV"
@@ -1736,8 +1798,8 @@ def write(filename, batch_objects = None, \
 	ob_all_typegroups = [ob_meshes, ob_lights, ob_cameras, ob_arms, ob_null]
 	
 	groups = [] # blender groups, only add ones that have objects in the selections
-	materials = {}
-	textures = {}
+	materials = {} # (mat, image) keys, should be a set()
+	textures = {} # should be a set()
 	
 	tmp_ob_type = ob_type = None # incase no objects are exported, so as not to raise an error
 	
@@ -1837,30 +1899,34 @@ def write(filename, batch_objects = None, \
 					if EXP_MESH_HQ_NORMALS:
 						BPyMesh.meshCalcNormals(me) # high quality normals nice for realtime engines.
 					
-					for mat in mats:
-						# 2.44 use mat.lib too for uniqueness
-						if mat: materials[mat] = mat
-					
 					texture_mapping_local = {}
+					material_mapping_local = {}
 					if me.faceUV:
 						uvlayer_orig = me.activeUVLayer
 						for uvlayer in me.getUVLayerNames():
 							me.activeUVLayer = uvlayer
 							for f in me.faces:
-								img = f.image
-								textures[img] = texture_mapping_local[img] = img
+								tex = f.image
+								textures[tex] = texture_mapping_local[tex] = None
+								
+								try: mat = mats[f.mat]
+								except: mat = None
+								
+								materials[mat, tex] = material_mapping_local[mat, tex] = None # should use sets, wait for blender 2.5
+									
 							
 							me.activeUVLayer = uvlayer_orig
+					else:
+						for mat in mats:
+							# 2.44 use mat.lib too for uniqueness
+							materials[mat, None] = material_mapping_local[mat, None] = None
+						else:
+							materials[None, None] = None
 					
 					if EXP_ARMATURE:
 						armob = BPyObject.getObjectArmature(ob)
 						blenParentBoneName = None
 						
-						# Note - Fixed in BPyObject but for now just copy the function because testers wont have up to date modukes,
-						# TODO - remove this for 2.45 release since getObjectArmature has been fixed
-						if (not armob) and ob.parent and ob.parent.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.ARMATURE:
-							armob = ob.parent
-						
 						# parent bone - special case
 						if (not armob) and ob.parent and ob.parent.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.BONE:
 							armob = ob.parent
@@ -1876,8 +1942,9 @@ def write(filename, batch_objects = None, \
 					my_mesh = my_object_generic(ob, mtx)
 					my_mesh.blenData =		me
 					my_mesh.origData = 		origData
-					my_mesh.blenMaterials =	mats
-					my_mesh.blenTextures =	texture_mapping_local.values()
+					my_mesh.blenMaterials =	material_mapping_local.keys()
+					my_mesh.blenMaterialList = mats
+					my_mesh.blenTextures =	texture_mapping_local.keys()
 					
 					# if only 1 null texture then empty the list
 					if len(my_mesh.blenTextures) == 1 and my_mesh.blenTextures[0] == None:
@@ -1996,8 +2063,8 @@ def write(filename, batch_objects = None, \
 	# Finished finding groups we use
 	
 	
-	materials =	[(sane_matname(mat), mat) for mat in materials.itervalues() if mat]
-	textures =	[(sane_texname(img), img) for img in textures.itervalues()  if img]
+	materials =	[(sane_matname(mat_tex_pair), mat_tex_pair) for mat_tex_pair in materials.iterkeys()]
+	textures =	[(sane_texname(tex), tex) for tex in textures.iterkeys()  if tex]
 	materials.sort() # sort by name
 	textures.sort()
 	
@@ -2126,8 +2193,8 @@ Objects:  {''')
 	
 	write_camera_default()
 	
-	for matname, mat in materials:
-		write_material(matname, mat)
+	for matname, (mat, tex) in materials:
+		write_material(matname, mat) # We only need to have a material per image pair, but no need to write any image info into the material (dumb fbx standard)
 	
 	# each texture uses a video, odd
 	for texname, tex in textures:
@@ -2247,7 +2314,7 @@ Relations:  {''')
 	Model: "Model::Camera Switcher", "CameraSwitcher" {
 	}''')
 	
-	for matname, mat in materials:
+	for matname, (mat, tex) in materials:
 		file.write('\n\tMaterial: "Material::%s", "" {\n\t}' % matname)
 
 	if textures:
@@ -2299,9 +2366,14 @@ Connections:  {''')
 	if materials:
 		for my_mesh in ob_meshes:
 			# Connect all materials to all objects, not good form but ok for now.
-			for mat in my_mesh.blenMaterials:
-				if mat:
-					file.write('\n\tConnect: "OO", "Material::%s", "Model::%s"' % (sane_name_mapping_mat[mat.name], my_mesh.fbxName))
+			for mat, tex in my_mesh.blenMaterials:
+				if mat:	mat_name = mat.name
+				else:	mat_name = None
+				
+				if tex:	tex_name = tex.name
+				else:	tex_name = None
+				
+				file.write('\n\tConnect: "OO", "Material::%s", "Model::%s"' % (sane_name_mapping_mat[mat_name, tex_name], my_mesh.fbxName))
 	
 	if textures:
 		for my_mesh in ob_meshes:
@@ -2734,15 +2806,16 @@ def fbx_ui_exit(e,v):
 	GLOBALS['EVENT'] = e
 
 def do_help(e,v):
-	url = 'http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx'
-	print 'Trying to open web browser with documentation at this address...'
-	print '\t' + url
-	
-	try:
-		import webbrowser
-		webbrowser.open(url)
-	except:
-		print '...could not open a browser window.'
+    url = 'http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx'
+    print 'Trying to open web browser with documentation at this address...'
+    print '\t' + url
+    
+    try:
+        import webbrowser
+        webbrowser.open(url)
+    except:
+        Blender.Draw.PupMenu("Error%t|Opening a webbrowser requires a full python installation")
+        print '...could not open a browser window.'
 
 	
 
diff --git a/release/scripts/help_bpy_api.py b/release/scripts/help_bpy_api.py
index 9c3a24af2882c6aa5dd6167fa35c046cd2f16b46..e8d77ed84528ab4e289ce72ad97cac125cedd093 100644
--- a/release/scripts/help_bpy_api.py
+++ b/release/scripts/help_bpy_api.py
@@ -36,6 +36,12 @@ This script opens the user's default web browser at http://www.blender.org's
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import Blender, webbrowser
-version = str(int(Blender.Get('version')))
-webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    version = str(int(Blender.Get('version')))
+    webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/help_getting_started.py b/release/scripts/help_getting_started.py
index a4f6da5cc55c8cd23f204945976d445f2fd5d67b..77dda2cf88f1cd503cb293ff1d0a7cb711d3f1fa 100644
--- a/release/scripts/help_getting_started.py
+++ b/release/scripts/help_getting_started.py
@@ -38,5 +38,13 @@ This script opens the user's default web browser at www.blender.org's
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import Blender, webbrowser
-webbrowser.open('http://www.blender.org/education-help/tutorials/getting-started/')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    webbrowser.open('http://www.blender.org/education-help/tutorials/getting-started/')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
+
+
diff --git a/release/scripts/help_manual.py b/release/scripts/help_manual.py
index b830975e593906ce00d772aad530005ff00059ce..27900040eb4f7f385ea3af21febb6c797a474efb 100644
--- a/release/scripts/help_manual.py
+++ b/release/scripts/help_manual.py
@@ -36,5 +36,13 @@ This script opens the user's default web browser at www.blender.org's
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import Blender, webbrowser
-webbrowser.open('http://wiki.blender.org/index.php/Manual')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    webbrowser.open('http://wiki.blender.org/index.php/Manual')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
+
+
diff --git a/release/scripts/help_release_notes.py b/release/scripts/help_release_notes.py
index 919ec72da3cad16e337e3a18ff9c57dcc5a1e9ed..870f2391487f5502282ef218979731437f0ba5c0 100644
--- a/release/scripts/help_release_notes.py
+++ b/release/scripts/help_release_notes.py
@@ -36,6 +36,12 @@ This script opens the user's default web browser at www.blender.org's
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import Blender, webbrowser
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    webbrowser.open('http://www.blender.org/development/release-logs/')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
 
-webbrowser.open('http://www.blender.org/development/release-logs/')
diff --git a/release/scripts/help_tutorials.py b/release/scripts/help_tutorials.py
index 1fe466560f0bb0032eadf499500cd16e4c67e9fd..e0cef1abdbffbe6fd7ccdfe70d40eafbec14ecfc 100644
--- a/release/scripts/help_tutorials.py
+++ b/release/scripts/help_tutorials.py
@@ -37,5 +37,11 @@ This script opens the user's default web browser at www.blender.org's
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import Blender, webbrowser
-webbrowser.open('http://www.blender.org/education-help/tutorials/')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    webbrowser.open('http://www.blender.org/education-help/tutorials/')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/help_web_blender.py b/release/scripts/help_web_blender.py
index db0a78d90f758ff07f1ae6c2986ab2cb248c0118..2a0f90844ae1c84cdb9a9dca964dcfd1e85182f5 100644
--- a/release/scripts/help_web_blender.py
+++ b/release/scripts/help_web_blender.py
@@ -38,5 +38,11 @@ www.blender.org.
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import Blender, webbrowser
-webbrowser.open('http://www.blender.org/')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    webbrowser.open('http://www.blender.org/')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/help_web_devcomm.py b/release/scripts/help_web_devcomm.py
index e04a54501f7bf68ef1db5a3f316172e7b778574e..46fa2487a899582bef586c24bb97e3b1ff610fe0 100644
--- a/release/scripts/help_web_devcomm.py
+++ b/release/scripts/help_web_devcomm.py
@@ -37,5 +37,11 @@ This script opens the user's default web browser at www.blender.org's
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import webbrowser
-webbrowser.open('http://www.blender.org/community/get-involved/')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    webbrowser.open('http://www.blender.org/community/get-involved/')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/help_web_eshop.py b/release/scripts/help_web_eshop.py
index c33849ac41912631482416e5a6224ffea61ec4a1..e40795b3a0d99fb288cc9da97a5cf6fa63dd8dce 100644
--- a/release/scripts/help_web_eshop.py
+++ b/release/scripts/help_web_eshop.py
@@ -37,5 +37,11 @@ This script opens the user's default web browser at www.blender.org's
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import Blender, webbrowser
-webbrowser.open('http://www.blender3d.org/e-shop')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    webbrowser.open('http://www.blender3d.org/e-shop')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/help_web_usercomm.py b/release/scripts/help_web_usercomm.py
index a77a2bb9fefcadbd15dbda1f98ba3ed550e78285..dda5e42f34e7c57f626c3e1c0fbd81a06b2270a4 100644
--- a/release/scripts/help_web_usercomm.py
+++ b/release/scripts/help_web_usercomm.py
@@ -37,5 +37,11 @@ This script opens the user's default web browser at www.blender.org's
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-import webbrowser
-webbrowser.open('http://www.blender.org/community/user-community/')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+    webbrowser.open('http://www.blender.org/community/user-community/')
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/image_2d_cutout.py b/release/scripts/image_2d_cutout.py
new file mode 100644
index 0000000000000000000000000000000000000000..16d0805256bd25fa7c6a0383c0d0dcc1aa2d2d9e
--- /dev/null
+++ b/release/scripts/image_2d_cutout.py
@@ -0,0 +1,559 @@
+#!BPY
+
+"""
+Name: '2D Cutout Image Importer'
+Blender: 249
+Group: 'Image'
+Tooltip: 'Batch UV Map images to Planes'
+"""
+
+__author__ = "Kevin Morgan (forTe)"
+__url__ = ("Home page, http://gamulabs.freepgs.com")
+__version__ = "1.2.1"
+__bpydoc__ = """\
+This Script will take an image and
+UV map it to a plane sharing the same width to height ratio as the image.
+Import options allow for the image to be a still or sequence type image
+<br><br>
+Imports can be single images or whole directories of images depending on the chosen
+option.
+"""
+
+####################################################
+#Copyright (C) 2008: Kevin Morgan
+####################################################
+#-------------GPL LICENSE BLOCK-------------
+#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 hopes 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 <http://www.gnu.org/licenses>.
+####################################################
+####################################################
+#V1.0
+#Basic Functionality
+#Published June 28, 2007
+####################################################
+#V1.1
+#Added Support for enabling viewport transparency
+#Added more options to the UI for materials
+#Added Proportionality code (Pixels per unit)
+#Added GPL License Block
+#Published June 29, 2007
+####################################################
+#V1.2
+#Added Support for Copying Existing Materials
+#Import Images as Sequences
+#Refreshed GUI - now with more clutter :(
+#Miscellaneous and Housekeeping
+#Published June 16, 2008
+####################################################
+#V1.2.1
+#Added Extend Texture Mode option at request of a user
+#Published September 24, 2008
+####################################################
+
+import Blender
+from Blender import BGL, Draw, Image, Mesh, Material, Texture, Window
+from Blender.Mathutils import *
+import bpy
+
+# Global Constants
+DIR = 0
+SINGLE = 1
+CUROFFS = 0
+
+# GUI CONSTANTS
+NO_EVT = 0
+SINGLE_IMG = 1
+DIRECTORY_IMG = 2
+CLR_PATH = 3
+CHG_EXT = 4
+EXIT = 5
+DO_SCRIPT = 6
+
+VERSIONSTRING = '1.2.1'
+
+# Note the two parameter dicts could be combined, I just, liked them seperate...
+# GUI Buttons Dict
+GUIPARAMS = {
+	'Path': Draw.Create(''),
+	'ImageExt': Draw.Create(''),
+	'Seq': Draw.Create(0),
+	'PackImage': Draw.Create(0),
+	'PPU': Draw.Create(50),
+	'VPTransp': Draw.Create(1),
+	'XOff': Draw.Create(0.0),
+	'YOff': Draw.Create(0.0),
+	'ZOff': Draw.Create(0.0),
+	'CopyMat': Draw.Create(0),
+	'MatId': Draw.Create(0),
+	'MatCol': Draw.Create(1.0, 0.0, 0.0),
+	'Ref': Draw.Create(0.8),
+	'Spec': Draw.Create(0.5),
+	'Hard': Draw.Create(50),
+	'Alpha': Draw.Create(1.0),
+	'ZTransp': Draw.Create(1),
+	'Shadeless': Draw.Create(0),
+	'TexChan': Draw.Create(1),
+	'MPTCol': Draw.Create(1),
+	'MPTAlpha': Draw.Create(1),
+	'UseAlpha': Draw.Create(1),
+	'CalcAlpha': Draw.Create(0),
+	'ExtendMode': Draw.Create(0),
+	'AutoRefresh': Draw.Create(0),
+	'Cyclic': Draw.Create(0),
+	'Frames': Draw.Create(100),
+	'Offs': Draw.Create(0),
+	'StartFr': Draw.Create(1),
+	'RedrawImp': Draw.Create(0)
+}
+
+# Script Execution Paramaters
+PARAMS = {
+	'ImagePaths': [], 									# Path to images to import
+	'ImportType': SINGLE, 							# Import a Directory or a Single Image?
+	'ImageProp': Image.Sources.STILL, 	# What sources for the image, still or sequence
+	'PackImage': 0,											# Pack the Image(s)?
+	'PPU': 20, 													# Pixels Per Blender Unit
+	'MakeTransp': 1, 										# Make face transparent in viewport
+	
+	'NewMat': 1, 												# If true make a new material, otherwise duplicate an existing one, replacing appropriate attributes
+	'MaterialId': 0,										# ID to take from the Materials list upon copy
+	'Materials': None,									# Materials in Scene
+	'MatProps': {'Col': [1.0, 0.0, 0.0], 'Shadeless': 1, 'Ref': 0.5, 'Spec': 0.5, 'Hard': 200, 'Alpha': 1.0, 'ZTransp': 1},
+	
+	'TexProps': {'UseAlpha': 1, 'CalcAlpha': 0, 'ExtendMode': 0}, # Texture Properties
+	'TexChannel': 0, 										# Texture Channel
+	'TexMapTo': {'Col': 1, 'Alpha': 1}, # Map to Col and/or Alpha
+	'SeqProps': {'AutoRefresh': 0, 'Cyclic': 0, 'Frames': 100, 'Offs': 0, 'StartFr': 1},
+	'ObOffset': Vector(1, 0, 0) 				# Offset by this vector upon creation for multifile import
+}
+
+# Get the Active Scene, of course
+scn = bpy.data.scenes.active
+
+##########################################
+# MAIN SCRIPT FUNCTIONS
+##########################################
+
+def imgImport(imgPath):
+	global CUROFFS, PARAMS
+	######################################
+	# Load the image
+	######################################
+	try:
+		img = Image.Load(imgPath)
+		imgDimensions = img.getSize() # do this to ensure the data is available
+	except:
+		Blender.Draw.PupMenu('Error%t|Unsupported image format for "'+ imgPath.split('\\')[-1].split('/')[-1] +'"')
+		return		
+	
+	if PARAMS['PackImage']:
+		img.pack()
+	name = Blender.sys.makename(imgPath, strip = 1)
+	
+	######################################
+	# Construct the mesh
+	######################################
+	
+	me = Mesh.New(name)
+	
+	# Calculate Dimensions from Image Size
+	dim = [float(i)/PARAMS['PPU'] for i in imgDimensions]
+	v = [[dim[0], dim[1], 0], [-dim[0], dim[1], 0], [-dim[0], -dim[1], 0], [dim[0], -dim[1], 0]]
+	me.verts.extend(v)
+	me.faces.extend([0, 1, 2, 3])
+	
+	me.faces[0].image = img
+	me.faces[0].uv = [Vector(1.0, 1.0), Vector(0.0, 1.0), Vector(0.0, 0.0), Vector(1.0, 0.0)]
+	
+	if PARAMS['MakeTransp']:
+		me.faces[0].transp = Mesh.FaceTranspModes.ALPHA
+	
+	######################################
+	# Modify the Material
+	######################################
+	
+	mat = None
+	if not PARAMS['NewMat']:
+		mat = PARAMS['Materials'][PARAMS['MaterialId']].__copy__()
+		mat.setName(name)
+	else:
+		mat = Material.New(name)
+		properties = PARAMS['MatProps']
+		mat.setRGBCol(properties['Col'])
+		mat.setRef(properties['Ref'])
+		mat.setSpec(properties['Spec'])
+		mat.setHardness(properties['Hard'])
+		mat.setAlpha(properties['Alpha'])
+		
+		if properties['Shadeless']:
+			mat.mode |= Material.Modes.SHADELESS
+		if properties['ZTransp']:
+			mat.mode |= Material.Modes.ZTRANSP
+	
+	properties = PARAMS['TexProps']
+		
+	tex = Texture.New(name)
+	tex.setType('Image')
+	tex.setImage(img)
+	if properties['UseAlpha']:
+		tex.useAlpha = Texture.ImageFlags.USEALPHA
+			
+	if properties['CalcAlpha']:
+		tex.calcAlpha = Texture.ImageFlags.CALCALPHA
+		
+	if properties['ExtendMode']:
+		tex.setExtend('Extend')
+		
+	if PARAMS['ImageProp'] == Image.Sources.SEQUENCE:
+		properties = PARAMS['SeqProps']
+		
+		img.source = PARAMS['ImageProp'] # Needs to be done here, otherwise an error with earlier getSize()
+		
+		tex.animStart = properties['StartFr']
+		tex.animOffset = properties['Offs']
+		tex.animFrames = properties['Frames']
+		tex.autoRefresh = properties['AutoRefresh']
+		tex.cyclic = properties['Cyclic']
+			
+	texMapSetters = Texture.TexCo.UV
+	
+	# PARAMS['TexMapTo']['Col'] (and alpha) will either be 0 or 1 because its from a toggle, otherwise this line doesn't work
+	texChanSetters = Texture.MapTo.COL * PARAMS['TexMapTo']['Col'] | Texture.MapTo.ALPHA * PARAMS['TexMapTo']['Alpha']
+	
+	mat.setTexture(PARAMS['TexChannel'], tex, texMapSetters, texChanSetters)
+	me.materials += [mat]
+	
+	######################################
+	# Object Construction
+	######################################
+	
+	ob = scn.objects.new(me, name)
+	p = Vector(ob.getLocation()) # Should be the origin, but just to be safe, get it
+	ob.setLocation((CUROFFS * PARAMS['ObOffset']) + p)
+		
+	return
+
+def translateParams():
+	# Translates (or assigns for the most part) GUI values to those that can be read by the
+	# Import Function
+	
+	global GUIPARAMS, PARAMS
+	
+	if GUIPARAMS['Seq'].val and PARAMS['ImportType'] != DIR:
+		PARAMS['ImageProp'] = Image.Sources.SEQUENCE
+	
+	PARAMS['PackImage'] = GUIPARAMS['PackImage'].val
+	PARAMS['PPU'] = GUIPARAMS['PPU'].val
+	PARAMS['MakeTransp'] = GUIPARAMS['VPTransp'].val
+	PARAMS['ObOffset'] = Vector(GUIPARAMS['XOff'].val, GUIPARAMS['YOff'].val, GUIPARAMS['ZOff'].val)
+	
+	PARAMS['NewMat'] = not GUIPARAMS['CopyMat'].val
+	PARAMS['MaterialId'] = GUIPARAMS['MatId'].val
+	PARAMS['MatProps']['Col'] = list(GUIPARAMS['MatCol'].val)
+	PARAMS['MatProps']['Ref'] = GUIPARAMS['Ref'].val
+	PARAMS['MatProps']['Spec'] = GUIPARAMS['Spec'].val
+	PARAMS['MatProps']['Hard'] = GUIPARAMS['Hard'].val
+	PARAMS['MatProps']['Alpha'] = GUIPARAMS['Alpha'].val
+	PARAMS['MatProps']['ZTransp'] = GUIPARAMS['ZTransp'].val
+	PARAMS['MatProps']['Shadeless'] = GUIPARAMS['Shadeless'].val
+	
+	PARAMS['TexChannel'] = GUIPARAMS['TexChan'].val - 1 #Channels are 0-9, but GUI shows 1-10
+	PARAMS['TexProps']['UseAlpha'] = GUIPARAMS['UseAlpha'].val
+	PARAMS['TexProps']['CalcAlpha'] = GUIPARAMS['CalcAlpha'].val
+	PARAMS['TexProps']['ExtendMode'] = GUIPARAMS['ExtendMode'].val
+	PARAMS['TexMapTo']['Col'] = GUIPARAMS['MPTCol'].val
+	PARAMS['TexMapTo']['Alpha'] = GUIPARAMS['MPTAlpha'].val
+	
+	PARAMS['SeqProps']['AutoRefresh'] = GUIPARAMS['AutoRefresh'].val
+	PARAMS['SeqProps']['Cyclic'] = GUIPARAMS['Cyclic'].val
+	PARAMS['SeqProps']['Frames'] = GUIPARAMS['Frames'].val
+	PARAMS['SeqProps']['Offs'] = GUIPARAMS['Offs'].val
+	PARAMS['SeqProps']['StartFr'] = GUIPARAMS['StartFr'].val
+	return
+	
+def doScript():
+	# Main script Function
+	# Consists of choosing between 2 loops, one with a redraw, one without, see comments for why
+	
+	global CUROFFS
+	
+	translateParams()
+	
+	total = len(PARAMS['ImagePaths'])
+	broken = 0
+	
+	if GUIPARAMS['RedrawImp'].val: # Reduces the need to compare on every go through the loop
+		for i, path in enumerate(PARAMS['ImagePaths']):
+			CUROFFS = i # Could be passed to the import Function, but I chose a global instead
+			Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))		
+			imgImport(path)		
+			Blender.Redraw()		
+			if Blender.Get('version') >= 246:
+				if Window.TestBreak():
+					broken = 1
+					break
+	else:
+		for i, path in enumerate(PARAMS['ImagePaths']):
+			CUROFFS = i
+			Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
+			imgImport(path)
+			if Blender.Get('version') >= 246:
+				if Window.TestBreak():
+					broken = 1
+					break
+				
+	if broken:
+		Window.DrawProgressBar(1.0, "Script Execution Aborted")
+	else:
+		Window.DrawProgressBar(1.0, "Finished Importing")
+		
+	Blender.Redraw() # Force a refresh, since the user may have chosen to not refresh as they go along
+	
+	return
+
+##########################################
+# PATH SETTERS AND CHANGERS
+##########################################
+
+def setSinglePath(filename):
+	global GUIPARAMS, PARAMS
+	GUIPARAMS['Path'].val = filename
+	PARAMS['ImagePaths'] = [filename]
+	return
+
+def setDirPath(filename):
+	global GUIPARAMS, PARAMS
+	
+	try:
+		import os
+	except:
+		Draw.PupMenu('Full install of python required to be able to set Directory Paths')
+		Draw.Exit()
+		return
+	
+	path = os.path.dirname(filename) # Blender.sys.dirname fails on '/'
+	GUIPARAMS['Path'].val = path
+	
+	ext_lower = GUIPARAMS['ImageExt'].val.lower()
+	for f in os.listdir(path):
+		if f.lower().endswith(ext_lower):
+			PARAMS['ImagePaths'].append(os.path.join(path, f))
+	
+	return
+
+def changeExtension():
+	global GUIPARAMS, PARAMS
+	
+	if PARAMS['ImportType'] == SINGLE:
+		return
+	
+	try:
+		import os
+	except:
+		Draw.PupMenu('Full install of python required to be able to set Directory Paths')
+		Draw.Exit()
+		return
+		
+	PARAMS['ImagePaths'] = []
+	
+	ext_lower = GUIPARAMS['ImageExt'].val.lower()
+	for f in os.listdir(GUIPARAMS['Path'].val):
+		if f.lower().endswith(ext_lower):
+			PARAMS['ImagePaths'].append(os.path.join(GUIPARAMS['Path'].val, f))
+			
+	return
+
+##########################################
+# INTERFACE FUNCTIONS
+##########################################
+def compileMaterialList():
+	# Pretty straight forward, just grabs the materials in the blend file and constructs
+	# an appropriate string for use as a menu
+	
+	mats = [mat for mat in bpy.data.materials]
+	PARAMS['Materials'] = mats
+	title = 'Materials%t|'
+	menStrs = [mat.name + '%x' + str(i) + '|' for i, mat in enumerate(mats)]
+	return title + ''.join(menStrs)
+
+def event(evt, val):
+	# Disabled, since Esc is often used from the file browser
+	#if evt == Draw.ESCKEY:
+	#	Draw.Exit()
+		
+	return
+
+def bevent(evt):
+	global GUIPARAMS, PARAMS
+	
+	if evt == NO_EVT:
+		Draw.Redraw()
+	
+	elif evt == SINGLE_IMG:
+		Window.FileSelector(setSinglePath, 'Image', Blender.sys.expandpath('//'))
+		Draw.Redraw()
+		PARAMS['ImportType'] = SINGLE
+	
+	elif evt == DIRECTORY_IMG:
+		Window.FileSelector(setDirPath, 'Directory', Blender.sys.expandpath('//'))
+		Draw.Redraw()
+		PARAMS['ImportType'] = DIR
+		
+	elif evt == CLR_PATH:
+		GUIPARAMS['Path'].val = ''
+		PARAMS['ImagePaths'] = []
+		GUIPARAMS['ImageExt'].val = ''
+		Draw.Redraw()
+		
+	elif evt == CHG_EXT:
+		changeExtension()
+		Draw.Redraw()
+		
+	elif evt == EXIT:
+		Draw.Exit()
+		
+	elif evt == DO_SCRIPT:
+		doScript()
+		
+	else:
+		print "ERROR: UNEXPECTED BUTTON EVENT"
+			
+	return
+
+# GUI Colors ######
+ScreenColor = [0.7, 0.7, 0.7]
+BackgroundColor = [0.8, 0.8, 0.8]
+TitleBG = [0.6, 0.6, 0.6]
+TitleCol = [1.0, 1.0, 1.0]
+ErrCol = [1.0, 0.0, 0.0]
+TextCol = [0.4, 0.4, 0.5]
+###################
+
+def GUI():
+	global GUIPARAMS, PARAMS
+	
+	BGL.glClearColor(*(ScreenColor + [1.0]))
+	BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
+	
+	minx = 5
+	maxx = 500
+	miny = 5
+	maxy = 450
+	
+	lineheight = 24
+	buPad = 5 # Generic Button Padding, most buttons should have 24-19 (or 5) px space around them
+	
+	lP = 5 # Left Padding
+	rP = 5 # Right Padding
+	
+	# Draw Background Box
+	BGL.glColor3f(*BackgroundColor)
+	BGL.glRecti(minx, miny, maxx, maxy)
+	
+	# Draw Title
+	BGL.glColor3f(*TitleBG)
+	BGL.glRecti(minx, maxy - (lineheight), maxx, maxy)
+	BGL.glColor3f(*TitleCol)
+	
+	title = "2D Cutout Image Importer v" + VERSIONSTRING
+	BGL.glRasterPos2i(minx + lP, maxy - 15)
+	Draw.Text(title, 'large')
+	
+	Draw.PushButton('Exit', EXIT, maxx-50-rP, maxy - lineheight + 2, 50, 19, "Exit Script")
+		
+	# Path Buttons
+	if GUIPARAMS['Path'].val == '':
+		Draw.PushButton('Single Image', SINGLE_IMG, minx + lP, maxy - (2*lineheight), 150, 19, "Select a Single Image to Import")
+		Draw.PushButton('Directory', DIRECTORY_IMG, minx + lP + 150, maxy - (2*lineheight), 150, 19, "Select a Directory of Images to Import")
+		
+	else:
+		Draw.PushButton('Clear', CLR_PATH, minx+lP, maxy - (2*lineheight), 50, 19, "Clear Path and Change Import Options")
+
+	GUIPARAMS['Path'] = Draw.String('Path: ', NO_EVT, minx + lP, maxy - (3*lineheight), (maxx-minx-lP-rP), 19, GUIPARAMS['Path'].val, 399, 'Path to Import From')
+	if PARAMS['ImportType'] == DIR:
+		GUIPARAMS['ImageExt'] = Draw.String('Image Ext: ', CHG_EXT, minx + lP, maxy - (4*lineheight), 110, 19,  GUIPARAMS['ImageExt'].val, 6, 'Image extension for batch directory importing (case insensitive)')
+	GUIPARAMS['PackImage'] = Draw.Toggle('Pack', NO_EVT, maxx - rP - 50, maxy - (4*lineheight), 50, 19, GUIPARAMS['PackImage'].val, 'Pack Image(s) into .Blend File')
+	
+	# Geometry and Viewport Options
+	BGL.glColor3f(*TextCol)
+	BGL.glRecti(minx+lP, maxy - (5*lineheight), maxx-rP, maxy - (5*lineheight) + 1)
+	BGL.glRasterPos2i(minx + lP, maxy-(5*lineheight) + 3)
+	Draw.Text('Geometry and Display Options', 'small')
+	
+	GUIPARAMS['PPU'] = Draw.Slider('Pixels Per Unit: ', NO_EVT, minx + lP, maxy - (6*lineheight), (maxx-minx)/2 - lP, 19, GUIPARAMS['PPU'].val, 1, 5000, 0, 'Set the Number of Pixels Per Blender Unit to preserve Image Size Relations') 
+	GUIPARAMS['VPTransp'] = Draw.Toggle('Viewport Transparency', NO_EVT, minx + lP, maxy - (8*lineheight),  (maxx-minx)/2 - lP, 2*lineheight - buPad, GUIPARAMS['VPTransp'].val, 'Display Alpha Transparency in the Viewport')
+
+	GUIPARAMS['XOff'] = Draw.Slider('Offs X: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (6*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['XOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the X-Direction if Importing Multiple Images')
+	GUIPARAMS['YOff'] = Draw.Slider('Offs Y: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (7*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['YOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Y-Direction if Importing Multiple Images')
+	GUIPARAMS['ZOff'] = Draw.Slider('Offs Z: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (8*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['ZOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Z-Direction if Importing Multiple Images')
+
+	# Material and Texture Options
+	BGL.glColor3f(*TextCol)
+	BGL.glRecti(minx+lP, maxy - (9*lineheight), maxx-rP, maxy - (9*lineheight) + 1)
+	BGL.glRasterPos2i(minx + lP, maxy-(9*lineheight) + 3)
+	Draw.Text('Material and Texture Options', 'small')
+	
+	half = (maxx-minx-lP-rP)/2
+	GUIPARAMS['CopyMat'] = Draw.Toggle('Copy Existing Material', NO_EVT, minx + lP, maxy-(10*lineheight), half, 19, GUIPARAMS['CopyMat'].val, 'Copy an Existing Material')
+	if GUIPARAMS['CopyMat'].val:
+		menStr = compileMaterialList()
+		GUIPARAMS['MatId'] = Draw.Menu(menStr, NO_EVT, minx + lP, maxy - (11*lineheight), half, 19, GUIPARAMS['MatId'].val, 'Material to Copy Settings From') 
+	else:
+		GUIPARAMS['MatCol'] = Draw.ColorPicker(NO_EVT, minx+lP, maxy - (13*lineheight), 40, (3*lineheight) - buPad, GUIPARAMS['MatCol'].val, 'Color of Newly Created Material')
+		GUIPARAMS['Ref'] = Draw.Slider('Ref: ', NO_EVT, minx +lP+45, maxy - (11*lineheight), half-45, 19, GUIPARAMS['Ref'].val, 0.0, 1.0, 0, 'Set the Ref Value for Created Materials')
+		GUIPARAMS['Spec'] = Draw.Slider('Spec: ', NO_EVT, minx +lP+45, maxy - (12*lineheight), half-45, 19, GUIPARAMS['Spec'].val, 0.0, 2.0, 0, 'Set the Spec Value for Created Materials')
+		GUIPARAMS['Hard'] = Draw.Slider('Hard: ', NO_EVT, minx +lP+45, maxy - (13*lineheight), half-45, 19, GUIPARAMS['Hard'].val, 1, 500, 0, 'Set the Hardness Value for Created Materials')
+		GUIPARAMS['Alpha'] = Draw.Slider('A: ', NO_EVT, minx +lP, maxy - (14*lineheight), half, 19, GUIPARAMS['Alpha'].val, 0.0, 1.0, 0, 'Set the Alpha Value for Created Materials')
+		
+		GUIPARAMS['ZTransp'] = Draw.Toggle('ZTransparency', NO_EVT, minx + lP, maxy - (15*lineheight), half, 19, GUIPARAMS['ZTransp'].val, 'Enable ZTransparency')
+		GUIPARAMS['Shadeless'] = Draw.Toggle('Shadeless', NO_EVT, minx + lP, maxy - (16*lineheight), half, 19, GUIPARAMS['Shadeless'].val, 'Enable Shadeless')
+
+	GUIPARAMS['TexChan'] = Draw.Number('Texture Channel: ', NO_EVT, minx + lP+ half + buPad, maxy - (10*lineheight), half-rP, 19, GUIPARAMS['TexChan'].val, 1, 10, 'Texture Channel for Image Texture')
+	
+	GUIPARAMS['MPTCol'] = Draw.Toggle('Color', NO_EVT, minx + lP + half + buPad, maxy - (11*lineheight), half/2, 19, GUIPARAMS['MPTCol'].val, 'Map To Color Channel')
+	GUIPARAMS['MPTAlpha'] = Draw.Toggle('Alpha', NO_EVT, minx + lP + int((1.5)*half) + buPad, maxy - (11*lineheight), half/2 - rP, 19, GUIPARAMS['MPTAlpha'].val, 'Map To Alpha Channel')
+	
+	third = int((maxx-minx-lP-rP)/6)
+	GUIPARAMS['UseAlpha'] = Draw.Toggle('Use Alpha', NO_EVT, minx + lP + half + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['UseAlpha'].val, "Use the Images' Alpha Values")
+	GUIPARAMS['CalcAlpha'] = Draw.Toggle('Calc Alpha', NO_EVT, minx + lP + half + third + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['CalcAlpha'].val, "Calculate Images' Alpha Values")
+	GUIPARAMS['ExtendMode'] = Draw.Toggle('Extend', NO_EVT, minx+lP+half+third+third+buPad, maxy - (12*lineheight), third-3, 19, GUIPARAMS['ExtendMode'].val, "Use Extend texture mode. If deselected, Repeat is used")
+	GUIPARAMS['Seq'] = Draw.Toggle('Sequence', NO_EVT, minx + lP + half + buPad, maxy - (13*lineheight), half-rP, 19, GUIPARAMS['Seq'].val, 'Set the Image(s) to use a Sequence instead of a Still')
+	
+	if GUIPARAMS['Seq'].val and not PARAMS['ImportType'] == DIR:
+		GUIPARAMS['AutoRefresh'] = Draw.Toggle('Auto Refresh', NO_EVT, minx + lP + half + buPad, maxy - (14*lineheight), half/2, 19, GUIPARAMS['AutoRefresh'].val, 'Use Auto Refresh')
+		GUIPARAMS['Cyclic'] = Draw.Toggle('Cyclic', NO_EVT, minx + lP + half + buPad + half/2, maxy - (14*lineheight), half/2 - rP, 19, GUIPARAMS['Cyclic'].val, 'Repeat Frames Cyclically`')
+
+		GUIPARAMS['Frames'] = Draw.Number('Frames: ', NO_EVT, minx +lP + half + buPad, maxy - (15*lineheight), half - rP, 19, GUIPARAMS['Frames'].val, 1, 30000, 'Sets the Number of Images of a Movie to Use')
+		GUIPARAMS['Offs'] = Draw.Number('Offs: ', NO_EVT, minx +lP + half + buPad, maxy - (16*lineheight), half/2, 19, GUIPARAMS['Offs'].val, -30000, 30000, 'Offsets the Number of the Frame to use in the Animation')
+		GUIPARAMS['StartFr'] = Draw.Number('StartFr: ', NO_EVT, minx +lP + half + buPad + half/2, maxy - (16*lineheight), half/2 - rP, 19, GUIPARAMS['StartFr'].val, 1, 30000, 'Sets the Global Starting Frame of the Movie')
+	elif GUIPARAMS['Seq'].val and PARAMS['ImportType'] == DIR:
+		BGL.glColor3f(*ErrCol)
+		BGL.glRasterPos2i(minx + lP + half + buPad + 7, maxy-(14 * lineheight) + 5)
+		Draw.Text('Sequence only available for Single Image Import', 'small')
+		
+	# Import Options
+	BGL.glColor3f(*TextCol)
+	BGL.glRecti(minx+lP, maxy - (17*lineheight), maxx-rP, maxy - (17*lineheight) + 1)
+	BGL.glRasterPos2i(minx + lP, maxy-(17*lineheight) + 3)
+	Draw.Text('Import', 'small')
+
+	if GUIPARAMS['Path'].val and GUIPARAMS['ImageExt'].val or GUIPARAMS['Path'].val and PARAMS['ImportType'] == SINGLE:
+		Draw.PushButton('Import', DO_SCRIPT, minx + lP, maxy - (18*lineheight), 75, 19, "Import Image(s)")
+	else:
+		BGL.glColor3f(*ErrCol)
+		BGL.glRasterPos2i(minx+lP, maxy - (18*lineheight) + 5)
+		Draw.Text('A path and image type must be specified to import images')
+		
+	GUIPARAMS['RedrawImp'] = Draw.Toggle('Redraw During Import', NO_EVT, maxx - rP - 150, maxy - (18*lineheight), 150, 19, GUIPARAMS['RedrawImp'].val, 'Redraw the View as Images Import')
+
+Draw.Register(GUI, event, bevent)
\ No newline at end of file
diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py
index c3203891c603a5c43fc58a9c697fc43665aec9da..ceb4dd567220f89836f8f84edc61308dc7e6ae45 100644
--- a/release/scripts/import_dxf.py
+++ b/release/scripts/import_dxf.py
@@ -1,20 +1,21 @@
 #!BPY
 
 """
-Name: 'Autodesk DXF (.dxf)'
+Name: 'Autodesk DXF (.dxf .dwg)'
 Blender: 246
 Group: 'Import'
-Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).'
+Tooltip: 'Import for DWG/DXF geometry data.'
 """
 __author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)'
-__version__ = '1.12 - 2009.03.14 by migius'
+__version__ = '1.12 - 2009.04.11 by migius'
 __url__ = ["http://blenderartists.org/forum/showthread.php?t=84319",
 	 "http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"]
 __email__ = ["migius(at)4d-vectors.de","Kitsune_e(at)yahoo.com"]
 __bpydoc__ = """\
-This script imports objects from DXF (2d/3d) into Blender.
+This script imports objects from DWG/DXF (2d/3d) into Blender.
 
 This script imports 2d and 3d geometery from DXF files.
+It supports DWG format too, with help of an external converter.
 Supported DXF format versions: from (r2.5) r12 up to r2008.
 Enhanced features are:
 - configurable object filtering and geometry manipulation,
@@ -111,6 +112,8 @@ History:
  -- support ortho mode for VIEWs and VPORTs as cameras 
 
 
+ v1.12 - 2009.04.11 by migius
+ d4 added DWG support, Stani Michiels idea for binding an extern DXF-DWG-converter 
  v1.12 - 2009.03.14 by migius
  d3 removed all set()functions (problem with osx/python<2.4 reported by Blinkozo)
  d3 code-cleaning
@@ -305,7 +308,8 @@ History:
 # --------------------------------------------------------------------------
 
 import Blender
-from Blender import *
+from Blender import Mathutils, BezTriple, Draw, Registry, sys,\
+Text3d, Window, Mesh, Material, Group
 #from Blender.Mathutils import Vector, Matrix
 #import bpy #not used yet
 #import BPyMessages
@@ -314,7 +318,7 @@ from dxfReader import readDXF
 #from dxfReader import get_name, get_layer
 from dxfReader import Object as dxfObject
 from dxfColorMap import color_map
-from math import *
+from math import log10, sqrt, radians, degrees, atan, cos, sin
 
 # osx-patch by Blinkozo
 #todo: avoid additional modules, prefer Blender-build-in test routines
@@ -325,9 +329,10 @@ from math import *
 #ver = '%s.%s' % version_info[0:2]
 # end osx-patch
 
-try:
-	import os
-	if os.name != 'mac':
+import subprocess
+import os
+if os.name != 'mac':
+	try:
 		import psyco
 		psyco.log(Blender.Get('tempdir')+"/blender.log-psyco")
 		#psyco.log()
@@ -335,14 +340,13 @@ try:
 		psyco.profile(0.05, memory=100)
 		psyco.profile(0.2)
 		#print 'psyco imported'
-except ImportError:
-	print 'psyco not imported'
-	pass
+	except ImportError:
+		print 'psyco not imported'
 
 #try: Curve.orderU
 
 print '\n\n\n'
-print 'DXF-Importer v%s *** start ***' %(__version__)   #---------------------
+print 'DXF/DWG-Importer v%s *** start ***' %(__version__)   #---------------------
 
 SCENE = None
 WORLDX = Mathutils.Vector((1,0,0))
@@ -386,6 +390,29 @@ FREE = BezTriple.HandleTypes.FREE
 VECT = BezTriple.HandleTypes.VECT
 ALIGN = BezTriple.HandleTypes.ALIGN
 
+UI_MODE = True #activates UI-popup-print, if not multiple files imported
+
+
+#-------- DWG support ------------------------------------------
+extCONV_OK = True
+extCONV = 'DConvertCon.exe'
+extCONV_PATH = os.path.join(Blender.Get('scriptsdir'),extCONV)
+if not os.path.isfile(extCONV_PATH):
+	extCONV_OK = False
+	extCONV_TEXT = 'DWG-Importer cant find external DWG-converter (%s) in Blender script directory.|\
+More details in online Help.' %extCONV
+else:
+	if not os.sys.platform.startswith('win'):
+		# check if Wine installed:   
+		if subprocess.Popen(('which', 'winepath'), stdout=subprocess.PIPE).stdout.read().strip():
+			extCONV_PATH    = 'wine %s'%extCONV_PATH
+		else: 
+			extCONV_OK = False
+			extCONV_TEXT = 'The external DWG-converter (%s) needs Wine installed on your system.|\
+More details in online Help.' %extCONV
+#print 'extCONV_PATH = ', extCONV_PATH
+
+
 
 class View:  #-----------------------------------------------------------------
 	"""Class for objects representing dxf VIEWs.
@@ -754,7 +781,7 @@ class Solid:  #-----------------------------------------------------------------
 
 		if settings.var['vGroup_on'] and not M_OBJ:
 			# each MeshSide becomes vertexGroup for easier material assignment ---------------------
-			replace = Blender.Mesh.AssignModes.ADD  #or .AssignModes.ADD/REPLACE
+			replace = Mesh.AssignModes.ADD  #or .AssignModes.ADD/REPLACE
 			if vg_left: me.addVertGroup('side.left')  ; me.assignVertsToGroup('side.left',  vg_left, 1.0, replace)
 			if vg_right:me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace)
 			if vg_top:  me.addVertGroup('side.top')   ; me.assignVertsToGroup('side.top',   vg_top, 1.0, replace)
@@ -899,7 +926,7 @@ class Line:  #-----------------------------------------------------------------
 				ob.link(me) # link mesh to that object
 				vG_name = 'color_%s' %self.color_index
 				if edges: faces = edges
-				replace = Blender.Mesh.AssignModes.ADD  #or .AssignModes.REPLACE or ADD
+				replace = Mesh.AssignModes.ADD  #or .AssignModes.REPLACE or ADD
 				try:
 					me.assignVertsToGroup(vG_name,  faces[0], 1.0, replace)
 					#print 'deb: existed vGroup:', vG_name #---------------------
@@ -1792,7 +1819,7 @@ class Polyline:  #--------------------------------------------------------------
 				# which may be linked to more than one object.
 				if settings.var['vGroup_on'] and not M_OBJ:
 					# each MeshSide becomes vertexGroup for easier material assignment ---------------------
-					replace = Blender.Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
+					replace = Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
 					vg_left, vg_right, vg_top, vg_bottom = [], [], [], []
 					for v in f_left: vg_left.extend(v)
 					for v in f_right: vg_right.extend(v)
@@ -2640,7 +2667,7 @@ class Circle:  #----------------------------------------------------------------
 				# each MeshSide becomes vertexGroup for easier material assignment ---------------------
 				if settings.var['vGroup_on'] and not M_OBJ:
 					# each MeshSide becomes vertexGroup for easier material assignment ---------------------
-					replace = Blender.Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
+					replace = Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
 					vg_band, vg_top, vg_bottom = [], [], []
 					for v in f_band: vg_band.extend(v)
 					me.addVertGroup('side.band')  ; me.assignVertsToGroup('side.band',  vg_band, 1.0, replace)
@@ -2820,7 +2847,7 @@ class Arc:  #-----------------------------------------------------------------
 					# each MeshSide becomes vertexGroup for easier material assignment ---------------------
 					if settings.var['vGroup_on'] and not M_OBJ:
 						# each MeshSide becomes vertexGroup for easier material assignment ---------------------
-						replace = Blender.Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
+						replace = Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
 						vg_left, vg_right, vg_top, vg_bottom = [], [], [], []
 						for v in f_left: vg_left.extend(v)
 						for v in f_right: vg_right.extend(v)
@@ -3364,7 +3391,7 @@ class Ellipse:  #---------------------------------------------------------------
 							me.faces[i].smooth = True
 					if settings.var['vGroup_on'] and not M_OBJ:
 						# each MeshSide becomes vertexGroup for easier material assignment ---------------------
-						replace = Blender.Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
+						replace = Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
 						vg_left, vg_right, vg_top, vg_bottom = [], [], [], []
 						for v in f_left: vg_left.extend(v)
 						for v in f_right: vg_right.extend(v)
@@ -3517,7 +3544,7 @@ class Face:  #-----------------------------------------------------------------
 			ob.link(me) # link mesh to that object
 			vG_name = 'color_%s' %self.color_index
 			if edges: faces = edges
-			replace = Blender.Mesh.AssignModes.ADD  #or .AssignModes.REPLACE or ADD
+			replace = Mesh.AssignModes.ADD  #or .AssignModes.REPLACE or ADD
 			try:
 				me.assignVertsToGroup(vG_name,  faces[0], 1.0, replace)
 				#print 'deb: existed vGroup:', vG_name #---------------------
@@ -4022,10 +4049,8 @@ class Settings:  #--------------------------------------------------------------
 		"""Wraps the built-in print command in a optimization check.
 		"""
 		if self.var['optimization'] <= self.MID:
-			if newline:
-				print text
-			else:
-				print text,
+			if newline: print text
+			else: print text,
 
 
 	def redraw(self):
@@ -4067,9 +4092,9 @@ def	analyzeDXF(dxfFile): #---------------------------------------
 	"""
 	Window.WaitCursor(True)   # Let the user know we are thinking
 	print 'reading DXF file: %s.' % dxfFile
-	time1 = Blender.sys.time()  #time marker1
+	time1 = sys.time()  #time marker1
 	drawing = readDXF(dxfFile, objectify)
-	print 'finish reading in %.4f sec.' % (Blender.sys.time()-time1)
+	print 'finish reading in %.4f sec.' % (sys.time()-time1)
 
 	# First sort out all the section_items
 	sections = dict([(item.name, item) for item in drawing.data])
@@ -4282,10 +4307,45 @@ def main(dxfFile):  #---------------#############################-----------
 		if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile):
 			Window.WaitCursor(True)   # Let the user know we are thinking
 			print 'reading file: %s.' % dxfFile
-			time1 = Blender.sys.time()  #time marker1
+			time1 = sys.time()  #time marker1
 			drawing = readDXF(dxfFile, objectify)
-			print 'reading finished in %.4f sec.' % (Blender.sys.time()-time1)
+			print 'reading finished in %.4f sec.' % (sys.time()-time1)
 			Window.WaitCursor(False)
+		elif dxfFile.lower().endswith('.dwg') and sys.exists(dxfFile):
+			if not extCONV_OK:
+				Draw.PupMenu(extCONV_TEXT)
+				Window.WaitCursor(False)
+				if editmode: Window.EditMode(1) # and put things back how we fond them
+				return None
+			else:
+				Window.WaitCursor(True)   # Let the user know we are thinking
+				#todo: issue: in DConvertCon.exe the output filename is fixed to dwg_name.dxf
+				
+				if 0: # works only for Windows
+					dwgTemp = 'temp_01.dwg'
+					dxfTemp = 'temp_01.dxf'
+					os.system('copy %s %s' %(dxfFile,dwgTemp))
+				else:
+					dwgTemp = dxfFile
+					dxfTemp = dxfFile[:-3]+'dxf'
+				#print 'temp. converting: %s\n              to: %s' %(dxfFile, dxfTemp)
+				#os.system('%s %s  -acad11 -dxf' %(extCONV_PATH, dxfFile))
+				os.system('%s %s  -dxf' %(extCONV_PATH, dwgTemp))
+				#os.system('%s %s  -dxf' %(extCONV_PATH, dxfFile_temp))
+				if sys.exists(dxfTemp):
+					print 'reading file: %s.' % dxfTemp
+					time1 = sys.time()  #time marker1
+					drawing = readDXF(dxfTemp, objectify)
+					#os.remove(dwgTemp)
+					os.remove(dxfTemp) # clean up
+					print 'reading finished in %.4f sec.' % (sys.time()-time1)
+					Window.WaitCursor(False)
+				else:
+					if UI_MODE: Draw.PupMenu('DWG importer:  nothing imported!%t|No valid DXF-representation found!')
+					print 'DWG importer:  nothing imported. No valid DXF-representation found.'
+					Window.WaitCursor(False)
+					if editmode: Window.EditMode(1) # and put things back how we fond them
+					return None
 		else:
 			if UI_MODE: Draw.PupMenu('DXF importer:  Alert!%t| no valid DXF-file selected!')
 			print "DXF importer: Alert! - no valid DXF-file selected."
@@ -4295,7 +4355,7 @@ def main(dxfFile):  #---------------#############################-----------
 
 		# Draw all the know entity types in the current scene
 		oblist = []  # a list of all created AND linked objects for final f_globalScale
-		time2 = Blender.sys.time()  #time marker2
+		time2 = sys.time()  #time marker2
 
 		Window.WaitCursor(True)   # Let the user know we are thinking
 		settings.write("\n\nDrawing entities...")
@@ -4322,7 +4382,7 @@ def main(dxfFile):  #---------------#############################-----------
 		#SCENE.objects.selected = SCENE.objects   #select all objects in current scene		  
 		Blender.Redraw()
 
-		time_text = Blender.sys.time() - time2
+		time_text = sys.time() - time2
 		Window.WaitCursor(False)
 		if settings.var['paper_space_on']: space = 'from paper space'
 		else: space = 'from model space'
@@ -4571,7 +4631,7 @@ def drawer(_type, entities, settings, block_def):  #----------------------------
 		activObjectLayer = ''
 		activObjectName = ''
 
-		message = "Drawing dxf\'%ss\'..." %_type
+		message = "Drawing dxf \'%ss\'..." %_type
 		cur_COUNTER += len_temp - len(entities)
 		settings.write(message, False)
 		settings.progress(cur_COUNTER, message)
@@ -5078,7 +5138,7 @@ def drawCurveArc(self):  #---- only for ELLIPSE --------------------------------
 
 
 # GUI STUFF -----#################################################-----------------
-from Blender.BGL import *
+from Blender.BGL import glColor3f, glRecti, glClear, glRasterPos2d
 
 EVENT_NONE = 1
 EVENT_START = 2
@@ -5577,7 +5637,7 @@ def draw_UI():  #---------------------------------------------------------------
 
 	y += 30
 	colorbox(x, y+20, x+menu_w+menu_margin*2, menu_margin)
-	Draw.Label("DXF-Importer  v" + __version__, but0c, y, menu_w, 20)
+	Draw.Label("DXF/DWG-Importer v" + __version__, but0c, y, menu_w, 20)
 
 	if config_UI.val:
 		b0, b0_ = but0c, but_0c + butt_margin
@@ -5853,9 +5913,9 @@ def draw_UI():  #---------------------------------------------------------------
 
 	#y -= 10
 	Draw.BeginAlign()
-	Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF-file from project directory')
-	dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, but_1c+but_2c+but_3c-20, 20, dxfFileName.val, FILENAME_MAX, "type the name of DXF-file or type *.dxf for multi-import")
-	Draw.PushButton('*.*', EVENT_DXF_DIR, but3c+but_3c-20, y, 20, 20, 'import all dxf files from this directory')
+	Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF/DWG-file for import')
+	dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, but_1c+but_2c+but_3c-20, 20, dxfFileName.val, FILENAME_MAX, "type the name of DXF/DWG-file or type *.dxf/*.dwg for multiple files")
+	Draw.PushButton('*.*', EVENT_DXF_DIR, but3c+but_3c-20, y, 20, 20, 'set filter for import all files from this directory')
 	Draw.EndAlign()
 
 	y -= 30
@@ -5902,8 +5962,9 @@ def colorbox(x,y,xright,bottom):
 
 def dxf_callback(input_filename):
 	global dxfFileName
-	dxfFileName.val=input_filename
-#	dirname == Blender.sys.dirname(Blender.Get('filename'))
+	if input_filename.lower()[-3:] in ('dwg','dxf'):
+		dxfFileName.val=input_filename
+#	dirname == sys.dirname(Blender.Get('filename'))
 #	update_RegistryKey('DirName', dirname)
 #	update_RegistryKey('dxfFileName', input_filename)
 	
@@ -5913,17 +5974,17 @@ def ini_callback(input_filename):
 
 def event(evt, val):
 	if evt in (Draw.QKEY, Draw.ESCKEY) and not val:
-		Blender.Draw.Exit()
+		Draw.Exit()
 
 def bevent(evt):
 #   global EVENT_NONE,EVENT_LOAD_DXF,EVENT_LOAD_INI,EVENT_SAVE_INI,EVENT_EXIT
 	global config_UI, user_preset
-	global GUI_A
+	global GUI_A, UI_MODE
 
 	######### Manages GUI events
 	if (evt==EVENT_EXIT):
-		Blender.Draw.Exit()
-		print 'DXF-Importer  *** exit ***'   #---------------------
+		Draw.Exit()
+		print 'DXF/DWG-Importer  *** exit ***'   #---------------------
 	elif (evt==EVENT_CHOOSE_INI):
 		Window.FileSelector(ini_callback, "INI-file Selection", '*.ini')
 	elif (evt==EVENT_REDRAW):
@@ -5980,13 +6041,14 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D')
 		Draw.Redraw()
 	elif (evt==EVENT_DXF_DIR):
 		dxfFile = dxfFileName.val
+		dxfFileExt = '*'+dxfFile.lower()[-4:]  #can be .dxf or .dwg
 		dxfPathName = ''
 		if '/' in dxfFile:
 			dxfPathName = '/'.join(dxfFile.split('/')[:-1]) + '/'
 		elif '\\' in dxfFile:
 			dxfPathName = '\\'.join(dxfFile.split('\\')[:-1]) + '\\'
-		dxfFileName.val = dxfPathName + '*.dxf'
-#		dirname == Blender.sys.dirname(Blender.Get('filename'))
+		dxfFileName.val = dxfPathName + dxfFileExt 
+#		dirname == sys.dirname(Blender.Get('filename'))
 #		update_RegistryKey('DirName', dirname)
 #		update_RegistryKey('dxfFileName', dxfFileName.val)
 		GUI_A['newScene_on'].val = 1
@@ -5994,45 +6056,55 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D')
 	elif (evt==EVENT_CHOOSE_DXF):
 		filename = '' # '*.dxf'
 		if dxfFileName.val:	filename = dxfFileName.val
-		Window.FileSelector(dxf_callback, "DXF-file Selection", filename)
+		Window.FileSelector(dxf_callback, "DXF/DWG-file Selection", filename)
 	elif (evt==EVENT_START):
 		dxfFile = dxfFileName.val
 		#print 'deb: dxfFile file: ', dxfFile #----------------------
 		if E_M: dxfFileName.val, dxfFile = e_mode(dxfFile) #evaluation mode
 		update_RegistryKey('dxfFileName', dxfFileName.val)
 		if dxfFile.lower().endswith('*.dxf'):
-			if Draw.PupMenu('DXF importer:  OK?|will import all DXF-files from:|%s' % dxfFile) == 1:
-				global UI_MODE
+			if Draw.PupMenu('DXF importer will import all DXF-files from:|%s|OK?' % dxfFile) != -1:
 				UI_MODE = False
-				multi_import(dxfFile[:-5])  # cut last 5 characters '*.dxf'
+				multi_import(dxfFile)
+				UI_MODE = True
 				Draw.Redraw()
-				#Draw.Exit()
-			else:
+
+		elif dxfFile.lower().endswith('*.dwg'):
+			if not extCONV_OK: Draw.PupMenu(extCONV_TEXT)
+			elif Draw.PupMenu('DWG importer will import all DWG-files from:|%s|OK?' % dxfFile) != -1:
+			#elif Draw.PupMenu('DWG importer will import all DWG-files from:|%s|Caution! overwrites existing DXF-files!| OK?' % dxfFile) != -1:
+				UI_MODE = False
+				multi_import(dxfFile)
+				UI_MODE = True
 				Draw.Redraw()
-		elif dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile):
-			print '\nStandard Mode: active'
-			if GUI_A['newScene_on'].val:
-				_dxf_file = dxfFile.split('/')[-1].split('\\')[-1]
-				_dxf_file = _dxf_file[:-4]  # cut last char:'.dxf'
-				_dxf_file = _dxf_file[:MAX_NAMELENGTH]  #? [-MAX_NAMELENGTH:])
-				global SCENE
-				SCENE = Blender.Scene.New(_dxf_file)
-				SCENE.makeCurrent()
-				Blender.Redraw()
-				#or so? Blender.Scene.makeCurrent(_dxf_file)
-				#sce = bpy.data.scenes.new(_dxf_file)
-				#bpy.data.scenes.active = sce
+				
+		elif sys.exists(dxfFile) and dxfFile.lower()[-4:] in ('.dxf','.dwg'):
+			if dxfFile.lower().endswith('.dwg') and (not extCONV_OK):
+				Draw.PupMenu(extCONV_TEXT)
 			else:
-				SCENE = Blender.Scene.GetCurrent()
-				SCENE.objects.selected = [] # deselect all
-			main(dxfFile)
-			#SCENE.objects.selected = SCENE.objects		 
-			#Window.RedrawAll()
-			#Blender.Redraw()
-			#Draw.Redraw()
+				#print '\nStandard Mode: active'
+				if GUI_A['newScene_on'].val:
+					_dxf_file = dxfFile.split('/')[-1].split('\\')[-1]
+					_dxf_file = _dxf_file[:-4]  # cut last char:'.dxf'
+					_dxf_file = _dxf_file[:MAX_NAMELENGTH]  #? [-MAX_NAMELENGTH:])
+					global SCENE
+					SCENE = Blender.Scene.New(_dxf_file)
+					SCENE.makeCurrent()
+					Blender.Redraw()
+					#or so? Blender.Scene.makeCurrent(_dxf_file)
+					#sce = bpy.data.scenes.new(_dxf_file)
+					#bpy.data.scenes.active = sce
+				else:
+					SCENE = Blender.Scene.GetCurrent()
+					SCENE.objects.selected = [] # deselect all
+				main(dxfFile)
+				#SCENE.objects.selected = SCENE.objects		 
+				#Window.RedrawAll()
+				#Blender.Redraw()
+				#Draw.Redraw()
 		else:
-			Draw.PupMenu('DXF importer:  Alert!%t|no valid DXF-file selected!')
-			print "DXF importer: error, no valid DXF-file selected! try again"
+			Draw.PupMenu('DXF importer: nothing imported!%t|no valid DXF-file selected!')
+			print "DXF importer: nothing imported, no valid DXF-file selected! try again"
 			Draw.Redraw()
 
 
@@ -6043,20 +6115,25 @@ def multi_import(DIR):
 	
 	"""
 	global SCENE
-	batchTIME = Blender.sys.time()
+	batchTIME = sys.time()
 	#if #DIR == "": DIR = os.path.curdir
-	if DIR == "": DIR = Blender.sys.dirname(Blender.Get('filename'))
-	print 'Multifiles Import from %s' %DIR
+	if DIR == "":
+		DIR = sys.dirname(Blender.Get('filename'))
+		EXT = '.dxf'
+	else:
+		EXT = DIR[-4:]  # get last 4 characters '.dxf'
+		DIR = DIR[:-5]  # cut last 5 characters '*.dxf'
+	print 'importing multiple %s files from %s' %(EXT,DIR)
 	files = \
-		[sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith('.dxf')] 
+		[sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith(EXT)] 
 	if not files:
-		print '...None DXF-files found. Abort!'
+		print '...None %s-files found. Abort!' %EXT
 		return
 	
 	i = 0
 	for dxfFile in files:
 		i += 1
-		print '\nDXF-file', i, 'of', len(files) #,'\nImporting', dxfFile
+		print '\n%s-file' %EXT, i, 'of', len(files) #,'\nImporting', dxfFile
 		if GUI_A['newScene_on'].val:
 			_dxf_file = dxfFile.split('/')[-1].split('\\')[-1]
 			_dxf_file = _dxf_file[:-4]  # cut last char:'.dxf'
@@ -6072,13 +6149,11 @@ def multi_import(DIR):
 		main(dxfFile)
 		#Blender.Redraw()
 
-	print 'TOTAL TIME: %.6f' % (Blender.sys.time() - batchTIME)
+	print 'TOTAL TIME: %.6f' % (sys.time() - batchTIME)
 	print '\a\r', # beep when done
+	Draw.PupMenu('DXF importer:	Done!|finished in %.4f sec.' % (sys.time() - batchTIME))
 
 
-
-UI_MODE = True
-
 if __name__ == "__main__":
 	UI_MODE = True
 	# recall last used DXF-file and INI-file names
@@ -6086,7 +6161,7 @@ if __name__ == "__main__":
 	#print 'deb:start dxffilename:', dxffilename #----------------
 	if dxffilename: dxfFileName.val = dxffilename
 	else:
-		dirname = Blender.sys.dirname(Blender.Get('filename'))
+		dirname = sys.dirname(Blender.Get('filename'))
 		#print 'deb:start dirname:', dirname #----------------
 		dxfFileName.val = sys.join(dirname, '')
 	inifilename = check_RegistryKey('iniFileName')
@@ -6099,7 +6174,7 @@ if __name__ == "__main__":
 if 1:
 	# DEBUG ONLY
 	UI_MODE = False
-	TIME= Blender.sys.time()
+	TIME= sys.time()
 	#DIR = '/dxf_r12_testfiles/'
 	DIR = '/metavr/'
 	import os
@@ -6128,5 +6203,5 @@ if 1:
 			dxfFileName.val = _dxf
 			main(_dxf)
 
-	print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
+	print 'TOTAL TIME: %.6f' % (sys.time() - TIME)
 """
\ No newline at end of file
diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py
index 42cdac4dc356404cb3b46f72f575a68ea72ed611..63da4606f3865f55cf81fd3aaf40c65d4ef31e72 100644
--- a/release/scripts/import_obj.py
+++ b/release/scripts/import_obj.py
@@ -537,6 +537,7 @@ def get_float_func(filepath):
 	'''
 	file= open(filepath, 'rU')
 	for line in file: #.xreadlines():
+		line = line.lstrip()
 		if line.startswith('v'): # vn vt v 
 			if ',' in line:
 				return lambda f: float(f.replace(',', '.'))
@@ -586,10 +587,11 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
 	# so we need to know weather 
 	multi_line_face= False
 	
-	print '\tpassing obj file "%s"...' % filepath,
+	print '\tparsing obj file "%s"...' % filepath,
 	time_sub= sys.time()
 	file= open(filepath, 'rU')
 	for line in file: #.xreadlines():
+		line = line.lstrip() # rare cases there is white space at the start of the line
 		
 		if line.startswith('v '):
 			line_split= line.split()
diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py
old mode 100755
new mode 100644
index 87a259cbe56b922ea647be078e84781f64b261be..fc3b5262376e09502702ab551e4d45d6ddaa6245
--- a/release/scripts/import_web3d.py
+++ b/release/scripts/import_web3d.py
@@ -1332,7 +1332,9 @@ class x3dNode(vrmlNode):
 	
 	# Other funcs operate from vrml, but this means we can wrap XML fields, still use nice utility funcs
 	# getFieldAsArray getFieldAsBool etc
-	def getFieldName(self, field):
+	def getFieldName(self, field, ancestry, AS_CHILD=False):
+		# ancestry and AS_CHILD are ignored, only used for VRML now
+		
 		self_real = self.getRealNode() # incase we're an instance
 		field_xml = self.x3dNode.getAttributeNode(field)
 		if field_xml:
@@ -1564,7 +1566,8 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry):
 	vcolor_spot = None # spot color when we dont have an array of colors
 	if vcolor:
 		# float to char
-		ifs_vcol = [[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)]
+		ifs_vcol = [(0,0,0)] # EEKADOODLE - vertex start at 1
+		ifs_vcol.extend([[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)])
 		ifs_color_index = geom.getFieldAsArray('colorIndex', 0, ancestry)
 		
 		if not ifs_vcol:
diff --git a/release/scripts/lightwave_export.py b/release/scripts/lightwave_export.py
index 458e61f3a28744feacd400176dba05db21024398..bbfb9649c6958cef1040c8bb54cebd586a1c6972 100644
--- a/release/scripts/lightwave_export.py
+++ b/release/scripts/lightwave_export.py
@@ -68,8 +68,13 @@ v5.5 format.
 # ***** END GPL LICENCE BLOCK *****
 
 import Blender
-import struct, cStringIO, operator
 import BPyMesh
+try: import struct
+except: struct = None
+try: import cStringIO
+except: cStringIO = None
+try: import operator
+except: operator = None
 
 VCOL_NAME = "\251 Per-Face Vertex Colors"
 DEFAULT_NAME = "\251 Blender Default"
@@ -95,12 +100,16 @@ def write(filename):
 	icon = "" #generate_icon()
 
 	meshes = []
+	mesh_object_name_lookup = {} # for name lookups only
+	
 	for obj in objects:
 		mesh = BPyMesh.getMeshFromObject(obj, None, True, False, scn)
 		if mesh:
 			mesh.transform(obj.matrixWorld)
 			meshes.append(mesh)
-
+			mesh_object_name_lookup[mesh] = obj.name
+	del obj
+	
 	material_names = get_used_material_names(meshes)
 	tags = generate_tags(material_names)
 	surfs = generate_surfs(material_names)
@@ -111,7 +120,7 @@ def write(filename):
 	layer_index = 0
 	
 	for mesh in meshes:
-		layr = generate_layr(obj.name, layer_index)
+		layr = generate_layr(mesh_object_name_lookup[mesh], layer_index)
 		pnts = generate_pnts(mesh)
 		bbox = generate_bbox(mesh)
 		pols = generate_pols(mesh)
@@ -149,7 +158,9 @@ def write(filename):
 		
 		layer_index += 1
 		mesh.verts = None # save some ram
-
+	
+	del mesh_object_name_lookup
+	
 	for surf in surfs:
 		chunks.append(surf)
 
@@ -345,23 +356,28 @@ def generate_vmad_vc(mesh):
 # === Generate Per-Face UV Coords (VMAD Chunk) ===
 # ================================================
 def generate_vmad_uv(mesh):
-	data = cStringIO.StringIO()
-	data.write("TXUV")                                       # type
-	data.write(struct.pack(">H", 2))                         # dimension
-	data.write(generate_nstring("Blender's UV Coordinates")) # name
+	layers = mesh.getUVLayerNames()
+	org_uv = mesh.activeUVLayer
+	for l in layers:
+		mesh.activeUVLayer = l
+		data = cStringIO.StringIO()
+		data.write("TXUV")                                       # type
+		data.write(struct.pack(">H", 2))                         # dimension
+		data.write(generate_nstring(l)) # name
+		for i, f in enumerate(mesh.faces):
+			if not i%100:
+				Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coordinates")
+			
+			uv = f.uv
+			f_v = f.v
+			for j in xrange(len(f)-1, -1, -1):             # Reverse order
+				U,V = uv[j]
+				v = f_v[j].index
+				data.write(struct.pack(">H", v)) # vertex index
+				data.write(struct.pack(">H", i)) # face index
+				data.write(struct.pack(">ff", U, V))
 	
-	for i, f in enumerate(mesh.faces):
-		if not i%100:
-			Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coordinates")
-		
-		uv = f.uv
-		f_v = f.v
-		for j in xrange(len(f)-1, -1, -1): 			# Reverse order
-			U,V = uv[j]
-			v = f_v[j].index
-			data.write(struct.pack(">H", v)) # vertex index
-			data.write(struct.pack(">H", i)) # face index
-			data.write(struct.pack(">ff", U, V))
+	mesh.activeUVLayer = org_uv
 	return data.getvalue()
 
 # ======================================
@@ -685,4 +701,7 @@ def fs_callback(filename):
 	if not filename.lower().endswith('.lwo'): filename += '.lwo'
 	write(filename)
 
-Blender.Window.FileSelector(fs_callback, "Export LWO", Blender.sys.makename(ext='.lwo'))
+if struct and cStringIO and operator:
+    Blender.Window.FileSelector(fs_callback, "Export LWO", Blender.sys.makename(ext='.lwo'))
+else:
+    Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/md2_export.py b/release/scripts/md2_export.py
index 588336ed4476a7776f174430b526bf0fe18bc366..cf5752597dad40c7996c00db47cc774cca0035ad 100644
--- a/release/scripts/md2_export.py
+++ b/release/scripts/md2_export.py
@@ -612,29 +612,9 @@ class md2_obj:
 ######################################################
 # Validation
 ######################################################
+
 def validation(object):
 	global user_frame_list
-
-	#move the object to the origin if it's not already there
-	if object.getLocation('worldspace')!=(0.0, 0.0, 0.0):
-		print "Model not centered at origin"
-		result=Blender.Draw.PupMenu("Model not centered at origin%t|Center (will not work with animations!)|Do not center")
-		if result==1:
-			object.setLocation(0.0,0.0,0.0)
-
-	#resize the object in case it is not the right size
-	if object.getSize('worldspace')!=(1.0,1.0,1.0):
-		print "Object is scaled-You should scale the mesh verts, not the object"
-		result=Blender.Draw.PupMenu("Object is scaled-You should scale the mesh verts, not the object%t|Fix scale (will not work with animations!)|Do not scale")
-		if result==1:
-			object.setSize(1.0,1.0,1.0)
-		
-	if object.getEuler('worldspace')!=Blender.Mathutils.Euler(0.0,0.0,0.0):
-		print "object.rot: ", object.getEuler('worldspace')
-		print "Object is rotated-You should rotate the mesh verts, not the object"
-		result=Blender.Draw.PupMenu("Object is rotated-You should rotate the mesh verts, not the object%t|Fix rotation (will not work with animations!)|Do not rotate")
-		if result==1:
-			object.setEuler([0.0,0.0,0.0])
 	
 	#get access to the mesh data
 	mesh=object.getData(False, True) #get the object (not just name) and the Mesh, not NMesh
@@ -696,7 +676,8 @@ def validation(object):
 				result=Blender.Draw.PupMenu("Model has more than 1 texture map assigned%t|Quit")
 				#return False
 		if mesh_image:
-			size=mesh_image.getSize()
+			try:		size=mesh_image.getSize()
+			except:	size= 256,256 # No image data
 			#is this really what the user wants
 			if (size[0]!=256 or size[1]!=256):
 				print "Texture map size is non-standard (not 256x256), it is: ",size[0],"x",size[1]
@@ -753,6 +734,8 @@ def fill_md2(md2, object):
 	#create the vertex list from the first frame
 	Blender.Set("curframe", 1)
 	
+	has_uvs = mesh.faceUV
+	
 	#header information
 	md2.ident=844121161
 	md2.version=8	
@@ -761,9 +744,11 @@ def fill_md2(md2, object):
 
 	#get the skin information
 	#use the first faces' image for the texture information
-	if mesh.faceUV:
+	if has_uvs:
 		mesh_image=mesh.faces[0].image
-		size=mesh_image.getSize()
+		try:		size=mesh_image.getSize()
+		except:	size= 256,256
+		
 		md2.skin_width=size[0]
 		md2.skin_height=size[1]
 		md2.num_skins=1
@@ -777,12 +762,14 @@ def fill_md2(md2, object):
 
 	#put texture information in the md2 structure
 	#build UV coord dictionary (prevents double entries-saves space)
+	if not has_uvs:
+		t=(0,0)
+	
 	for face in mesh.faces:
 		for i in xrange(0,3):
-			if mesh.faceUV:
+			if has_uvs:
 				t=(face.uv[i])
-			else:
-				t=(0,0)
+				
 			tex_key=(t[0],t[1])
 			if not tex_list.has_key(tex_key):
 				tex_list[tex_key]=tex_count
@@ -798,16 +785,25 @@ def fill_md2(md2, object):
 
 	#put faces in the md2 structure
 	#for each face in the model
+	
+	if not has_uvs:
+		uv_coords=[(0,0)]*3
+	
 	for this_face in xrange(0, md2.num_faces):
 		md2.faces.append(md2_face())
+		mf = mesh.faces[this_face]
+		mf_v = mf.v
+		if has_uvs:
+			uv_coords = mf.uv
+		
 		for i in xrange(0,3):
 			#blender uses indexed vertexes so this works very well
-			md2.faces[this_face].vertex_index[i]=mesh.faces[this_face].verts[i].index
+			md2.faces[this_face].vertex_index[i] = mf_v[i].index
 			#lookup texture index in dictionary
-			if mesh.faceUV:
-				uv_coord=(mesh.faces[this_face].uv[i])
-			else:
-				uv_coord=(0,0)
+			if has_uvs:
+				uv_coord = uv_coords[i]
+			# otherwise we set it before
+				
 			tex_key=(uv_coord[0],uv_coord[1])
 			tex_index=tex_list[tex_key]
 			md2.faces[this_face].texture_index[i]=tex_index
@@ -837,13 +833,18 @@ def fill_md2(md2, object):
 	for frame_counter in xrange(0,md2.num_frames):
 		
 		progress+=progressIncrement
-		Blender.Window.DrawProgressBar(progress, "Calculating Frame: "+str(frame_counter))
+		Blender.Window.DrawProgressBar(progress, "Calculating Frame: %d of %d" % (frame_counter, md2.num_frames))
 			
 		#add a frame
 		md2.frames.append(md2_frame())
 		#update the mesh objects vertex positions for the animation
 		Blender.Set("curframe", frame_counter)  #set blender to the correct frame
-		mesh.getFromObject(object.name)  #update the mesh to make verts current
+		
+		
+		
+		
+		mesh.getFromObject(object)  #update the mesh to make verts current
+		mesh.transform(object.matrixWorld)
 		
 #each frame has a scale and transform value that gets the vertex value between 0-255
 #since the scale and transform are the same for the all the verts in the frame, we only need
@@ -862,13 +863,14 @@ def fill_md2(md2, object):
 		frame_max_z=-100000.0
 	
 		for face in mesh.faces:
-			for vert in face.verts:					
-				if frame_min_x>vert.co[1]: frame_min_x=vert.co[1]
-				if frame_max_x<vert.co[1]: frame_max_x=vert.co[1]
-				if frame_min_y>vert.co[0]: frame_min_y=vert.co[0]
-				if frame_max_y<vert.co[0]: frame_max_y=vert.co[0]
-				if frame_min_z>vert.co[2]: frame_min_z=vert.co[2]
-				if frame_max_z<vert.co[2]: frame_max_z=vert.co[2]
+			for vert in face:
+				co = vert.co
+				if frame_min_x>co[1]: frame_min_x=co[1]
+				if frame_max_x<co[1]: frame_max_x=co[1]
+				if frame_min_y>co[0]: frame_min_y=co[0]
+				if frame_max_y<co[0]: frame_max_y=co[0]
+				if frame_min_z>co[2]: frame_min_z=co[2]
+				if frame_max_z<co[2]: frame_max_z=co[2]
 		
 		#the scale is the difference between the min and max (on that axis) / 255
 		frame_scale_x=(frame_max_x-frame_min_x)/255
@@ -896,9 +898,10 @@ def fill_md2(md2, object):
 			#then translates the point so it's not less than 0
 			#then scale it so it's between 0..255
 			#print "frame scale : ", frame_scale_x, " ", frame_scale_y, " ", frame_scale_z
-			new_x=int((mesh.verts[vert_counter].co[1]-frame_trans_x)/frame_scale_x)
-			new_y=int((mesh.verts[vert_counter].co[0]-frame_trans_y)/frame_scale_y)
-			new_z=int((mesh.verts[vert_counter].co[2]-frame_trans_z)/frame_scale_z)
+			co = mesh.verts[vert_counter].co
+			new_x=int((co[1]-frame_trans_x)/frame_scale_x)
+			new_y=int((co[0]-frame_trans_y)/frame_scale_y)
+			new_z=int((co[2]-frame_trans_z)/frame_scale_z)
 			#put them in the structure
 			md2.frames[frame_counter].vertices[vert_counter].vertices=(new_x, new_y, new_z)
 
@@ -908,14 +911,14 @@ def fill_md2(md2, object):
 
 			
 			#swap y and x for difference in axis orientation 
-			x1=-mesh.verts[vert_counter].no[1]
-			y1=mesh.verts[vert_counter].no[0]
-			z1=mesh.verts[vert_counter].no[2]
+			no = mesh.verts[vert_counter].no
+			x1=	-no[1]
+			y1=	 no[0]
+			z1=	 no[2]
+			
 			for j in xrange(0,162):
 				#dot = (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
-				dot = (x1*MD2_NORMALS[j][0]+
-				       y1*MD2_NORMALS[j][1]+
-							 z1*MD2_NORMALS[j][2]);
+				dot = (x1*MD2_NORMALS[j][0] + y1*MD2_NORMALS[j][1]+ z1*MD2_NORMALS[j][2]);
 				if (dot > maxdot):
 					maxdot = dot;
 					maxdotindex = j;
diff --git a/release/scripts/object_active_to_other.py b/release/scripts/object_active_to_other.py
new file mode 100644
index 0000000000000000000000000000000000000000..131d1f63d74a72fda5c2936547cf751653a38330
--- /dev/null
+++ b/release/scripts/object_active_to_other.py
@@ -0,0 +1,58 @@
+#!BPY
+"""
+Name: 'Copy Active to Selected'
+Blender: 249
+Group: 'Object'
+Tooltip: 'For every selected object, copy the active to their loc/size/rot'
+"""
+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Script copyright (C) Campbell Barton
+#
+# 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 2
+# 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, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+
+from Blender import Window, sys, Draw
+import bpy
+
+def my_object_util(sce):
+	ob_act = sce.objects.active
+	
+	if not ob_act:
+		Draw.PupMenu('Error%t|No active object selected')
+		return
+	
+	mats = [ob.matrixWorld for ob in sce.objects.context if ob != ob_act]
+	
+	for m in mats:
+		ob_copy = ob_act.copy()
+		sce.objects.link(ob_copy)
+		ob_copy.setMatrix(m)
+		ob_copy.Layers = ob.Layers
+		
+
+def main():
+	sce = bpy.data.scenes.active
+	
+	Window.WaitCursor(1)
+	my_object_util(sce)
+	Window.WaitCursor(0)
+
+if __name__ == '__main__':
+	main()
diff --git a/release/scripts/object_cookie_cutter.py b/release/scripts/object_cookie_cutter.py
index 2a6e0ad6b2e00701d25dd2875214ddc90ce7f43e..4950c18c0f49fb531511c3e9b2e00cafc286c11f 100644
--- a/release/scripts/object_cookie_cutter.py
+++ b/release/scripts/object_cookie_cutter.py
@@ -10,7 +10,7 @@ __url__= ["blender", "blenderartist"]
 __version__= "1.0"
 
 __bpydoc__= """\
-This script takes the selected mesh objects, devides them into 2 groups
+This script takes the selected mesh objects, divides them into 2 groups
 Cutters and The objects to be cut.
 
 Cutters are meshes with no faces, just edge loops. and any meshes with faces will be cut.
@@ -128,14 +128,14 @@ def sorted_indicies(i1, i2):
 
 def fake_length2d(pt1, pt2):
 	'''
-	Only used for comparison so dont sqrt
+	Only used for comparison so don't sqrt
 	'''
 	#return math.sqrt(abs(pow(x1-x2, 2)+ pow(y1-y2, 2)))
 	return pow(pt1[0]-pt2[0], 2) + pow(pt1[1]- pt2[1], 2)
 
 def length2d(pt1, pt2):
 	'''
-	Only used for comparison so dont sqrt
+	Only used for comparison so don't sqrt
 	'''
 	#return math.sqrt(abs(pow(x1-x2, 2)+ pow(y1-y2, 2)))
 	return sqrt(pow(pt1[0]-pt2[0], 2) + pow(pt1[1]- pt2[1], 2))
@@ -150,7 +150,7 @@ def tri_area_2d(v1, v2, v3):
 	return 0.25 * sqrt(abs(p*(p-2*e1)*(p-2*e2)*(p-2*e3)))
 
 def tri_pt_find_z_2d(pt, tri):
-	""" Takes a face and 3d vector and assigns teh vectors Z to its on the face"""
+	""" Takes a face and 3d vector and assigns the vectors Z to its on the face"""
 	
 	l1= tri_area_2d(tri[1], tri[2], pt)
 	l2= tri_area_2d(tri[0], tri[2], pt)
@@ -170,7 +170,7 @@ def tri_pt_find_z_2d(pt, tri):
 
 
 def tri_pt_find_uv_2d(pt, tri, uvs):
-	""" Takes a face and 3d vector and assigns teh vectors Z to its on the face"""
+	""" Takes a face and 3d vector and assigns the vectors Z to its on the face"""
 	
 	l1= tri_area_2d(tri[1], tri[2], pt)
 	l2= tri_area_2d(tri[0], tri[2], pt)
@@ -288,12 +288,12 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
 			# Loop through the cutter edges.
 			for ei_c, ed_c in enumerate(me_c.edges):
 				# If the cutter edge has 2 verts inside the same face then we can ignore it
-				# Bothe are different faces or None
+				# Both are different faces or None
 				if cut_vert_terrain_faces[ed_c.v1.index] != cut_vert_terrain_faces[ed_c.v2.index] or\
 				cut_vert_terrain_faces[ed_c.v1.index] == cut_vert_terrain_faces[ed_c.v2.index] == None:
 					eb_c= c.edge_bounds[ei_c]
 					if bounds_intersect(eb_t, eb_c): # face/edge bounds intersect?
-						# Now we know the 2 edges might intersect, we'll do a propper test
+						# Now we know the 2 edges might intersect, we'll do a proper test
 						
 						x= LineIntersect2D(ed_t.v1.co, ed_t.v2.co,   ed_c.v1.co, ed_c.v2.co)					
 						if x:
@@ -340,7 +340,7 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
 		for f in faces:
 			faces_intersecting.setdefault(f.index, []).append(ed_isect)
 	
-	# this list is used to store edges that are totaly inside a face ( no intersections with terrain)
+	# this list is used to store edges that are totally inside a face ( no intersections with terrain)
 	# we can remove these as we
 	face_containing_edges= [[] for i in xrange(len(me_t.faces))]
 	for ed_c in me_c.edges:
@@ -412,8 +412,8 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
 		
 		
 		
-		# edges that dont have a vert in the face have to span between to intersection points
-		# since we dont know the other point at any 1 time we need to remember edges that 
+		# edges that don't have a vert in the face have to span between to intersection points
+		# since we don't know the other point at any 1 time we need to remember edges that 
 		# span a face and add them once we'v collected both
 		# first add outline edges
 		edge_span_face= {}
@@ -507,7 +507,7 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
 						# 0,2,3
 						f_uv_mod= f_uv[0], f_uv[2], f_uv[3]
 						f_vco_mod= f_vco[0], f_vco[2], f_vco[3]
-					# else - side of 0,1,2 - dont modify the quad
+					# else - side of 0,1,2 - don't modify the quad
 				
 				uvs[i]= tri_pt_find_uv_2d(v_co, f_vco_mod, f_uv_mod)	
 			
@@ -579,7 +579,7 @@ def main():
 	for ob in obs:
 		if ob.type == 'Mesh':
 			me= ob.getData(mesh=1)
-		elif ob.data.flag & 1: # Is the curve 3D? else dont use.
+		elif ob.data.flag & 1: # Is the curve 3D? else don't use.
 			me= BPyMesh.getMeshFromObject(ob) # get the curve
 		else:
 			continue
diff --git a/release/scripts/scripttemplate_gamelogic.py b/release/scripts/scripttemplate_gamelogic.py
index 01348e86d0a04fe2830db82aee26840e562fb02d..8711783a5f869268c159b08510abdce8bc720d4a 100644
--- a/release/scripts/scripttemplate_gamelogic.py
+++ b/release/scripts/scripttemplate_gamelogic.py
@@ -29,58 +29,58 @@ def main():
 	cont = GameLogic.getCurrentController()
 	
 	# The KX_GameObject that owns this controller.
-	own = cont.getOwner()
+	own = cont.owner
 	
 	# for scripts that deal with spacial logic
-	own_pos = own.getPosition() 
+	own_pos = own.worldPosition
 	
 	
 	# Some example functions, remove to write your own script.
 	# check for a positive sensor, will run on any object without errors.
-	print 'Logic info for KX_GameObject', own.getName()
+	print 'Logic info for KX_GameObject', own.name
 	input = False
 	
-	for sens in cont.getSensors():
+	for sens in cont.sensors:
 		# The sensor can be on another object, we may want to use it
-		own_sens = sens.getOwner()
-		print '    sensor:', sens.getName(),
-		if sens.isPositive():
+		own_sens = sens.owner
+		print '    sensor:', sens.name,
+		if sens.positive:
 			print '(true)'
 			input = True
 		else:
 			print '(false)'
 	
-	for actu in cont.getActuators():
+	for actu in cont.actuators:
 		# The actuator can be on another object, we may want to use it
-		own_actu = actu.getOwner()
-		print '    actuator:', actu.getName()
+		own_actu = actu.owner
+		print '    actuator:', actu.name
 		
 		# This runs the actuator or turns it off
 		# note that actuators will continue to run unless explicitly turned off.
 		if input:
-			GameLogic.addActiveActuator(actu, True)
+			cont.activate(actu)
 		else:
-			GameLogic.addActiveActuator(actu, False)
+			cont.deactivate(actu)
 	
-	# Its also good practice to get sensors and actuators by names
-	# so any changes to their order wont break the script.
+	# Its also good practice to get sensors and actuators by name
+	# rather then index so any changes to their order wont break the script.
 	
-	# sens_key = cont.getSensor('key_sensor')
-	# actu_motion = cont.getActuator('motion')
+	# sens_key = cont.sensors['key_sensor']
+	# actu_motion = cont.actuators['motion']
 	
 	
 	# Loop through all other objects in the scene
 	sce = GameLogic.getCurrentScene()
-	print 'Scene Objects:', sce.getName()
-	for ob in sce.getObjectList():
-		print '   ', ob.getName(), ob.getPosition()
+	print 'Scene Objects:', sce.name
+	for ob in sce.objects:
+		print '   ', ob.name, ob.worldPosition
 	
 	
 	# Example where collision objects are checked for their properties
 	# adding to our objects "life" property
 	"""
-	actu_collide = cont.getSensor('collision_sens')
-	for ob in actu_collide.getHitObjectList():
+	actu_collide = cont.sensors['collision_sens']
+	for ob in actu_collide.objectHitList:
 		# Check to see the object has this property
 		if hasattr(ob, 'life'):
 			own.life += ob.life
diff --git a/release/scripts/scripttemplate_gamelogic_basic.py b/release/scripts/scripttemplate_gamelogic_basic.py
index 1584659d3176f13130ff84dcc673f34181568f58..fd404d5c8a45f17e5975c224c7d8d01b39fdc7f1 100644
--- a/release/scripts/scripttemplate_gamelogic_basic.py
+++ b/release/scripts/scripttemplate_gamelogic_basic.py
@@ -1,7 +1,7 @@
 #!BPY
 """
 Name: 'GameLogic Template'
-Blender: 245
+Blender: 249
 Group: 'ScriptTemplate'
 Tooltip: 'Basic template for new game logic scripts'
 """
@@ -14,15 +14,15 @@ script_data = \
 def main():
 
 	cont = GameLogic.getCurrentController()
-	own = cont.getOwner()
+	own = cont.owner
 	
-	sens = cont.getSensor('mySensor')
-	actu = cont.getActuator('myActuator')
+	sens = cont.sensors['mySensor']
+	actu = cont.actuators['myActuator']
 	
-	if sens.isPositive():
-		GameLogic.addActiveActuator(actu, True)
+	if sens.positive:
+		cont.activate(actu)
 	else:
-		GameLogic.addActiveActuator(actu, False)
+		cont.deactivate(actu)
 
 main()
 '''
diff --git a/release/scripts/vertexpaint_selfshadow_ao.py b/release/scripts/vertexpaint_selfshadow_ao.py
index 95ba7d2fb23c600ef84e96228d2364b934a73c2c..d641fd12111d00dbf3a1313a556fdcab0f3902ae 100644
--- a/release/scripts/vertexpaint_selfshadow_ao.py
+++ b/release/scripts/vertexpaint_selfshadow_ao.py
@@ -180,6 +180,10 @@ def main():
 	
 	t= sys.time()
 	vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_RADIUS, PREF_MIN_EDLEN, PREF_CLAMP_CONCAVE, PREF_CLAMP_CONVEX, PREF_SHADOW_ONLY, PREF_SEL_ONLY)
+	
+	if ob.modifiers:
+		me.update()
+	
 	print 'done in %.6f' % (sys.time()-t)
 if __name__=='__main__':
 	main()
diff --git a/release/scripts/wizard_bolt_factory.py b/release/scripts/wizard_bolt_factory.py
new file mode 100644
index 0000000000000000000000000000000000000000..572cd763c1874fac848c6d9d77f816dffe644205
--- /dev/null
+++ b/release/scripts/wizard_bolt_factory.py
@@ -0,0 +1,3041 @@
+#!BPY
+
+"""
+Name: 'Bolt Factory'
+Blender: 249
+Group: 'Wizards'
+Tooltip: 'Create models of various types to screw fasteners.'
+"""
+
+__author__ = " Aaron Keith (Spudmn) "
+__version__ = "1.50 "
+__url__ = ["blender", "http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Misc/Bolt_Factory"]
+__email__= [""]
+__bpydoc__ = """\
+Bolt_Factory.py 
+
+Bolt Factory is a Python script for Blender 3D.
+
+The script allows the user to create models of various types to screw fasteners.
+
+This version is very much a work in progress.
+
+This is my first attempt to program in Python.  This version is unpolished and
+doesn't do much error checking.  Therefore if the user sets strange
+variable the model created will be as equally strange.
+
+For best results set the material to smooth and apply a Edge Split modifier
+with default settings.
+
+To Do:
+Better error checking.
+Nuts to go with the bolts.
+Pre-sets for common bolts.
+Improved GUI.
+More Head and Bit types. 
+Better documentation.
+Fix error with mesh when using crest and root percent other than 10.
+
+
+"""
+
+# -------------------------------------------------------------------------- 
+# Bolt_Factory.py 
+# -------------------------------------------------------------------------- 
+# ***** BEGIN GPL LICENSE BLOCK ***** 
+# 
+# Copyright (C) 2008: Aaron Keith
+# 
+# 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 2 
+# 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, write to the Free Software Foundation, 
+# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
+# 
+# ***** END GPL LICENCE BLOCK ***** 
+# -------------------------------------------------------------------------- 
+
+
+
+
+import Blender
+from Blender import Draw, BGL,Mesh
+from Blender import *
+from math import *
+from Blender import Mathutils
+from Blender.Mathutils import *
+
+
+Global_NutRad = 0.0
+MAX_INPUT_NUMBER = 50
+
+No_Event,On_Preset_Click,On_Apply_Click,On_Create_Click,On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click,On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click,On_Exit_Click,On_Model_Bolt_Click,On_Model_Nut_Click,On_Hex_Nut_Click,On_Lock_Nut_Click,On_Test_Click = range(17)  # this is like a ENUM
+
+
+Head_Type={'HEX' : [Draw.Create(1),On_Hex_Click],
+           'CAP' : [Draw.Create(0),On_Cap_Click],
+           'DOME': [Draw.Create(0),On_Dome_Click],
+           'PAN' : [Draw.Create(0),On_Pan_Click]}
+
+
+Bit_Type={'NONE' : [Draw.Create(1),On_Bit_None_Click],
+           'ALLEN' : [Draw.Create(0),On_Bit_Allen_Click],
+           'PHILLIPS': [Draw.Create(0),On_Bit_Philips_Click]}
+
+Model_Type={'BOLT' : [Draw.Create(1),On_Model_Bolt_Click],
+           'NUT' : [Draw.Create(0),On_Model_Nut_Click]}
+
+Nut_Type={'HEX' : [Draw.Create(1),On_Hex_Nut_Click],
+           'LOCK' : [Draw.Create(0),On_Lock_Nut_Click]}
+
+
+
+Phillips_Bit_Depth = Draw.Create(1.0)
+Philips_Bit_Dia = Draw.Create(1.75)
+
+Allen_Bit_Depth = Draw.Create(1.0)
+Allen_Bit_Flat_Distance = Draw.Create(1.25)
+
+Hex_Head_Height = Draw.Create(1.0)
+Hex_Head_Flat_Distance = Draw.Create(2.25)
+
+Cap_Head_Dia = Draw.Create(2.25)
+Cap_Head_Height = Draw.Create(1.5)
+Cap_Head_Inside_Rad = 0.0
+
+Dome_Head_Dia = Draw.Create(3.75)
+
+Pan_Head_Dia = Draw.Create(5.375)
+
+Shank_Dia = Draw.Create(1.5)
+Shank_Length = Draw.Create(0.125)
+
+Thread_Length = Draw.Create(2.5)
+Major_Dia = Draw.Create(1.5)
+Minor_Dia = Draw.Create(1.25)
+Pitch = Draw.Create(0.125)
+Crest_Percent = Draw.Create(1.25)
+Root_Percent = Draw.Create(1.25)
+
+Hex_Nut_Height = Draw.Create(1.0)
+Hex_Nut_Flat_Distance = Draw.Create(2.25)
+
+Preset_Menu = Draw.Create(0.25)
+Preset_Length = Draw.Create(1.5)
+
+
+##########################################################################################
+##########################################################################################
+##                    Miscellaneous Utilities
+##########################################################################################
+##########################################################################################
+
+
+def Rot_Mesh(verts,matrix):
+        ret = []
+        for v in verts:
+            vec = Vector(v) * matrix
+            ret.append([vec.x,vec.y,vec.z])
+        return ret
+
+def Copy_Faces(faces,offset):        
+    ret = []
+    for f in faces:
+        fsub = []
+        for i in range(len(f)):
+            fsub.append(f[i]+ offset)
+        ret.append(fsub)
+    return ret
+
+def Move_Verts_Up_Z(VERTS,DISTANCE):        
+    ret = []
+    for v in VERTS:
+        ret.append([v[0],v[1],v[2]+DISTANCE])
+    return ret
+
+
+def SpinDup(VERTS,FACES,DEGREE,DIVISIONS,AXIS):
+    verts=[]
+    faces=[]
+    
+    if DIVISIONS == 0:
+       DIVISIONS = 1  
+  
+    step = DEGREE/DIVISIONS # set step so pieces * step = degrees in arc
+    
+    for i in range(int(DIVISIONS)):
+        rotmat = Mathutils.RotationMatrix(step*i, 4, AXIS) # 4x4 rotation matrix, 30d about the x axis.
+        Rot = Rot_Mesh(VERTS,rotmat)
+        faces.extend(Copy_Faces(FACES,len(verts)))    
+        #print faces
+        verts.extend(Rot)
+    return verts,faces
+
+
+def Mirror_Verts(VERTS,AXIS):
+    ret = []
+    for v in VERTS:
+        ret.append([0-v[0],v[1],v[2]]) 
+    return ret
+
+
+def Mirror_Verts_Faces(VERTS,FACES,AXIS,FLIP_POINT =0):
+    ret_vert = []
+    ret_face = []
+    offset = len(VERTS)    
+    if AXIS == 'y':
+        for v in VERTS:
+            Delta = v[0] - FLIP_POINT
+            ret_vert.append([FLIP_POINT-Delta,v[1],v[2]]) 
+    if AXIS == 'x':
+        for v in VERTS:
+            Delta = v[1] - FLIP_POINT
+            ret_vert.append([v[0],FLIP_POINT-Delta,v[2]]) 
+    if AXIS == 'z':
+        for v in VERTS:
+            Delta = v[2] - FLIP_POINT
+            ret_vert.append([v[0],v[1],FLIP_POINT-Delta]) 
+            
+    for f in FACES:
+        fsub = []
+        for i in range(len(f)):
+            fsub.append(f[i]+ offset)
+        fsub.reverse() # filp the order to make norm point out
+        ret_face.append(fsub)
+            
+    return ret_vert,ret_face
+
+def Lath(tool_V1,tool_V2,verts,faces):
+    
+    #verts = []
+    #faces = []f
+       
+    #verts.append([7.0,6.0,0.0])
+    #verts.append([7.0+10,6.0-10,0.0])
+    #faces.append([3,4])
+        
+    vec1 = Vector(verts[-1])
+    vec2 = Vector(verts[-2])
+    
+    VecOut1,VecR2 = LineIntersect(vec1, vec2,Vector(tool_V1), Vector(tool_V2))
+    
+    vec1 = Vector(verts[-2])
+    vec2 = Vector(verts[-3])
+    
+    VecOut2,VecR2 = LineIntersect(vec1, vec2,Vector(tool_V1), Vector(tool_V2))
+    
+    if VecOut1 != None:
+        if VecOut1 == VecOut2:
+            #print "got it"
+            faces.append([len(verts),len(verts)+1])
+            verts.append([VecOut1.x,VecOut1.y,VecOut1.z])
+            verts.append([VecOut2.x,VecOut2.y,VecOut2.z])
+            #print verts[-1]
+            #print verts[-2]
+    
+    return verts,faces
+
+
+def Build_Face_List_Quads(OFFSET,COLUM,ROW,FLIP = 0):
+    Ret =[]
+    RowStart = 0;
+    for j in range(ROW):
+        for i in range(COLUM):
+            Res1 = RowStart + i;
+            Res2 = RowStart + i + (COLUM +1)
+            Res3 = RowStart + i + (COLUM +1) +1
+            Res4 = RowStart+i+1
+            if FLIP:
+                Ret.append([OFFSET+Res1,OFFSET+Res2,OFFSET+Res3,OFFSET+Res4])
+            else:
+                Ret.append([OFFSET+Res4,OFFSET+Res3,OFFSET+Res2,OFFSET+Res1])
+        RowStart += COLUM+1
+    return Ret
+
+
+
+def Fill_Ring_Face(OFFSET,NUM,FACE_DOWN = 0):
+    Ret =[]
+    Face = [1,2,0]
+    TempFace = [0,0,0]
+    A = 0
+    B = 1
+    C = 2
+    if NUM < 3:
+        return None
+    for i in range(NUM-2):
+        if (i%2):
+            TempFace[0] = Face[C];
+            TempFace[1] = Face[C] + 1;
+            TempFace[2] = Face[B];
+            if FACE_DOWN:
+                Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
+            else:
+                Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
+        else:
+            TempFace[0] =Face[C];
+            if Face[C] == 0:
+                TempFace[1] = NUM-1; 
+            else:
+                TempFace[1] = Face[C] - 1;
+            TempFace[2] = Face[B];
+            if FACE_DOWN:
+                Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
+            else:
+                Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
+        
+        Face[0] = TempFace[0]
+        Face[1] = TempFace[1]
+        Face[2] = TempFace[2]
+    return Ret
+    
+
+def Flat_To_Radius(FLAT):
+    h = (float(FLAT)/2)/cos(radians(30))
+    #print h
+    return h
+
+
+
+##########################################################################################
+##########################################################################################
+##                    Error Checking
+##########################################################################################
+##########################################################################################
+
+
+def Error_Check():
+
+    #global Phillips_Bit_Depth 
+    #global Philips_Bit_Dia 
+
+    #global Allen_Bit_Depth 
+    #global Allen_Bit_Flat_Distance 
+
+    #global Hex_Head_Height 
+    #global Hex_Head_Flat_Distance 
+
+    #global Cap_Head_Dia 
+    #global Cap_Head_Height 
+    
+
+    #global Dome_Head_Dia 
+
+    #global Pan_Head_Dia 
+
+    #global Shank_Dia 
+    #global Shank_Length 
+
+    global Thread_Length
+    global Major_Dia 
+    global Minor_Dia 
+    global Pitch 
+    #global Crest_Percent 
+    #global Root_Percent 
+
+    Error_Result = 0
+    
+    if Minor_Dia.val >= Major_Dia.val:
+        error_txt = "Error%t|Major Dia must be larger than Minor Dia"
+        Blender.Draw.PupMenu(error_txt)
+        print error_txt
+        Error_Result = TRUE  
+
+    elif (Pitch.val*7.0) > Thread_Length.val:
+        error_txt =  "Error%t|Thread length must be at least 7 times the pitch"
+        Blender.Draw.PupMenu(error_txt)
+        print error_txt
+        Error_Result = TRUE  
+    return Error_Result 
+
+
+
+
+
+
+
+
+
+
+##########################################################################################
+##########################################################################################
+##                    Create Allen Bit
+##########################################################################################
+##########################################################################################
+
+
+
+def Allen_Fill(OFFSET,FLIP= 0):
+    faces = []
+    Lookup = [[19,1,0],
+              [19,2,1],
+              [19,3,2],
+              [19,20,3],
+              [20,4,3],
+              [20,5,4],
+              [20,6,5],
+              [20,7,6],
+              [20,8,7],
+              [20,9,8],
+              
+              [20,21,9],
+              
+              [21,10,9],
+              [21,11,10],
+              [21,12,11],
+              [21,13,12],
+              [21,14,13],
+              [21,15,14],
+              
+              [21,22,15],
+              [22,16,15],
+              [22,17,16],
+              [22,18,17]
+              ]
+    for i in Lookup:
+        if FLIP:
+            faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
+        else:
+            faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
+            
+    return faces
+
+
+
+def Create_Allen_Bit(FLAT_DISTANCE,HEIGHT):
+    Div = 36
+    verts = []
+    faces = []
+    
+    Flat_Radius = (float(FLAT_DISTANCE)/2)/cos(radians(30))
+    OUTTER_RADIUS = Flat_Radius * 1.05
+    Outter_Radius_Height = Flat_Radius * (0.1/5.77)
+    FaceStart_Outside = len(verts)
+    Deg_Step = 360.0 /float(Div)
+    
+    for i in range((Div/2)+1):    # only do half and mirror later
+        x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+        y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+        verts.append([x,y,0])
+    
+    FaceStart_Inside = len(verts)
+        
+    Deg_Step = 360.0 /float(6) 
+    for i in range((6/2)+1): 
+        x = sin(radians(i*Deg_Step))* Flat_Radius
+        y = cos(radians(i*Deg_Step))* Flat_Radius
+        verts.append([x,y,0-Outter_Radius_Height])     
+     
+    faces.extend(Allen_Fill(FaceStart_Outside,0))
+    
+    
+    FaceStart_Bottom = len(verts)
+    
+    Deg_Step = 360.0 /float(6) 
+    for i in range((6/2)+1): 
+        x = sin(radians(i*Deg_Step))* Flat_Radius
+        y = cos(radians(i*Deg_Step))* Flat_Radius
+        verts.append([x,y,0-HEIGHT])     
+        
+    faces.extend(Build_Face_List_Quads(FaceStart_Inside,3,1,TRUE))
+    faces.extend(Fill_Ring_Face(FaceStart_Bottom,4))
+    
+    
+    M_Verts,M_Faces = Mirror_Verts_Faces(verts,faces,'y')
+    verts.extend(M_Verts)
+    faces.extend(M_Faces)
+    
+    return verts,faces,OUTTER_RADIUS * 2
+
+
+##########################################################################################
+##########################################################################################
+##                    Create Phillips Bit
+##########################################################################################
+##########################################################################################
+
+
+def Phillips_Fill(OFFSET,FLIP= 0):
+    faces = []
+    Lookup = [[0,1,10],
+              [1,11,10],
+              [1,2,11],
+              [2,12,11],
+              
+              [2,3,12],
+              [3,4,12],
+              [4,5,12],
+              [5,6,12],
+              [6,7,12],
+              
+              [7,13,12],
+              [7,8,13],
+              [8,14,13],
+              [8,9,14],
+              
+              
+              [10,11,16,15],
+              [11,12,16],
+              [12,13,16],
+              [13,14,17,16],
+              [15,16,17,18]
+              
+              
+              ]
+    for i in Lookup:
+        if FLIP:
+            if len(i) == 3:
+                faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
+            else:    
+                faces.append([OFFSET+i[3],OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
+        else:
+            if len(i) == 3:
+                faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
+            else:
+                faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2],OFFSET+i[3]])
+    return faces
+
+
+
+def Create_Phillips_Bit(FLAT_DIA,FLAT_WIDTH,HEIGHT):
+    Div = 36
+    verts = []
+    faces = []
+    
+    FLAT_RADIUS = FLAT_DIA * 0.5
+    OUTTER_RADIUS = FLAT_RADIUS * 1.05
+    
+    Flat_Half = float(FLAT_WIDTH)/2.0
+        
+    FaceStart_Outside = len(verts)
+    Deg_Step = 360.0 /float(Div)
+    for i in range((Div/4)+1):    # only do half and mirror later
+        x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+        y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+        verts.append([x,y,0])
+    
+        
+    FaceStart_Inside = len(verts)
+    verts.append([0,FLAT_RADIUS,0]) #10
+    verts.append([Flat_Half,FLAT_RADIUS,0]) #11
+    verts.append([Flat_Half,Flat_Half,0])     #12
+    verts.append([FLAT_RADIUS,Flat_Half,0])    #13
+    verts.append([FLAT_RADIUS,0,0])            #14
+
+ 
+    verts.append([0,Flat_Half,0-HEIGHT])        #15
+    verts.append([Flat_Half,Flat_Half,0-HEIGHT])    #16
+    verts.append([Flat_Half,0,0-HEIGHT])            #17
+    
+    verts.append([0,0,0-HEIGHT])            #18
+    
+    faces.extend(Phillips_Fill(FaceStart_Outside,TRUE))
+
+    Spin_Verts,Spin_Face = SpinDup(verts,faces,360,4,'z')
+   
+    return Spin_Verts,Spin_Face,OUTTER_RADIUS * 2
+    
+
+##########################################################################################
+##########################################################################################
+##                    Create Head Types
+##########################################################################################
+##########################################################################################
+
+
+
+def Create_Pan_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
+
+    DIV = 36
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    HEAD_RADIUS = HEAD_DIA * 0.5
+    SHANK_RADIUS = SHANK_DIA * 0.5
+    
+    print "hole dia", HOLE_DIA
+    verts = []
+    faces = []
+    Row = 0
+    BEVEL = HEIGHT * 0.01
+    #Dome_Rad =  HEAD_RADIUS * (1.0/1.75)
+    
+    
+    Dome_Rad = HEAD_RADIUS * 1.12
+    RAD_Offset = HEAD_RADIUS * 0.96
+    OtherRad = HEAD_RADIUS * 0.16
+    OtherRad_X_Offset = HEAD_RADIUS * 0.84
+    OtherRad_Z_Offset = HEAD_RADIUS * 0.504
+    XRad = HEAD_RADIUS * 1.976
+    ZRad = HEAD_RADIUS * 1.768
+    EndRad = HEAD_RADIUS * 0.284
+    EndZOffset = HEAD_RADIUS * 0.432
+    HEIGHT = HEAD_RADIUS * 0.59
+    
+#    Dome_Rad =  5.6
+#    RAD_Offset = 4.9
+#    OtherRad = 0.8
+#    OtherRad_X_Offset = 4.2
+#    OtherRad_Z_Offset = 2.52
+#    XRad = 9.88
+#    ZRad = 8.84
+#    EndRad = 1.42
+#    EndZOffset = 2.16
+#    HEIGHT = 2.95
+    
+    FaceStart = FACE_OFFSET
+
+    z = cos(radians(10))*ZRad
+    verts.append([HOLE_RADIUS,0.0,(0.0-ZRad)+z])
+    Start_Height = 0 - ((0.0-ZRad)+z)
+    Row += 1
+
+    #for i in range(0,30,10):  was 0 to 30 more work needed to make this look good.
+    for i in range(10,30,10):
+        x = sin(radians(i))*XRad
+        z = cos(radians(i))*ZRad
+        print x
+        verts.append([x,0.0,(0.0-ZRad)+z])
+        Row += 1
+
+    for i in range(20,140,10):
+        x = sin(radians(i))*EndRad
+        z = cos(radians(i))*EndRad
+        if ((0.0 - EndZOffset)+z) < (0.0-HEIGHT):
+            verts.append([(HEAD_RADIUS -EndRad)+x,0.0,0.0 - HEIGHT])
+        else:
+            verts.append([(HEAD_RADIUS -EndRad)+x,0.0,(0.0 - EndZOffset)+z])
+        Row += 1
+        
+        
+    verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)])
+    Row += 1
+    
+    verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)-Start_Height])
+    Row += 1
+
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    Global_Head_Height = HEIGHT ;
+
+    
+    return Move_Verts_Up_Z(sVerts,Start_Height),faces,HEIGHT
+
+
+
+def Create_Dome_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
+    DIV = 36
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    HEAD_RADIUS = HEAD_DIA * 0.5
+    SHANK_RADIUS = SHANK_DIA * 0.5
+    
+    verts = []
+    faces = []
+    Row = 0
+    BEVEL = HEIGHT * 0.01
+    #Dome_Rad =  HEAD_RADIUS * (1.0/1.75)
+    
+    Dome_Rad =  HEAD_RADIUS * 1.12
+    #Head_Height = HEAD_RADIUS * 0.78
+    RAD_Offset = HEAD_RADIUS * 0.98
+    Dome_Height = HEAD_RADIUS * 0.64
+    OtherRad = HEAD_RADIUS * 0.16
+    OtherRad_X_Offset = HEAD_RADIUS * 0.84
+    OtherRad_Z_Offset = HEAD_RADIUS * 0.504
+    
+    
+#    Dome_Rad =  5.6
+#    RAD_Offset = 4.9
+#    Dome_Height = 3.2
+#    OtherRad = 0.8
+#    OtherRad_X_Offset = 4.2
+#    OtherRad_Z_Offset = 2.52
+#    
+    
+    
+    #averts, afaces = Create_Allen_Bit(8.5,5,5)
+    #verts.extend(averts)
+    #faces.extend(afaces)
+    
+    #FaceStart = len(verts)
+    FaceStart = FACE_OFFSET
+    
+    verts.append([HOLE_RADIUS,0.0,0.0])
+    Row += 1
+
+
+    for i in range(0,60,10):
+        x = sin(radians(i))*Dome_Rad
+        z = cos(radians(i))*Dome_Rad
+        #verts.append([x,0.0,(0.0-RAD_Offset)+z])
+        if ((0.0-RAD_Offset)+z) <= 0:
+            verts.append([x,0.0,(0.0-RAD_Offset)+z])
+            Row += 1
+
+
+    for i in range(60,160,10):
+        x = sin(radians(i))*OtherRad
+        z = cos(radians(i))*OtherRad
+        z = (0.0-OtherRad_Z_Offset)+z
+        if z < (0.0-Dome_Height):
+            z = (0.0-Dome_Height)
+        verts.append([OtherRad_X_Offset+x,0.0,z])
+        Row += 1
+        
+    verts.append([SHANK_RADIUS,0.0,(0.0-Dome_Height)])
+    Row += 1
+
+
+
+    #for i in range(0,18,1):
+    #    x = i
+    #    verts.append([x,0.0,(0.0-Dome_Height)])
+    #    Row += 1
+
+    
+    #verts.append([SHANK_RADIUS,0.0,(0.0-Dome_Height)-Dome_Height])
+    #Row += 1
+
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+ 
+
+    #Global_Head_Height = Dome_Height	   
+    return sVerts,faces,Dome_Height
+    #return verts,faces
+
+
+
+def Create_Cap_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2):
+    DIV = 36
+    
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    HEAD_RADIUS = HEAD_DIA * 0.5
+    SHANK_RADIUS = SHANK_DIA * 0.5
+    
+    
+    print "Head dia" , HEAD_DIA
+    print "Rad1" , RAD1
+    print "Rad2" , RAD2
+    
+    verts = []
+    faces = []
+    Row = 0
+    BEVEL = HEIGHT * 0.01
+    
+    
+    FaceStart = len(verts)
+
+    verts.append([HOLE_RADIUS,0.0,0.0])
+    Row += 1
+
+    #verts.append([HEAD_RADIUS-RAD1,0.0,0.0])
+    #Row += 1  Done in for loop below
+
+    #rad
+    
+    for i in range(0,100,10):
+        #print i
+        x = sin(radians(i))*RAD1
+        z = cos(radians(i))*RAD1
+        verts.append([(HEAD_RADIUS-RAD1)+x,0.0,(0.0-RAD1)+z])
+        Row += 1
+    
+    
+    #verts.append([HEAD_RADIUS,0.0,0.0-RAD1])
+    #Row += 1  Done in for loop above
+    
+    verts.append([HEAD_RADIUS,0.0,0.0-HEIGHT+BEVEL])
+    Row += 1
+
+    verts.append([HEAD_RADIUS-BEVEL,0.0,0.0-HEIGHT])
+    Row += 1
+
+    #rad2
+
+
+#    verts.append([SHANK_RADIUS+RAD2,0.0,0.0-HEIGHT])
+#    Row += 1 Done by rad2 below
+    
+    for i in range(0,100,10):
+        x = sin(radians(i))*RAD2
+        z = cos(radians(i))*RAD2
+        verts.append([(SHANK_RADIUS+RAD2)-x,0.0,(0.0-HEIGHT-RAD2)+z])
+        Row += 1
+    
+#    verts.append([SHANK_RADIUS,0.0,0.0-HEIGHT-RAD2])
+#    Row += 1 done by rad2 above
+
+
+#    verts.append([SHANK_RADIUS,0.0,0.0-HEIGHT-RAD2-RAD2])
+#    Row += 1
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    #Global_Head_Height = HEIGHT+RAD2
+	    
+
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+    
+    return sVerts,faces,HEIGHT+RAD2
+    #return verts,faces
+
+
+
+def Create_Hex_Head(FLAT,HOLE_DIA,SHANK_DIA,HEIGHT):
+    
+    verts = []
+    faces = []
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    Half_Flat = FLAT/2
+    TopBevelRadius = Half_Flat - (Half_Flat* (0.05/8))
+    Undercut_Height = (Half_Flat* (0.05/8))
+    Shank_Bevel = (Half_Flat* (0.05/8)) 
+    Flat_Height = HEIGHT - Undercut_Height - Shank_Bevel
+    #Undercut_Height = 5
+    SHANK_RADIUS = SHANK_DIA/2
+    Row = 0;
+
+    verts.append([0.0,0.0,0.0])
+    
+    
+    FaceStart = len(verts)
+    #inner hole
+    
+    x = sin(radians(0))*HOLE_RADIUS
+    y = cos(radians(0))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/6))*HOLE_RADIUS
+    y = cos(radians(60/6))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/3))*HOLE_RADIUS
+    y = cos(radians(60/3))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/2))*HOLE_RADIUS
+    y = cos(radians(60/2))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    Row += 1
+    
+    #bevel
+    
+    x = sin(radians(0))*TopBevelRadius
+    y = cos(radians(0))*TopBevelRadius
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/6))*TopBevelRadius
+    y = cos(radians(60/6))*TopBevelRadius
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/3))*TopBevelRadius
+    y = cos(radians(60/3))*TopBevelRadius
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/2))*TopBevelRadius
+    y = cos(radians(60/2))*TopBevelRadius
+    vec4 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    Row += 1
+    
+    #Flats
+    
+    x = tan(radians(0))*Half_Flat
+    dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0])
+    #print dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    
+    
+    x = tan(radians(60/6))*Half_Flat
+    dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0])
+    verts.append([x,Half_Flat,-dvec.length])
+    
+
+    x = tan(radians(60/3))*Half_Flat
+    dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0])
+    Lowest_Point = -dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    
+
+    x = tan(radians(60/2))*Half_Flat
+    dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0])
+    Lowest_Point = -dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    Row += 1
+    
+    #down Bits Tri
+    x = tan(radians(0))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    
+    x = tan(radians(60/6))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+
+    x = tan(radians(60/3))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    
+    x = tan(radians(60/2))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    Row += 1
+
+    #down Bits
+    
+    x = tan(radians(0))*Half_Flat
+    verts.append([x,Half_Flat,-Flat_Height])
+    
+    x = tan(radians(60/6))*Half_Flat
+    verts.append([x,Half_Flat,-Flat_Height])
+
+    x = tan(radians(60/3))*Half_Flat
+    verts.append([x,Half_Flat,-Flat_Height])
+    
+    x = tan(radians(60/2))*Half_Flat
+    verts.append([x,Half_Flat,-Flat_Height])
+    Row += 1
+    
+    
+    #under cut 
+       
+    x = sin(radians(0))*Half_Flat
+    y = cos(radians(0))*Half_Flat
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height])
+    
+    x = sin(radians(60/6))*Half_Flat
+    y = cos(radians(60/6))*Half_Flat
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height])
+    
+    x = sin(radians(60/3))*Half_Flat
+    y = cos(radians(60/3))*Half_Flat
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height])
+    
+    x = sin(radians(60/2))*Half_Flat
+    y = cos(radians(60/2))*Half_Flat
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height])
+    Row += 1
+    
+    #under cut down bit
+    x = sin(radians(0))*Half_Flat
+    y = cos(radians(0))*Half_Flat
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/6))*Half_Flat
+    y = cos(radians(60/6))*Half_Flat
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/3))*Half_Flat
+    y = cos(radians(60/3))*Half_Flat
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/2))*Half_Flat
+    y = cos(radians(60/2))*Half_Flat
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    Row += 1
+    
+    #under cut to Shank BEVEAL
+    x = sin(radians(0))*(SHANK_RADIUS+Shank_Bevel)
+    y = cos(radians(0))*(SHANK_RADIUS+Shank_Bevel)
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
+    y = cos(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
+    y = cos(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
+    y = cos(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    Row += 1
+    
+    #under cut to Shank BEVEAL
+    x = sin(radians(0))*SHANK_RADIUS
+    y = cos(radians(0))*SHANK_RADIUS
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
+    
+    x = sin(radians(60/6))*SHANK_RADIUS
+    y = cos(radians(60/6))*SHANK_RADIUS
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
+    
+    x = sin(radians(60/3))*SHANK_RADIUS
+    y = cos(radians(60/3))*SHANK_RADIUS
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
+    
+    x = sin(radians(60/2))*SHANK_RADIUS
+    y = cos(radians(60/2))*SHANK_RADIUS
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
+    Row += 1
+    
+    
+    #Shank
+#    x = sin(radians(0))*SHANK_RADIUS
+#    y = cos(radians(0))*SHANK_RADIUS
+#    vec1 = Mathutils.Vector([x,y,0.0])
+#    verts.append([x,y,-HEIGHT-0.5])
+#    
+#    x = sin(radians(60/6))*SHANK_RADIUS
+#    y = cos(radians(60/6))*SHANK_RADIUS
+#    vec2 = Mathutils.Vector([x,y,0.0])
+#    verts.append([x,y,-HEIGHT-0.5])
+#    
+#    x = sin(radians(60/3))*SHANK_RADIUS
+#    y = cos(radians(60/3))*SHANK_RADIUS
+#    vec3 = Mathutils.Vector([x,y,0.0])
+#    verts.append([x,y,-HEIGHT-0.5])
+#    
+#    x = sin(radians(60/2))*SHANK_RADIUS
+#    y = cos(radians(60/2))*SHANK_RADIUS
+#    vec3 = Mathutils.Vector([x,y,0.0])
+#    verts.append([x,y,-HEIGHT-0.5])
+    
+    #Global_Head_Height = 0 - (-HEIGHT-0.1)
+    faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
+       
+    
+    Mirror_Verts,Mirror_Faces = Mirror_Verts_Faces(verts,faces,'y')
+    verts.extend(Mirror_Verts)
+    faces.extend(Mirror_Faces)
+    
+    Spin_Verts,Spin_Faces = SpinDup(verts,faces,360,6,'z')
+    
+    return Spin_Verts,Spin_Faces,0 - (-HEIGHT)
+   
+    
+##########################################################################################
+##########################################################################################
+##                    Create Bolt
+##########################################################################################
+##########################################################################################
+
+
+
+def MakeBolt():
+    global Phillips_Bit_Depth 
+    global Philips_Bit_Dia 
+
+    global Allen_Bit_Depth 
+    global Allen_Bit_Flat_Distance 
+
+    global Hex_Head_Height 
+    global Hex_Head_Flat_Distance 
+
+    global Cap_Head_Dia 
+    global Cap_Head_Height 
+    
+
+    global Dome_Head_Dia 
+
+    global Pan_Head_Dia 
+
+    global Shank_Dia 
+    global Shank_Length 
+
+    global Thread_Length
+    global Major_Dia 
+    global Minor_Dia 
+    global Pitch 
+    global Crest_Percent 
+    global Root_Percent 
+    
+    verts = []
+    faces = []
+    Bit_Verts = []
+    Bit_Faces = []
+    Bit_Dia = 0.001
+    Head_Verts = []
+    Head_Faces= []
+    Head_Height = 0.0
+
+
+    
+    
+    Head_Height = Hex_Head_Height.val # will be changed by the Head Functions
+
+    #bit Mesh
+    if Bit_Type['ALLEN'][0].val:
+        #Create_Allen_Bit(FLAT_DISTANCE,OUTTER_RADIUS,HEIGHT):
+        Bit_Verts,Bit_Faces,Bit_Dia = Create_Allen_Bit(Allen_Bit_Flat_Distance.val,Allen_Bit_Depth.val)
+    
+    if Bit_Type['PHILLIPS'][0].val:
+        #Create_Phillips_Bit(FLAT_RADIUS, FLAT_WIDTH, HEIGHT)
+        #Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(Philips_Bit_Dia.val,3,Phillips_Bit_Depth.val)
+        #Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(3.00,0.4856,1.98)
+        #Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(4,1,2)
+        #Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(3.8,0.9,2.0)
+        #Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(3.0,0.9,2.0)
+        Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(Philips_Bit_Dia.val,Philips_Bit_Dia.val*(0.5/1.82),Phillips_Bit_Depth.val)
+   
+        
+    #Head Mesh
+    if Head_Type['HEX'][0].val:  
+        #add_Hex_Head(FLAT, HOLE_DIA, SHANK_DIA, HEIGHT)
+        Head_Verts,Head_Faces,Head_Height = Create_Hex_Head(Hex_Head_Flat_Distance.val,Bit_Dia,Shank_Dia.val,Hex_Head_Height.val)
+
+    elif Head_Type['CAP'][0].val:  
+        #add_Cap_Head(HOLE_RADIUS,HEAD_RADIUS,SHANK_RADIUS,HEIGHT,RAD1,RAD2)
+        #add_Cap_Head(2,5,3,6,1,1)
+        Head_Verts,Head_Faces,Head_Height = Create_Cap_Head(Bit_Dia,Cap_Head_Dia.val,Shank_Dia.val,Cap_Head_Height.val,Cap_Head_Dia.val*(1.0/19.0),Cap_Head_Dia.val*(1.0/19.0))
+        
+    elif Head_Type['DOME'][0].val:  
+        #add_Dome_Head(HOLE_RADIUS,HEAD_RADIUS,SHANK_RADIUS,HEIGHT,RAD1,RAD2,FACE_OFFSET):
+        Head_Verts,Head_Faces,Head_Height = Create_Dome_Head(Bit_Dia,Dome_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
+    
+    elif Head_Type['PAN'][0].val:  
+        #add_Pan_Head(HOLE_RADIUS,HEAD_RADIUS,SHANK_RADIUS,HEIGHT,RAD1,RAD2,FACE_OFFSET):
+        #verts, faces = add_Pan_Head(2.6,5,2,6,3.2,1,0)
+        #Head_Verts,Head_Faces = add_Pan_Head(2.6*2,5*2,2*2,6,3.2,1,0)
+        Head_Verts,Head_Faces,Head_Height = Create_Pan_Head(Bit_Dia,Pan_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
+
+    print 'got here'
+
+    Face_Start = len(verts)
+    verts.extend(Move_Verts_Up_Z(Bit_Verts,Head_Height))
+    faces.extend(Copy_Faces(Bit_Faces,Face_Start))
+
+    Face_Start = len(verts)
+    verts.extend(Move_Verts_Up_Z(Head_Verts,Head_Height))
+    faces.extend(Copy_Faces(Head_Faces,Face_Start))
+
+    Face_Start = len(verts)
+    Thread_Verts,Thread_Faces,Thread_Height = Create_External_Thread(Shank_Dia.val,Shank_Length.val,Minor_Dia.val,Major_Dia.val,Pitch.val,Thread_Length.val,Crest_Percent.val,Root_Percent.val)
+
+    verts.extend(Move_Verts_Up_Z(Thread_Verts,00))
+    faces.extend(Copy_Faces(Thread_Faces,Face_Start))
+    
+    return Move_Verts_Up_Z(verts,Thread_Height),faces
+    #return Move_Verts_Up_Z(verts,0),faces
+
+
+
+
+
+def Create_Bolt():
+    verts = []
+    faces = []
+
+  
+    if Error_Check() :
+        return
+
+
+    me = Mesh.New('Bolt')          # create a new mesh
+    
+    verts, faces = MakeBolt()
+    
+    me.verts.extend(verts)          # add vertices to mesh
+    me.faces.extend(faces)           # add faces to the mesh (also adds edges)
+
+    
+    
+    is_editmode = Window.EditMode() # Store edit mode state
+    if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode.
+
+
+    scn = Scene.GetCurrent()          # link object to current scene
+    scn.objects.selected = []
+    
+    ob = scn.objects.active = scn.objects.new(me, 'Bolt')
+    ob.loc = Window.GetCursorPos()
+    me.remDoubles(0.010)    
+
+    if is_editmode: Window.EditMode(1)
+    
+    Blender.Redraw()
+
+
+
+
+##########################################################################################
+##########################################################################################
+##                    Create Internal Thread
+##########################################################################################
+##########################################################################################
+
+
+def Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
+    
+    
+    Ret_Row = 0;
+    
+    Height_Offset = Height_Offset + PITCH  #Move the offset up so that the verts start at 
+                                           #at the corect place  (Height_Start)
+    
+    
+    Half_Pitch = float(PITCH)/2
+    Height_Start = Height_Offset - PITCH 
+    Height_Step = float(PITCH)/float(DIV)
+    Deg_Step = 360.0 /float(DIV)
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+    
+    
+#theard start
+    #print Height_Start
+    #print "Height_Offset" , Height_Offset
+
+    Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
+    for j in range(1):
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z])
+        Height_Offset -= Crest_Height
+        Ret_Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z ])
+        Height_Offset -= Crest_to_Root_Height
+        Ret_Row += 1
+    
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+        Height_Offset -= Root_Height
+        Ret_Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+        Height_Offset -= Root_to_Crest_Height
+        Ret_Row += 1
+   
+    return Ret_Row,Height_Offset
+
+
+def Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
+    
+    
+    Ret_Row = 0;
+    
+    Half_Pitch = float(PITCH)/2
+    #Height_End = Height_Offset - PITCH - PITCH - PITCH- PITCH - PITCH- PITCH
+    Height_End = Height_Offset - PITCH 
+    #Height_End = -2.1
+    Height_Step = float(PITCH)/float(DIV)
+    Deg_Step = 360.0 /float(DIV)
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+   
+    
+#theard start
+
+    Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
+    
+    Num = 0
+    
+    for j in range(2):
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z < Height_End:
+                z = Height_End
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z])
+        Height_Offset -= Crest_Height
+        Ret_Row += 1
+    
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z < Height_End:
+                z = Height_End
+            
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z ])
+        Height_Offset -= Crest_to_Root_Height
+        Ret_Row += 1
+    
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z < Height_End:
+                z = Height_End
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            if j == Num:
+                x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
+                y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
+            if j > Num:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS)
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
+                
+            verts.append([x,y,z ])
+        Height_Offset -= Root_Height
+        Ret_Row += 1
+    
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z < Height_End:
+                z = Height_End
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+
+            if j == Num:
+                x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
+                y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
+            if j > Num:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS )
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
+                
+            verts.append([x,y,z ])
+        Height_Offset -= Root_to_Crest_Height
+        Ret_Row += 1
+
+        
+        
+       
+    return Ret_Row,Height_End  # send back Height End as this is the lowest point
+
+
+def Create_Internal_Thread(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,INTERNAL = 1):
+    verts = []
+    faces = []
+    
+    DIV = 36
+    
+    INNER_RADIUS = INNER_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Half_Pitch = float(PITCH)/2
+    Deg_Step = 360.0 /float(DIV)
+    Height_Step = float(PITCH)/float(DIV)
+
+    #print "HEIGHT" , HEIGHT
+            
+    Num = int(round((HEIGHT- PITCH)/PITCH))  # less one pitch for the start and end that is 1/2 pitch high    
+    
+    #print "Num" ,Num
+    
+    Col = 0
+    Row = 0
+    
+    #CREST_PERCENT = 10
+    #ROOT_PERCENT = 10
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+    
+    Height_Offset = 0
+    FaceStart = len(verts)
+    
+    Row_Inc,Height_Offset = Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
+    #Row_Inc,Height_Offset = Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
+    Row += Row_Inc
+    
+    print "start Height_Offset ", Height_Offset
+    #Global_Thread_Height = 0 - Height_Offset
+    #faces.extend(Build_Face_List_Quads(FaceStart,DIV,Row -1))
+    #return verts,faces
+
+    
+    for j in range(Num):
+        
+        print j
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,Height_Offset - (Height_Step*i) ])
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,Height_Offset - (Height_Step*i) ])
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+    
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            verts.append([x,y,Height_Offset - (Height_Step*i) ])
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            verts.append([x,y,Height_Offset - (Height_Step*i) ])
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+    
+    print "thread Height_Offset ", Height_Offset      
+   # Row_Inc,Height_Offset = Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
+    
+   # Row += Row_Inc
+    Row_Inc,Height_Offset = Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
+    Row += Row_Inc
+    
+    
+    print "End Height_Offset ", Height_Offset      
+    
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,DIV,Row -1,INTERNAL))
+    
+    #faces.extend(Fill_Ring_Face(len(verts)-DIV,DIV,1))
+
+    #Global_Thread_Height = 0 - Height_Offset
+    #print "Global_Thread_Height" ,Global_Thread_Height 
+    return verts,faces,0 - Height_Offset
+
+
+
+##########################################################################################
+##########################################################################################
+##                    Create External Thread
+##########################################################################################
+##########################################################################################
+
+
+
+
+
+def Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
+    
+    
+    Ret_Row = 0;
+    
+    Half_Pitch = float(PITCH)/2
+    Height_Start = Height_Offset - PITCH
+    Height_Step = float(PITCH)/float(DIV)
+    Deg_Step = 360.0 /float(DIV)
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+   
+#theard start
+
+    Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
+    for j in range(4):
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z])
+        Height_Offset -= Crest_Height
+        Ret_Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z ])
+        Height_Offset -= Crest_to_Root_Height
+        Ret_Row += 1
+    
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+        Height_Offset -= Root_Height
+        Ret_Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+        Height_Offset -= Root_to_Crest_Height
+        Ret_Row += 1
+   
+    return Ret_Row,Height_Offset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Create_Shank_Verts(START_DIA,OUTTER_DIA,LENGTH,Z_LOCATION = 0):
+
+    verts = []
+    DIV = 36
+    
+    START_RADIUS = START_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Opp = abs(START_RADIUS - OUTTER_RADIUS)
+    Taper_Lentgh = Opp/tan(radians(31));
+    
+    if Taper_Lentgh > LENGTH:
+        Taper_Lentgh = 0
+    
+    Stright_Length = LENGTH - Taper_Lentgh
+    
+    print "opp " , Opp
+    print "Taper_Lentgh " , Taper_Lentgh
+    print "Stright_Length " , Stright_Length
+
+    
+    Deg_Step = 360.0 /float(DIV)
+    
+    Row = 0
+    
+    Lowest_Z_Vert = 0;    
+    
+    Height_Offset = Z_LOCATION
+
+
+        #ring
+    for i in range(DIV+1): 
+        x = sin(radians(i*Deg_Step))*START_RADIUS
+        y = cos(radians(i*Deg_Step))*START_RADIUS
+        z =  Height_Offset - 0
+        verts.append([x,y,z])
+        Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Height_Offset -= Stright_Length
+    Row += 1
+
+    for i in range(DIV+1): 
+        x = sin(radians(i*Deg_Step))*START_RADIUS
+        y = cos(radians(i*Deg_Step))*START_RADIUS
+        z =  Height_Offset - 0
+        verts.append([x,y,z])
+        if i == DIV:
+            print "ring", x,y,z
+        Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Height_Offset -= Taper_Lentgh
+    Row += 1
+
+    
+#    for i in range(DIV+1): 
+#        x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+#        y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+#        z =  Height_Offset - 0
+#        verts.append([x,y,z])
+#        Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+#    Height_Offset -= 1
+#    Row += 1
+
+
+    
+    return verts,Row,Height_Offset
+
+
+def Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
+    
+    verts = []
+    DIV = 36
+    
+    INNER_RADIUS = INNER_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Half_Pitch = float(PITCH)/2
+    Deg_Step = 360.0 /float(DIV)
+    Height_Step = float(PITCH)/float(DIV)
+
+    Row = 0
+    
+    Lowest_Z_Vert = 0;    
+    
+    Height_Offset = Z_LOCATION
+        
+    #Height_Start = Height_Offset - PITCH
+    Height_Start = Height_Offset 
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+
+    Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
+    
+    Height_Offset = Z_LOCATION + PITCH 
+    Cut_off = Z_LOCATION
+  
+    
+    for j in range(1):
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            print "z", z
+            if z > Cut_off : z = Cut_off
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            if z > Cut_off : z = Cut_off
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            if z > Cut_off : z = Cut_off 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            if z > Cut_off : z = Cut_off 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+    
+##    return verts,Row,Height_Offset
+    
+    
+    for j in range(2):
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z ])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+    
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+        
+   
+    return verts,Row,Height_Offset
+
+
+
+
+
+
+
+
+
+def Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
+    verts = []
+        
+    DIV = 36
+    
+    INNER_RADIUS = INNER_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Half_Pitch = float(PITCH)/2
+    Deg_Step = 360.0 /float(DIV)
+    Height_Step = float(PITCH)/float(DIV)
+
+    NUM_OF_START_THREADS = 4.0
+    NUM_OF_END_THREADS = 3.0
+    Num = int((HEIGHT- ((NUM_OF_START_THREADS*PITCH) + (NUM_OF_END_THREADS*PITCH) ))/PITCH)
+    Row = 0
+    
+
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+
+
+      
+    #print "Crest_Height" ,Crest_Height
+    #print "Crest_to_Root_Height"  ,Crest_to_Root_Height 
+    #print "Root_Height"   ,Root_Height 
+    #print "Root_to_Crest_Height" ,Root_to_Crest_Height 
+       
+
+
+    #Height_Offset = Half_Pitch
+    Height_Offset = Z_LOCATION
+    
+    Lowest_Z_Vert = 0;
+    FaceStart = len(verts)
+    
+    
+    
+    
+    
+    for j in range(Num):
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i) 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+    
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            z = Height_Offset - (Height_Step*i) 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            z = Height_Offset - (Height_Step*i) 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+    
+    return verts,Row,Height_Offset
+
+
+
+def Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
+    verts = []
+        
+    DIV = 36
+
+    INNER_RADIUS = INNER_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Half_Pitch = float(PITCH)/2
+    Deg_Step = 360.0 /float(DIV)
+    Height_Step = float(PITCH)/float(DIV)
+
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+       
+    Col = 0
+    Row = 0
+    
+    Height_Offset = Z_LOCATION 
+    
+    
+    Tapper_Height_Start = Height_Offset - PITCH - PITCH 
+    #Tapper_Height_Start = Height_Offset
+    
+    Max_Height = Tapper_Height_Start - PITCH 
+    #Max_Height = Tapper_Height_Start - PITCH - PITCH - PITCH - PITCH - PITCH 
+    
+    Lowest_Z_Vert = 0;
+    
+    FaceStart = len(verts)
+    for j in range(4):
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i)
+            z = max(z,Max_Height)
+            Tapper_Radius = OUTTER_RADIUS
+            if z < Tapper_Height_Start:
+                Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
+
+            x = sin(radians(i*Deg_Step))*(Tapper_Radius)
+            y = cos(radians(i*Deg_Step))*(Tapper_Radius)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i)
+            z = max(z,Max_Height)
+            Tapper_Radius = OUTTER_RADIUS
+            if z < Tapper_Height_Start:
+                Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
+
+            x = sin(radians(i*Deg_Step))*(Tapper_Radius)
+            y = cos(radians(i*Deg_Step))*(Tapper_Radius)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+    
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i)
+            z = max(z,Max_Height)
+            Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
+            if Tapper_Radius > INNER_RADIUS:
+               Tapper_Radius = INNER_RADIUS
+            
+            x = sin(radians(i*Deg_Step))*(Tapper_Radius)
+            y = cos(radians(i*Deg_Step))*(Tapper_Radius)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i)
+            z = max(z,Max_Height)
+            Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
+            if Tapper_Radius > INNER_RADIUS:
+               Tapper_Radius = INNER_RADIUS
+            
+            x = sin(radians(i*Deg_Step))*(Tapper_Radius)
+            y = cos(radians(i*Deg_Step))*(Tapper_Radius)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+    
+    return verts,Row,Height_Offset,Lowest_Z_Vert
+
+
+
+
+def Create_External_Thread(SHANK_DIA,SHANK_LENGTH,INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT):
+    
+    verts = []
+    faces = []
+
+    DIV = 36
+    
+    Total_Row = 0
+    Thread_Len = 0;
+    
+    Face_Start = len(verts)
+    Offset = 0.0;
+    
+                                             
+    Shank_Verts,Shank_Row,Offset = Create_Shank_Verts(SHANK_DIA,OUTTER_DIA,SHANK_LENGTH,Offset)
+    Total_Row += Shank_Row
+    print "Shank offset " , Offset
+    
+
+    Thread_Start_Verts,Thread_Start_Row,Offset = Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset)
+    Total_Row += Thread_Start_Row
+    print "Start offset " , Offset
+    
+    
+    Thread_Verts,Thread_Row,Offset = Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT,Offset)
+    Total_Row += Thread_Row
+    print "Thread offset " , Offset
+    
+    
+    Thread_End_Verts,Thread_End_Row,Offset,Lowest_Z_Vert = Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset )
+    Total_Row += Thread_End_Row       
+    print "End offset " , Offset
+    print "Lowest_Z_Vert " , Lowest_Z_Vert
+    
+    
+    
+    verts.extend(Shank_Verts)
+    verts.extend(Thread_Start_Verts)
+    verts.extend(Thread_Verts)
+    verts.extend(Thread_End_Verts)
+    
+    faces.extend(Build_Face_List_Quads(Face_Start,DIV,Total_Row -1,0))
+    faces.extend(Fill_Ring_Face(len(verts)-DIV,DIV,1))
+    
+    return verts,faces,0.0 - Lowest_Z_Vert
+ 
+
+##########################################################################################
+##########################################################################################
+##                    Create Nut
+##########################################################################################
+##########################################################################################
+
+
+def add_Hex_Nut(FLAT,HOLE_DIA,HEIGHT):
+    global Global_Head_Height
+    global Global_NutRad
+    
+    verts = []
+    faces = []
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    Half_Flat = FLAT/2
+    Half_Height = HEIGHT/2
+    TopBevelRadius = Half_Flat - 0.05
+    
+    Global_NutRad =  TopBevelRadius
+    
+    Row = 0;
+    Lowest_Z_Vert = 0.0;
+
+    verts.append([0.0,0.0,0.0])
+    
+    
+    FaceStart = len(verts)
+    #inner hole
+    
+    x = sin(radians(0))*HOLE_RADIUS
+    y = cos(radians(0))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/6))*HOLE_RADIUS
+    y = cos(radians(60/6))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/3))*HOLE_RADIUS
+    y = cos(radians(60/3))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/2))*HOLE_RADIUS
+    y = cos(radians(60/2))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    Row += 1
+    
+    #bevel
+    
+    x = sin(radians(0))*TopBevelRadius
+    y = cos(radians(0))*TopBevelRadius
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/6))*TopBevelRadius
+    y = cos(radians(60/6))*TopBevelRadius
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/3))*TopBevelRadius
+    y = cos(radians(60/3))*TopBevelRadius
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/2))*TopBevelRadius
+    y = cos(radians(60/2))*TopBevelRadius
+    vec4 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    Row += 1
+    
+    #Flats
+    
+    x = tan(radians(0))*Half_Flat
+    dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0])
+    #print dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
+    
+    
+    x = tan(radians(60/6))*Half_Flat
+    dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0])
+    verts.append([x,Half_Flat,-dvec.length])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
+    
+
+    x = tan(radians(60/3))*Half_Flat
+    dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0])
+    Lowest_Point = -dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
+
+    x = tan(radians(60/2))*Half_Flat
+    dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0])
+    Lowest_Point = -dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
+    Row += 1
+    
+    #down Bits Tri
+    x = tan(radians(0))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    
+    
+    x = tan(radians(60/6))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+
+    x = tan(radians(60/3))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    
+    x = tan(radians(60/2))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,Lowest_Point)
+    Row += 1
+
+    #down Bits
+    
+    x = tan(radians(0))*Half_Flat
+    verts.append([x,Half_Flat,-Half_Height])
+    
+    x = tan(radians(60/6))*Half_Flat
+    verts.append([x,Half_Flat,-Half_Height])
+
+    x = tan(radians(60/3))*Half_Flat
+    verts.append([x,Half_Flat,-Half_Height])
+    
+    x = tan(radians(60/2))*Half_Flat
+    verts.append([x,Half_Flat,-Half_Height])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-Half_Height)
+    Row += 1
+
+    
+    
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
+
+
+    Global_Head_Height = HEIGHT
+    
+    Tvert,tface = Mirror_Verts_Faces(verts,faces,'z',Lowest_Z_Vert)
+    verts.extend(Tvert)
+    faces.extend(tface)
+           
+    
+    Tvert,tface = Mirror_Verts_Faces(verts,faces,'y')
+    verts.extend(Tvert)
+    faces.extend(tface)
+    
+    S_verts,S_faces = SpinDup(verts,faces,360,6,'z')
+    return S_verts,S_faces,TopBevelRadius
+
+
+
+
+
+def add_Nylon_Head_Top(OUTSIDE_RADIUS):
+    DIV = 36
+    verts = []
+    faces = []
+    Row = 0
+
+    print "outside" , OUTSIDE_RADIUS
+    
+    INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75))
+    EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
+    RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
+    OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
+    
+    FaceStart = len(verts)
+
+    Start_Height = 0 - 3
+    Height_Offset = 0
+    Lowest_Z_Vert = 0
+    
+
+    x = INNER_HOLE
+    z = Height_Offset - EDGE_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = INNER_HOLE
+    z = Height_Offset - 0
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    
+    for i in range(0,100,10):
+        #print i
+        x = sin(radians(i))*RAD1
+        z = cos(radians(i))*RAD1
+        verts.append([(OUTSIDE_RADIUS-RAD1)+x,0.0,(Height_Offset-RAD1)+z])
+        Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Row += 1
+    
+    
+    x = OUTSIDE_RADIUS - 0
+    z = Height_Offset - OVER_ALL_HEIGTH
+    print "ada" , z , OVER_ALL_HEIGTH
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    #return Move_Verts_Up_Z(verts,Start_Height),faces
+    return Move_Verts_Up_Z(sVerts,0 - Lowest_Z_Vert),faces,0 - Lowest_Z_Vert
+
+
+
+def add_Nylon_Head(OUTSIDE_RADIUS,Z_LOCATION = 0):
+    DIV = 36
+    verts = []
+    faces = []
+    Row = 0
+
+    print "outside" , OUTSIDE_RADIUS
+    
+    INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75))
+    EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
+    RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
+    OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
+    
+    FaceStart = len(verts)
+
+    Start_Height = 0 - 3
+    Height_Offset = Z_LOCATION
+    Lowest_Z_Vert = 0
+    
+
+    x = INNER_HOLE
+    z = (Height_Offset - OVER_ALL_HEIGTH) + EDGE_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = INNER_HOLE
+    z = (Height_Offset - OVER_ALL_HEIGTH)
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    
+    for i in range(180,80,-10):
+        print i
+        x = sin(radians(i))*RAD1
+        z = cos(radians(i))*RAD1
+        verts.append([(OUTSIDE_RADIUS-RAD1)+x,0.0,((Height_Offset - OVER_ALL_HEIGTH)+RAD1)+z])
+        Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Row += 1
+    
+    
+    x = OUTSIDE_RADIUS - 0
+    z = Height_Offset 
+    print "ada" , z , OVER_ALL_HEIGTH
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    return Move_Verts_Up_Z(sVerts,0),faces,Lowest_Z_Vert
+    #return Move_Verts_Up_Z(sVerts,0 - Lowest_Z_Vert),faces,0 - Lowest_Z_Vert
+
+
+
+def add_Nylon_Part_top(OUTSIDE_RADIUS,Z_LOCATION = 0):
+    DIV = 36
+    verts = []
+    faces = []
+    Row = 0
+
+    print "outside" , OUTSIDE_RADIUS
+     
+    
+    INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75))
+    EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
+    RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
+    OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
+    PART_THICKNESS = OVER_ALL_HEIGTH - EDGE_THICKNESS
+    PART_INNER_HOLE = (OUTSIDE_RADIUS * (2.5/4.75))
+    
+    FaceStart = len(verts)
+
+    Start_Height = 0 - 3
+    Height_Offset = 0
+    Lowest_Z_Vert = 0
+    
+
+    x = INNER_HOLE + EDGE_THICKNESS
+    z = Height_Offset - OVER_ALL_HEIGTH
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = PART_INNER_HOLE
+    z = Height_Offset - OVER_ALL_HEIGTH
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = PART_INNER_HOLE
+    z = Height_Offset - EDGE_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = INNER_HOLE + EDGE_THICKNESS
+    z = Height_Offset - EDGE_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    return sVerts,faces,0 - Lowest_Z_Vert
+    #return Move_Verts_Up_Z(sVerts,0 - Lowest_Z_Vert),faces,0 - Lowest_Z_Vert
+
+
+
+def add_Nylon_Part(OUTSIDE_RADIUS,Z_LOCATION = 0):
+    DIV = 36
+    verts = []
+    faces = []
+    Row = 0
+
+    print "outside" , OUTSIDE_RADIUS
+     
+    
+    INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75))
+    EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
+    RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
+    OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
+    PART_THICKNESS = OVER_ALL_HEIGTH - EDGE_THICKNESS
+    PART_INNER_HOLE = (OUTSIDE_RADIUS * (2.5/4.75))
+    
+    FaceStart = len(verts)
+
+    Start_Height = 0 - 3
+    Height_Offset = Z_LOCATION
+    Lowest_Z_Vert = 0
+    
+
+    x = INNER_HOLE + EDGE_THICKNESS
+    z = Height_Offset 
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = PART_INNER_HOLE
+    z = Height_Offset
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = PART_INNER_HOLE
+    z = Height_Offset - PART_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = INNER_HOLE + EDGE_THICKNESS
+    z = Height_Offset - PART_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)  #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    return sVerts,faces,0 - Lowest_Z_Vert
+    #return Move_Verts_Up_Z(sVerts,0 - Lowest_Z_Vert),faces,0 - Lowest_Z_Vert
+
+
+
+def Nut_Mesh():
+
+    verts = []
+    faces = []
+    Head_Verts = []
+    Head_Faces= []
+
+    Face_Start = len(verts)
+    Thread_Verts,Thread_Faces,New_Nut_Height = Create_Internal_Thread(Minor_Dia.val,Major_Dia.val,Pitch.val,Hex_Nut_Height.val,Crest_Percent.val,Root_Percent.val,1)
+    verts.extend(Thread_Verts)
+    faces.extend(Copy_Faces(Thread_Faces,Face_Start))
+    
+    Face_Start = len(verts)
+    Head_Verts,Head_Faces,Lock_Nut_Rad = add_Hex_Nut(Hex_Nut_Flat_Distance.val,Major_Dia.val,New_Nut_Height)
+    verts.extend((Head_Verts))
+    faces.extend(Copy_Faces(Head_Faces,Face_Start))
+    
+    LowZ = 0 - New_Nut_Height
+    
+    if Nut_Type['LOCK'][0].val:
+        Face_Start = len(verts)
+        Nylon_Head_Verts,Nylon_Head_faces,LowZ = add_Nylon_Head(Lock_Nut_Rad,0-New_Nut_Height)    
+        verts.extend((Nylon_Head_Verts))
+        faces.extend(Copy_Faces(Nylon_Head_faces,Face_Start))
+    
+        Face_Start = len(verts)
+        Nylon_Verts,Nylon_faces,Temp_LowZ = add_Nylon_Part(Lock_Nut_Rad,0-New_Nut_Height)    
+        verts.extend((Nylon_Verts))
+        faces.extend(Copy_Faces(Nylon_faces,Face_Start))
+    
+
+    #verts.extend(Move_Verts_Up_Z(Thread_Verts,Global_Thread_Height))
+    #verts.extend(Thread_Verts)
+    #faces.extend(Copy_Faces(Thread_Faces,Face_Start))
+    print "low z" , LowZ
+    #return Move_Verts_Up_Z(verts,0),faces
+    return Move_Verts_Up_Z(verts,0 - LowZ),faces
+
+
+
+def Create_Nut():
+    verts = []
+    faces = []
+    
+  
+    if Error_Check() :
+        return
+
+    me = Mesh.New('Nut')          # create a new mesh
+    
+    verts, faces = Nut_Mesh()
+    
+    me.verts.extend(verts)          # add vertices to mesh
+    me.faces.extend(faces)           # add faces to the mesh (also adds edges)
+    
+    is_editmode = Window.EditMode() # Store edit mode state
+    if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode.
+
+
+    scn = Scene.GetCurrent()          # link object to current scene
+    scn.objects.selected = []
+    ob = scn.objects.active = scn.objects.new(me, 'Nut')
+    ob.loc = Window.GetCursorPos()
+    
+    me.remDoubles(0.010)    
+    
+    if is_editmode: Window.EditMode(1)
+    
+    Blender.Redraw()
+
+
+##################################################################################################
+
+def Get_Phillips_Bit_Height(Bit_Dia):
+    Flat_Width_half = (Bit_Dia*(0.5/1.82))/2.0
+    Bit_Rad = Bit_Dia / 2.0
+    x = Bit_Rad - Flat_Width_half
+    y = tan(radians(60))*x
+    return y 
+    
+    
+
+def Load_Preset():
+
+    global Preset_Menu
+    global Preset_Length
+    global Shank_Dia
+    global Shank_Length
+    global Thread_Length
+    global Major_Dia 
+    global Minor_Dia
+    global Pitch 
+    global Crest_Percent 
+    global Root_Percent 
+    global Allen_Bit_Flat_Distance
+    global Allen_Bit_Depth
+    global Head_Height
+    global Hex_Head_Flat_Distance 
+    global Head_Dia 
+    global Dome_Head_Dia
+    global Pan_Head_Dia 
+    global Philips_Bit_Dia 
+    global Phillips_Bit_Depth 
+    global Cap_Head_Inside_Rad
+    global Cap_Head_Height
+
+    global Hex_Nut_Height
+    global Hex_Nut_Flat_Distance
+
+
+  
+#    Crest_Percent.val = 13
+#    Root_Percent.val = 24
+#    Thread_Length.val = 8
+#        
+#    
+#    if Preset_Menu.val == 4 : #M4
+#        Major_Dia.val = 4.0
+#        Pitch.val = 0.7
+#    
+#    Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+#    Hex_Head_Flat_Distance.val = 1.75 * Major_Dia.val
+#        
+#    Shank_Dia.val = Major_Dia.val
+#    Shank_Length.val = 0.0
+#    Hex_Head_Height.val = 2.8
+#        
+#    Cap_Head_Dia.val = 7.0
+#    Allen_Bit_Flat_Distance.val = 3.0
+#    Phillips_Bit_Depth.val = 1.5 
+
+
+    if Preset_Menu.val == 1 : #M3
+        Shank_Dia.val = 3.0
+        #Pitch.val = 0.5    #Coarse
+        Pitch.val = 0.35  #Fine
+        Major_Dia.val = 3.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 5.5
+        Hex_Head_Height.val = 2.0
+        Cap_Head_Dia.val = 5.5
+        Cap_Head_Height.val = 3.0
+        Allen_Bit_Flat_Distance.val = 2.5
+        Allen_Bit_Depth.val = 1.5
+        Pan_Head_Dia.val = 5.6
+        Dome_Head_Dia.val = 5.6
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 2.4
+        Hex_Nut_Flat_Distance.val = 5.5
+        Thread_Length.val = 6
+        Shank_Length.val = 0.0
+        
+    
+    if Preset_Menu.val == 2 : #M4
+        Shank_Dia.val = 4.0
+        #Pitch.val = 0.7    #Coarse
+        Pitch.val = 0.5  #Fine
+        Major_Dia.val = 4.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 7.0
+        Hex_Head_Height.val = 2.8
+        Cap_Head_Dia.val = 7.0
+        Cap_Head_Height.val = 4.0
+        Allen_Bit_Flat_Distance.val = 3.0
+        Allen_Bit_Depth.val = 2.0
+        Pan_Head_Dia.val = 8.0
+        Dome_Head_Dia.val = 8.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 3.2
+        Hex_Nut_Flat_Distance.val = 7.0
+        Thread_Length.val = 8
+        Shank_Length.val = 0.0
+        
+        
+    if Preset_Menu.val == 3 : #M5
+        Shank_Dia.val = 5.0
+        #Pitch.val = 0.8 #Coarse
+        Pitch.val = 0.5  #Fine
+        Major_Dia.val = 5.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 8.0
+        Hex_Head_Height.val = 3.5
+        Cap_Head_Dia.val = 8.5
+        Cap_Head_Height.val = 5.0
+        Allen_Bit_Flat_Distance.val = 4.0
+        Allen_Bit_Depth.val = 2.5
+        Pan_Head_Dia.val = 9.5
+        Dome_Head_Dia.val = 9.5
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 4.0
+        Hex_Nut_Flat_Distance.val = 8.0
+        Thread_Length.val = 10
+        Shank_Length.val = 0.0
+        
+        
+    if Preset_Menu.val == 4 : #M6
+        Shank_Dia.val = 6.0
+        #Pitch.val = 1.0 #Coarse
+        Pitch.val = 0.75  #Fine
+        Major_Dia.val = 6.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 10.0
+        Hex_Head_Height.val = 4.0
+        Cap_Head_Dia.val = 10.0
+        Cap_Head_Height.val = 6.0
+        Allen_Bit_Flat_Distance.val = 5.0
+        Allen_Bit_Depth.val = 3.0
+        Pan_Head_Dia.val = 12.0
+        Dome_Head_Dia.val = 12.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 5.0
+        Hex_Nut_Flat_Distance.val = 10.0
+        Thread_Length.val = 12
+        Shank_Length.val = 0.0
+        
+        
+    if Preset_Menu.val == 5 : #M8
+        Shank_Dia.val = 8.0
+        #Pitch.val = 1.25 #Coarse
+        Pitch.val = 1.00  #Fine
+        Major_Dia.val = 8.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 13.0
+        Hex_Head_Height.val = 5.3
+        Cap_Head_Dia.val = 13.5
+        Cap_Head_Height.val = 8.0
+        Allen_Bit_Flat_Distance.val = 6.0
+        Allen_Bit_Depth.val = 4.0
+        Pan_Head_Dia.val = 16.0
+        Dome_Head_Dia.val = 16.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 6.5
+        Hex_Nut_Flat_Distance.val = 13.0
+        Thread_Length.val = 16
+        Shank_Length.val = 0.0
+    
+    if Preset_Menu.val == 6 : #M10
+        Shank_Dia.val = 10.0
+        #Pitch.val = 1.5 #Coarse
+        Pitch.val = 1.25  #Fine
+        Major_Dia.val = 10.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 17.0
+        Hex_Head_Height.val = 6.4
+        Cap_Head_Dia.val = 16.0
+        Cap_Head_Height.val = 10.0
+        Allen_Bit_Flat_Distance.val = 8.0
+        Allen_Bit_Depth.val = 5.0
+        Pan_Head_Dia.val = 20.0
+        Dome_Head_Dia.val = 20.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 8.0
+        Hex_Nut_Flat_Distance.val = 17.0
+        Thread_Length.val = 20
+        Shank_Length.val = 0.0
+    
+    
+    if Preset_Menu.val == 7 : #M12
+        #Pitch.val = 1.75 #Coarse
+        Pitch.val = 1.50  #Fine
+        Major_Dia.val = 12.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 19.0
+        Hex_Head_Height.val = 7.5
+        Cap_Head_Dia.val = 18.5
+        Cap_Head_Height.val = 12.0
+        Allen_Bit_Flat_Distance.val = 10.0
+        Allen_Bit_Depth.val = 6.0
+        Pan_Head_Dia.val = 24.0
+        Dome_Head_Dia.val = 24.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 10.0
+        Hex_Nut_Flat_Distance.val = 19.0
+        Shank_Dia.val = 12.0
+        Shank_Length.val = 33.0
+        Thread_Length.val = 32.0
+        
+
+
+def get_selected_edges(edge_lst):
+    ret = []
+    for i in range(0, len(edge_lst)):
+        if edge_lst[i].sel == 1:
+            ret.append(edge_lst[i])
+    return ret
+
+def Test():
+    
+    
+    print "Test"
+    scn = Scene.GetCurrent()
+    ob = scn.getActiveObject() # Gets the current active object (If Any)
+        
+    if ob == None or ob.getType() != 'Mesh': # Checks the active objects a mesh
+        Draw.PupMenu('ERROR%t|Select a mesh object.')
+        return
+
+    is_editmode = Window.EditMode() # Store edit mode state
+    if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode.
+    
+    me = ob.getData(False, True)
+    Sel_Edges = get_selected_edges(me.faces)
+    print Sel_Edges
+    print Sel_Edges[0].index
+    mystr = 'Face Number ' + str(Sel_Edges)
+    #mystr = 'Face Number ' + str(Sel_Edges[0].index)  
+    Draw.PupMenu(mystr)
+        
+    
+    if is_editmode: Window.EditMode(1)
+    
+    
+
+        
+        
+
+##############################################################################################
+
+def event(evt, val):    # the function to handle input events
+
+  if evt == Draw.ESCKEY:
+    Draw.Exit()                 # exit when user presses ESC
+    return
+
+
+def button_event(evt):  # the function to handle Draw Button events
+
+    if evt == On_Exit_Click:
+        Draw.Exit()                 # exit when user presses ESC
+        return
+
+    if evt == On_Test_Click:
+        Test()
+        Draw.Redraw(1)
+    
+    if evt == On_Preset_Click:
+        Load_Preset()
+        Draw.Redraw(1)
+
+    if evt == On_Create_Click:
+        if Model_Type['BOLT'][0].val:
+            Create_Bolt()
+        if Model_Type['NUT'][0].val:
+            Create_Nut()
+        Draw.Redraw(1)
+    
+    elif (evt in [On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click]):
+        for k in Head_Type.iterkeys():
+            if Head_Type[k][1]!=evt:
+                Head_Type[k][0].val=0
+            else:
+                Head_Type[k][0].val=1    
+        Draw.Redraw(1)
+    
+    elif (evt in [On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click]):
+        for k in Bit_Type.iterkeys():
+            if Bit_Type[k][1]!=evt:
+                Bit_Type[k][0].val=0
+            else:
+                Bit_Type[k][0].val=1
+        Draw.Redraw(1)
+
+    elif (evt in [On_Model_Bolt_Click,On_Model_Nut_Click]):
+        for k in Model_Type.iterkeys():
+            if Model_Type[k][1]!=evt:
+                Model_Type[k][0].val=0
+            else:
+                Model_Type[k][0].val=1
+        Draw.Redraw(1)
+
+    elif (evt in [On_Hex_Nut_Click,On_Lock_Nut_Click]):
+        for k in Nut_Type.iterkeys():
+            if Nut_Type[k][1]!=evt:
+                Nut_Type[k][0].val=0
+            else:
+                Nut_Type[k][0].val=1
+        Draw.Redraw(1)
+    
+#####################################################################################
+      
+
+def Draw_Border(X1,Y1,X2,Y2): # X1,Y1 = Top Left X2,Y2 = Bottom Right
+    INDENT = 3
+    
+    BGL.glColor3f(1.0,1.0,1.0)
+    BGL.glBegin(BGL.GL_LINES)                
+    BGL.glVertex2i(X1+INDENT,Y1-INDENT)     #top line
+    BGL.glVertex2i(X2-INDENT,Y1-INDENT)
+    
+    BGL.glVertex2i(X1+INDENT,Y1-INDENT)     #left line
+    BGL.glVertex2i(X1+INDENT,Y2+INDENT)
+    BGL.glEnd()
+
+    BGL.glColor3f(0.5,0.5,0.5)
+    BGL.glBegin(BGL.GL_LINES)                
+    BGL.glVertex2i(X2-INDENT,Y1-INDENT)     #Right line
+    BGL.glVertex2i(X2-INDENT,Y2+INDENT)
+    
+    BGL.glVertex2i(X1+INDENT,Y2+INDENT)     #bottom line
+    BGL.glVertex2i(X2-INDENT,Y2+INDENT)
+    BGL.glEnd()
+    
+    
+
+
+def Create_Tab(X1,Y1,X2,Y2,Title,Buttons): # X1,Y1 = Top Left X2,Y2 = Bottom Right
+
+    BIT_BUTTON_WIDTH = 55
+    BIT_BUTTON_HEIGHT = 18
+    TITLE_HEIGHT = 15
+    INDENT = 6
+    BUTTON_GAP = 4
+
+    BGL.glColor3f(0.75, 0.75, 0.75)
+    BGL.glRecti(X1,Y1,X2,Y2)
+    
+    Draw_Border(X1,Y1,X2,Y2);
+    
+    BGL.glColor3f(0.0,0.0,0.0)
+    BGL.glRasterPos2d(X1+INDENT,Y1 - TITLE_HEIGHT)
+    Draw.Text(Title)
+    
+    Button_X = X1 + INDENT
+    Button_Y = Y1 - TITLE_HEIGHT - BIT_BUTTON_HEIGHT - 8
+    
+    #Nut_Number_X = Nut_Button_X
+    #Nut_Number_Y = Nut_Button_Y - 25
+    if (Buttons != 0):
+        key= Buttons.keys()
+        for k in key:
+            Buttons[k][0]= Draw.Toggle(k,Buttons[k][1],Button_X,Button_Y, BIT_BUTTON_WIDTH,BIT_BUTTON_HEIGHT,Buttons[k][0].val)
+            Button_X += BIT_BUTTON_WIDTH + BUTTON_GAP    
+    
+    
+    
+def Dispaly_Title_Bar(Y_POS,CONTROL_HEIGHT):
+    CONTROL_WIDTH = 250
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS -CONTROL_HEIGHT,"Bolt Factory V1.50_249",Model_Type)
+    
+    
+      
+def Dispaly_Preset_Tab(Y_POS,CONTROL_HEIGHT):
+    CONTROL_WIDTH = 250
+    BUTTON_Y_OFFSET = 40
+    
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Preset",0)
+    
+    name = "M3%x1|M4%x2|M5%x3|M6%x4|M8%x5|M10%x6|M12%x7"
+    
+    global Preset_Menu
+    Preset_Menu = Draw.Menu(name,No_Event,9,Y_POS-BUTTON_Y_OFFSET,50,18, Preset_Menu.val, "Just a test menu.")
+    Draw.Button("Apply",On_Preset_Click,150,Y_POS-BUTTON_Y_OFFSET,55,18)
+    
+
+def Dispaly_Bit_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+
+    Bit_Number_X = 3+3+3
+    Bit_Number_Y = Y_POS - 64
+        
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Bit Type",Bit_Type)
+    
+    if Bit_Type['NONE'][0].val:
+        DoNothing = 1;
+        
+    elif Bit_Type['ALLEN'][0].val:
+        global Allen_Bit_Depth
+        Allen_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Allen_Bit_Depth.val, 0,100, '')
+        Bit_Number_Y -= NUMBER_HEIGHT
+        global Allen_Bit_Flat_Distance
+        Allen_Bit_Flat_Distance = Draw.Number('Flat Dist: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH,NUMBER_HEIGHT,Allen_Bit_Flat_Distance.val, 0,100, '')
+        Bit_Number_Y -= NUMBER_HEIGHT
+
+    elif Bit_Type['PHILLIPS'][0].val:
+        global Phillips_Bit_Depth
+        Phillips_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Phillips_Bit_Depth.val, 0,100, '')
+        Bit_Number_Y -= NUMBER_HEIGHT
+        global Philips_Bit_Dia
+        Philips_Bit_Dia = Draw.Number('Bit Dia: ',No_Event,Bit_Number_X,Bit_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Philips_Bit_Dia.val, 0,100, '')
+        Bit_Number_Y -= NUMBER_HEIGHT
+
+
+
+def Dispaly_Shank_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+
+    Number_X = 3+3+3
+    Number_Y_Pos = Y_POS - 40
+        
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Shank",0)
+  
+    global Shank_Length 
+    Shank_Length = Draw.Number('Shank Length: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Length.val, 0,MAX_INPUT_NUMBER, 'some text tip')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Shank_Dia 
+    Shank_Dia = Draw.Number('Shank Dia: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Dia.val, 0,MAX_INPUT_NUMBER, 'some text tip')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    
+
+def Dispaly_Thread_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+    
+
+    Number_X = 3+3+3
+    Number_Y_Pos = Y_POS - 40
+            
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Thread",0)
+    
+    global Thread_Length
+    if Model_Type['BOLT'][0].val:
+        Thread_Length = Draw.Number('Thread Length: ',No_Event, Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Thread_Length.val, 0,MAX_INPUT_NUMBER, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Major_Dia
+    Major_Dia = Draw.Number('Major Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Major_Dia.val, 0,MAX_INPUT_NUMBER, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Minor_Dia
+    Minor_Dia = Draw.Number('Minor Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Minor_Dia.val, 0,MAX_INPUT_NUMBER, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Pitch
+    Pitch = Draw.Number('Pitch: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Pitch.val, 0.01,50.0, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+    
+    global Crest_Percent
+    Crest_Percent = Draw.Number('Crest %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Crest_Percent.val, 1,90, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Root_Percent
+    Root_Percent = Draw.Number('Root %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Root_Percent.val, 1,90, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+
+    
+    
+def Dispaly_Head_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+
+    Head_Number_X = 3+3+3
+    Head_Number_Y = Y_POS - 64
+        
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Head Type",Head_Type)
+    
+    if Head_Type['HEX'][0].val:  
+        global Hex_Head_Height
+        Hex_Head_Height = Draw.Number('Head Height: ',No_Event,Head_Number_X ,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Height.val, 0,100, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+        global Hex_Head_Flat_Distance
+        Hex_Head_Flat_Distance = Draw.Number('Head Hex Flat Distance ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+  
+    elif Head_Type['CAP'][0].val:  
+        global Cap_Head_Height
+        Cap_Head_Height = Draw.Number('Head Height: ',No_Event, Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Height.val, 0,100, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+        global Cap_Head_Dia
+        Cap_Head_Dia = Draw.Number('Head Dia ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+  
+    elif Head_Type['DOME'][0].val:  
+        global Dome_Head_Dia
+        Dome_Head_Dia = Draw.Number(' Dome Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Dome_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+  
+    elif Head_Type['PAN'][0].val:  
+        global Pan_Head_Dia
+        Pan_Head_Dia = Draw.Number('Pan Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Pan_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+  
+    
+    
+    
+def Dispaly_Nut_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+
+    Nut_Number_X = 3+3+3
+    Nut_Number_Y = Y_POS - 64
+   
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Nut Type",Nut_Type)
+        
+    #if Nut_Type['HEX'][0].val:  
+    global Hex_Nut_Height
+    Hex_Nut_Height = Draw.Number('Nut Height: ',No_Event,Nut_Number_X ,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Height.val, 0,MAX_INPUT_NUMBER, '')
+    Nut_Number_Y -= NUMBER_HEIGHT
+    global Hex_Nut_Flat_Distance
+    Hex_Nut_Flat_Distance = Draw.Number('Nut Flat Distance ',No_Event,Nut_Number_X,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
+    Nut_Number_Y -= NUMBER_HEIGHT
+  
+
+def Dispaly_Bolt_Tab():    
+       
+    Dispaly_Shank_Tab(284,66)
+    Dispaly_Head_Tab(374,90)
+    Dispaly_Bit_Tab(464,90)
+    
+
+##########################################################################################
+
+def gui():              # the function to draw the screen
+    
+    CONTROL_WIDTH = 250
+
+    BGL.glClearColor(0.6, 0.6, 0.6, 1.0)
+    BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
+    
+    BGL.glColor3f(0.75, 0.75, 0.75)
+    BGL.glRecti(3,30,CONTROL_WIDTH,3)
+    
+    Dispaly_Title_Bar(514,50);
+    
+    if Model_Type['BOLT'][0].val:
+        Dispaly_Bolt_Tab();
+    
+    if Model_Type['NUT'][0].val:
+        Dispaly_Nut_Tab(464,246);
+
+    Dispaly_Thread_Tab(218,138)
+
+    Dispaly_Preset_Tab(80,50)
+    
+    Draw.PushButton("Create",On_Create_Click,6,8,55,18,"Create Bolt")
+    Draw.Button("Exit",On_Exit_Click,6+55+4,8,55,18)
+    
+    #Draw.Button("Test",On_Test_Click,150,10,55,20)
+    #Draw.Button("Nut2",On_Nut2_Click,150,32,55,20)  
+   
+      #key.sort()
+   
+
+Draw.Register(gui, event, button_event)  # registering the 3 callbacks
diff --git a/release/scripts/wizard_landscape_ant.py b/release/scripts/wizard_landscape_ant.py
new file mode 100644
index 0000000000000000000000000000000000000000..405c06432ca7cec1892ce2a3e0466e6c71afddd1
--- /dev/null
+++ b/release/scripts/wizard_landscape_ant.py
@@ -0,0 +1,2148 @@
+#!BPY
+"""
+Name: 'Landscape Generator (A.N.T)'
+Blender: 248
+Group: 'Wizards'
+Tip: 'Create landscape mesh.'
+"""
+
+__author__ = "Jimmy Hazevoet"
+__url__     = ('http://wiki.blender.org/index.php/Scripts/Manual/Wizards/ANTLandscape','elysiun')
+__version__ = "v.1.05 03-2007"
+__bpydoc__ = """\
+
+Another Noise Tool 'Landscape' v.1.05
+
+This script uses noise functions to create a terrain from a grid mesh.
+
+Usage:
+
+Make new terrain:  press the "Add New Grid" button, change some noise settings and press the "Update" button.
+
+Work on previous made grid:  select the grid/terrain in the 3D view, and press the "Assign" button.
+
+Tip: use a low resolution grid mesh and add some Multires levels for detail
+
+Note: when using Multires materials can get weird,
+only apply materials when your terrain is ready, or not use Multires.
+
+This Script creates a landscape mesh.
+Press the Auto button when you start the script.
+Then the Generate Button & read it's tooltip.
+The mesh created is average 16000 verts.
+To me the mesh appears quite small in the 3d view.
+Just Press S in the 3d view to scale it up.
+This saves overhead drawing the Mesh.
+
+Known Issues:
+If the mesh is not drawn in the 3d view first time, 
+Move your mouse to the 3d view, or press the button again.
+
+Not really an issue, more to be aware.
+Due to the complex nature & design of the script, it only creates one mesh at a time.
+When you press Generate or Reset, 
+Even if you have Closed then Opened the script or .blend file,
+The mesh Will be Overwritten.
+To create Multiple Landscapes you Must Re-Name or save the Mesh
+in Blender's F7 menu Links & Materials Panel.
+
+Readme:
+v.1.04:
+_ New G.U.I.
+_ New noise types like: 
+Double_Terrain, 
+StatsByAlt_Terrain, 
+slickRock, 
+ditorted_heteroTerrain, 
+vlNoise_turbulence, 
+and many more.
+
+New fractalized Effect functions.     
+Effect types such as: gradient,
+waves and bumps, dome, piramide, 
+squares, grid, shattered rocks, 
+lunar, and many more.
+     
+Bias types: Sin, Cos, Tri, Saw, 
+and Default(no bias).
+    
+For example the 'Rings' effect 
+with 'Sin Bias' makes 'Rings' 
+and 'Default Bias' makes 'Dome'.
+The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, 
+-1.0=noise, 0.0=average, 1.0=effect
+this slider controls also the 'Warp amount' if mix type 'Warp' is selected.
+
+Image effect: mix image with noise
+_ IPOCurve Filter: use Ipo curve to filter terrain height.
+I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that)
+the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible.
+Usage:
+Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times),
+move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want,
+Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely.
+(use the 'Pin' option to keep the curves visible while other objects are selected)
+Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve.
+A curve filter is very versatile when it comes to 'height' filtering.
+
+_ PreView in UV/Image Editor Window:
+The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga'
+you have to select 'ANTview_size.tga' in the UV/Image Editor Window
+now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled),
+! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) !
+
+_ VertexColours: use any image as colour gradient.
+This function actualy uses one 'row' of pixels from a image to produce the color gradient,
+Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top.
+you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result) 
+Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel !
+
+_ Mesh Tiles: Create large scale terrains.
+
+_ Vertices Selection: select flat areas.
+
+_ Keyboard HotKeys:
+SPACE = Update mesh.
+R = Randomise.
+V = Redraw preview.
+
+_ and more...
+
+"""
+
+
+
+
+###
+#
+# Alt+P to start script.
+#
+###
+# scroll down to see info about updates
+##
+################################################################################################################
+# Another Noise Tool 'Landscape'
+# Jimmy Hazevoet
+# license: Do whatever you want with it.
+################################################################################################################
+
+################################################################################################################
+#   v.1.04:
+#
+# _ New G.U.I.
+# _ New noise types like: Double_Terrain, StatsByAlt_Terrain, slickRock, ditorted_heteroTerrain, vlNoise_turbulence, and many more.
+# _ New fractalized Effect functions.
+#      Effect types such as: gradient, waves and bumps, dome, piramide, squares, grid, shattered rocks, lunar, and many more.
+#      Bias types: Sin, Cos, Tri, Saw, and Default(no bias).
+#      For example the 'Rings' effect with 'Sin Bias' makes 'Rings' and 'Default Bias' makes 'Dome'.
+# _ The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, -1.0=noise, 0.0=average, 1.0=effect
+#      this slider controls also the 'Warp amount' if mix type 'Warp' is selected.
+# _ Image effect: mix image with noise
+# _ IPOCurve Filter: use Ipo curve to filter terrain height.
+#      I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that)
+#      the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible.
+#     Usage:
+#      Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times),
+#      move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want,
+#      Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely.
+#      (use the 'Pin' option to keep the curves visible while other objects are selected)
+#      Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve.
+#      A curve filter is very versatile when it comes to 'height' filtering.
+# _ PreView in UV/Image Editor Window:
+#      The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga'
+#      you have to select 'ANTview_size.tga' in the UV/Image Editor Window
+#      now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled),
+#      ! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) !
+# _ VertexColours: use any image as colour gradient.
+#      This function actualy uses one 'row' of pixels from a image to produce the color gradient,
+#      Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top.
+#      you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result) 
+#      Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel !
+# _ Mesh Tiles: Create large scale terrains.
+# _ Vertices Selection: select flat areas.
+# _ Keyboard HotKeys:
+#      SPACE = Update mesh.
+#      R = Randomise.
+#      V = Redraw preview.
+# _ and more...
+################################################################################################################
+
+################################################################################################################
+# BugFix: Sept./2006  v.1.04a
+#-----------------------------
+# _Image Effect did not worked well with tiled mesh. Fixed (now use Freq. and Loc. buttons to scale and position image).
+#
+################################################################################################################
+
+
+################################################################################################################
+# UPDATE: v.1.05  03-2007
+#---------------------------------------------------------------------------------------------------------------
+#
+# _ New: Save and Load function, save your settings to a .ant file.
+# __NOTE: when saving/loading settings to/from a file,
+#         make sure the filename/path is not too long!
+# __HOTKEY__ Load from file: L
+# __HOTKEY__ Save to file  : S
+#
+# _ New mesh code, uses Mesh instead of NMesh,
+#        this gives a small speed improvement and alows you to use Multires.
+#
+#   Usage: Select a Grid/Terrain mesh and hit the Assign button, now you can work on it, when ready you assign another.
+#
+# _ New: 'Musgrave' noise types, 'Random noise' and 'Constant' in 'Effects' section.
+# _ New: 'Custom Effect', write custom formulae ( x,y, a,b, from math import *, from Blender.Noise import * )
+# _ New: 'Custom Height Filter', write custom formulae ( x,y, h, a,b, from math import *, from Blender.Noise import * )
+# _ New: 'Change Filter Order', Toggle: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff
+#
+# _ If you want to make a tiled terrain, you need to set the coordinates to "WorldSpace" or "Center at Cursor" (in G.U.I.Noise panel),
+#   create and place the grid meshes. now one by one select, assign and update, you may need to adjust the "EdgeFalloff" size.
+#
+# WARNING!: when using Multires, materials can get weird (?), so apply materials when your terrain is finnished.
+#
+###############################################################################################################
+
+
+###############################################################################################################
+#
+##  Execute Script: Alt P 
+#
+
+
+import Blender
+from Blender import * 
+from math import *
+from Blender.Noise import * 
+from Blender.Draw import *
+from Blender.BGL import *
+from Blender import Image
+import string
+from string import strip
+import BPyMathutils
+from BPyMathutils import genrand
+from random import choice
+scene = Scene.GetCurrent()
+
+###---------------------------------------------------------------------------
+
+CurVersion = 'A.N.T.Landscape v.1.05'
+
+##---------------------------------------------------------------------------
+# Customise default settings: ----------------------------------------------
+
+# Names:
+antfilename = 'Terrain'   # Default filename
+previewname = Create('')  # Default preview Image name
+DefaultIpoName  = ''      # Default Ipo DataBlock name (for height filter)
+# G.U.I.:
+FullScreen = Create( 0 )            # FullScreen on/off
+# gui colors:
+ledcolors = [ [1.0,0.498,0.498], [1.0,0.698,0.498], [1.0,0.898,0.498], [0.898,1.0,0.498], [0.698,1.0,0.498], [0.498,1.0,0.498], [0.498,1.0,0.698], [0.498,1.0,0.898], [0.600,0.918,1.0], [0.6,0.757,1.0], [0.6,0.6,1.0], [0.757,0.6,1.0], [0.898,0.498,1.0], [1.0,0.498,0.898] ]
+#ledcolor   = [ 1.0, 0.5, 0.0 ]
+lightgrey  = [ 0.76, 0.76, 0.76 ]   # gui col.
+grey       = [ 0.6, 0.6, 0.6 ]      # panel col.
+background = [ 0.7, 0.7, 0.7, 1.0 ] # background col.
+black      = [ 0.0, 0.0, 0.0 ]      # text col.
+white      = [ 1.0, 1.0, 1.0 ]
+# gui size
+size_x  = 320                       # gui x size
+size_y  = 280                       # gui y size
+# tabs
+guitabs = [ Create( 1 ), Create( 0 ), Create( 0 ), Create( 0 ), Create( 0 ) ]  # gui Tabs
+# How long does it take to generate a mesh or image ?
+print_time = 0 # 1 = Print time in console.
+
+# end customise. ----------------------------------------------------------
+##--------------------------------------------------------------------------
+###--------------------------------------------------------------------------
+####--------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+
+dirpath=Blender.sys.dirname(Blender.Get('filename'))
+fname=dirpath.replace('\\','/')+'/' + antfilename + '.ant'
+txtFile = Create( fname )
+
+###---------------------------------------------------------------------------
+columns = 10 # gui columns
+rows    = 13 # gui rows
+actob = [] # active object
+actme = [] # active mesh
+ipoblockname=''
+thiscurve=[]
+selectedcurve=0
+phi=3.14159265359
+# events
+App_Evt = 144
+New_Evt = 166
+SelFile_Evt  = 71
+LoadFile_Evt = 72
+SaveFile_Evt = 73
+UseMe_Evt = 74
+No_Evt   = 1
+Btn_Evt  = 2
+Msh_Evt  = 12
+Upd_Evt  = 3
+Rndm_Evt = 4
+Load_Evt = 5
+Sel_Evt  = 6
+Save_Evt = 7
+Rend_Evt = 8
+End_Evt  = 9
+Scrn_Evt = 15
+Im_Evt   = 16
+gt0_Evt  = 20
+gt1_Evt  = 21
+gt2_Evt  = 22
+gt3_Evt  = 23
+gt4_Evt  = 24
+Ipo_Evt  = 17
+New_Ipo_Evt=700
+
+###---------------------------------------------------------------------------
+# menus
+noisetypemenu  = "Noise type: %t|multiFractal %x0|ridgedMFractal %x1|hybridMFractal %x2|heteroTerrain %x3|fBm %x4|turbulence %x5|Voronoi turb. %x6|vlNoise turb. %x7|noise %x8|cellNoise %x9|Marble %x10|lava_multiFractal %x11|slopey_noise %x12|duo_multiFractal %x13|distorted_heteroTerrain %x14|slickRock %x15|terra_turbulence %x16|rocky_fBm %x17|StatsByAlt_Terrain %x18|Double_Terrain %x19|Shattered_hTerrain %x20|vlhTerrain %x21"
+noisebasismenu = "Basis %t|Blender Original%x0|Original Perlin%x1|Improved Perlin%x2|Voronoi_F1%x3|Voronoi_F2%x4|Voronoi_F3%x5|Voronoi_F4%x6|Voronoi_F2-F1%x7|Voronoi Crackle%x8|CellNoise%x9"
+voronitypemenu = "Voronoi type %t|Distance %x0|Distance Squared %x1|Manhattan %x2|Chebychev %x3|Minkovsky 1/2 %x4|Minkovsky 4 %x5|Minkovsky %x6"
+tBasismodemenu = "Terrain basis mode: %t|noise %x0|ridged noise %x1|vlNoise %x2|ridged vlNoise %x3"
+effecttypemenu = ['Effect Type %t','No Effect %x0','Image %x1','Turbulence %x2','vlNoise %x3','Marble %x4', 'multiFractal %x5','ridgedMFractal %x6','hybridMFractal %x7','heteroTerrain %x8','fBm %x9', 'Gradient %x10','Waves and Bumps %x11','ZigZag %x12','Wavy %x13','Sine Bump %x14','Dots %x15','Rings / Dome %x16','Spiral %x17','Square / Piramide %x18','Blocks %x19','Grid %x20','Tech %x21','Crackle %x22','Sparse Cracks %x23','Shattered Rocks %x24','Lunar %x25','Cosine noise %x26','Spike noise %x27','Stone noise %x28','Flat Turb %x29','Flat Voroni %x30','Random noise %x31','Constant %x32','Custom Effect %x33' ]
+mixtypemenu    = ['Mix Type %t','Effect only %x0','%l','Mix %x1','Add %x2','Subtract %x3','Multiply %x4','Difference %x5','Screen %x6','addmodulo %x7','Minimum %x8','Maximum %x9','%l','Warp Effect %x10','Warp Noise %x11']
+biastypemenu   = "Bias %t|Sin bias %x0|Cos bias %x1|Tri bias %x2|Saw bias %x3|Default (no bias)%x4"
+sharptypemenu  = "Sharpen %t|Soft %x0|Sharp %x1|Sharper %x2"
+filtermodemenu = "Filter Mode %t|No Filter %x0| %l|Default Filters %x1|IPOCurve Filter %x2|Custom Filter %x3"
+filtertypemenu = "Filter Type %t|Default Terrace %x0|Sharper Terrace %x1|Rounded Terrace %x2|Posterise Mixed %x3|Posterise %x4|Layered Peaks %x5|Peaked %x6|Smooth-thing %x7|Sin bias %x8|Cos bias %x9|Tri bias %x10|Saw bias %x11|Clamp Max. %x12"
+falloftypemenu = "Edge Falloff %t|No Edge Falloff %x0| %l|Soft Falloff %x1|Default Falloff %x2|Hard Falloff %x3|Linear Falloff Y %x4|Linear Falloff X %x5|Diagonal Falloff + %x6|Diagonal Falloff - %x7|Square %x8|Round %x9"
+randomtypemenu = "Random type: %t|setRandomSeed() : Blender.Noise %x0|Rand() : Blender.Mathutils %x1|genrand() : BPyMathutils MersenneTwister %x2"
+
+##--------------------------------------------------
+def Set_ReSet_Values():
+	global fileinfo, filemessage
+	global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly, WorldSpaceCo
+	global NType, Basis, musgr, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, tBasismod, musgrTwo
+	global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+	global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, AutoUpd, PreView, DefaultIpoName
+
+	filemessage = ''
+	fileinfo    = ''
+	effect_image = 'Load and Select image.'
+	AutoUpd  = Create( 0 )
+	PreView = [ Create( 0 ), Create( 1.0 ), Create( 0.0 ) ]
+	## Coords controls:
+	WorldSpaceCo = Create(0)
+	iScale = [ Create( 1.0 ), Create( 1.0 ), Create( 0.25) ]
+	Offset = [ Create( 0.0 ), Create( 0.0), Create( 0.0) ]
+	Invert = [ Create( 0 ), Create( 0 ), Create( 0 ) ]
+	NSize = [ Create( 1.0 ), Create( 2.0 ) ]
+	Sx = [ Create( 1.0 ), Create( 1.0 ) ]
+	Sy = [ Create( 1.0 ), Create( 1.0 ) ]
+	Lx = [ Create( 0.0 ), Create( 0.0 ) ]
+	Ly = [ Create( 0.0 ), Create( 0.0 ) ]
+	## Noise controls:
+	NType = Create( 3 )
+	Basis = [ Create( 0 ), Create( 0 ) ]
+	musgr = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ), Create( 0.5 ) ]
+	vlnoi = [ Create( 1.0 ), Create( 0 ) ]
+	vlnoiTwo = [ Create( 1.0 ), Create( 0 ) ]
+	voron = [ Create( 0 ), Create( 2.5 ) ]
+	turbOne = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ]
+	marbleOne = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ]
+	tBasismod = Create(0)
+	## Effect controls:
+	musgrTwo = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ) ]
+	turbTwo = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ]
+	marbleTwo = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ]
+	Effect_Ctrl = [ Create( 0 ),Create( 2 ),Create( 0.0 ),Create( 0 ),Create( 0.0 ) ,Create( 0 ),Create( 2.0 ),Create( 0.5 ),Create( 0.5 ) ]
+	CustomFX = [ Create('sin(x*pi)'), Create('cos(y*pi)'), Create('abs(a*b)*0.5') ]
+	## Filter controls:
+	Min = Create( 0.0 )
+	Max = Create( 1.0 )
+	Falloff = [ Create( 2 ), Create( 1.0 ), Create( 1.0 ), Create( 0 ) , Create( 0 ) ]
+	Filter_Mode = Create( 0 )
+	Def_Filter_Ctrl = [ Create( 0 ), Create( 3.0 ) ]
+	Ipo_Filter_Ctrl = [ Create( DefaultIpoName ), Create( 0 ), Create( 100.0 ), Create( 100.0 ) ]
+	Filter_Order =  Create( 0 )
+	CustomFilt = [ Create('sqrt(h*h)**2'), Create('0'), Create('a') ]
+	## Randomise noise buttons:
+	RandMod = Create( 1 )
+	RSeed   = Create( 0 )
+	rand_I  = Create( 0 )
+	rand_H  = Create( 0 )
+	rand_S  = Create( 0 )
+	rand_L  = Create( 1 )
+
+##-------------------------
+Set_ReSet_Values()
+
+
+####----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+## G.U.I.: text,backpanel,panel
+#--------------------------------------------------
+def draw_Text( ( x, y ), text, color, size ):
+	glColor3f( color[0],color[1],color[2] )
+	glRasterPos2d(x,y)
+	txtsize = 'small', 'normal', 'large'
+	Text( text, txtsize[ size ] )
+def draw_BackPanel( text, x, y, w, h, colors ):
+	glColor3f( colors[0]*0.76, colors[1]*0.76, colors[2]*0.76 )
+	glRecti( x, h, w, h+20 )
+	glColor3f( colors[0], colors[1], colors[2] )
+	glRecti( x, y, w, h )
+	glColor3f( colors[0], colors[1], colors[2] )
+	glRasterPos2d( x+10, h+5 )
+	Text( text, 'small' )
+def draw_Panel( x, y, w, h, colors ):
+	glColor3f( colors[0], colors[1], colors[2] )
+	glRecti( x,y, w,h )
+def draw_Frame( text, x, y, w, h, color ):
+   glColor3f( color[0], color[1], color[2] )
+   glRasterPos2i(x+3,h-3)
+   Text(text ,'small')
+   stringwidth = GetStringWidth( text,'small' )
+   glColor3f( color[0], color[1], color[2]  )
+   glBegin(Blender.BGL.GL_LINE_STRIP)
+   glVertex2i(x,h)
+   glVertex2i(x,y)
+   glVertex2i(w,y)
+   glVertex2i(w,h)
+   glVertex2i(x+stringwidth+10,h)
+   glEnd()
+def draw_Led( x, y, colors ):
+	glColor3f( colors[0], colors[1], colors[2] )
+	glRecti( x,y, x+4,y+4 )
+
+
+###----------------------------------------------------------------------------------------------------
+## G.U.I. Buttons:
+#----------------------------------------------------------------------------------------------------
+
+###-------------------------
+## Main / Mesh Buttons:
+#
+def MeshButtons( col, row, width, height ):
+	global actme, actob, AutoUpd, txtFile, filemessage, fileinfo
+
+	PushButton("I", UseMe_Evt, col[8], row[3], width[0], height[1], "Info: Here you can write some text to save with the file." )
+	draw_Text( ( col[0], row[1]+5 ), 'Info: ' + fileinfo, black, 0 )
+	txtFile = String("",  No_Evt,      col[0], row[2], width[9], height[1],  txtFile.val, 256, "File: Full path and filename" )
+	PushButton( "Select", SelFile_Evt, col[1], row[3], width[0], height[1], "File: Open FileBrowser and select *.ant file" )
+	PushButton( "Load",   LoadFile_Evt,col[2], row[3], width[2], height[1], "File: Load settings from file ( HotKey: L )" )
+	PushButton( "Save",   SaveFile_Evt,col[5], row[3], width[2], height[1], "File: Save settings to file ( HotKey: S )" )
+
+	activeobname = ''
+	if actme !=[]:
+		activeobname = actob[0].name
+	draw_Text( ( col[5]+5, row[7]-5 ), 'OB: ' + activeobname, [0.0,0.0,1.0], 1 )
+	PushButton( "Add New Grid",    New_Evt, col[0], row[6], width[4], height[2] )
+	PushButton( "Assign Selected", App_Evt, col[5], row[6], width[4], height[2], 'Assign selected terrain')
+
+###-------------------------
+## Noise Buttons:
+#
+def NoiseButtons( col, row, width, height ):
+	global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy, WorldSpaceCo
+	global Ha, La, Oc, Of, Ga, Basis, NType, musgr, vlnoi, voron, turbOne, tBasismod 
+	global Depth, Hard, Amp, Freq, vlBasis, Distort, VFunc, VExp, VDep, marbleOne
+	global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I
+
+	bth = height[1]/2+5
+	iScale[0] = Number("iScale:", Btn_Evt, col[5], row[2]+bth, width[3], height[1], iScale[0].val,   -10.0, 10.0 , "Noise: Intensity Scale." )
+	Invert[0] = Toggle("Inv.",    Btn_Evt, col[9], row[2]+bth, width[0], height[1], Invert[0].val, "Noise: Invert")
+	Offset[0] = Number("Offset:", Btn_Evt, col[5], row[3]+bth, width[4], height[1], Offset[0].val,   -10.0, 10.0 , "Noise: Offset " )
+	NSize[0] = Number("Noise Size:",Btn_Evt, col[5], row[5], width[4], height[2], NSize[0].val, 0.001, 10.0 , "Noise Size" )
+	Sx[0]     = Number("Size X:", Btn_Evt, col[5], row[6], width[4], height[1], Sx[0].val,    0.001, 10.0 , "Size X" )
+	Sy[0]     = Number("Size Y:", Btn_Evt, col[5], row[7], width[4], height[1], Sy[0].val,    0.001, 10.0 , "Size Y" )
+	Lx[0]     = Number("Loc X:",  Btn_Evt, col[5], row[8], width[4], height[1], Lx[0].val,  -10000.0, 10000.0 , "Loc X" )
+	Ly[0]     = Number("Loc Y:",  Btn_Evt, col[5], row[9],width[4], height[1], Ly[0].val,  -10000.0, 10000.0 , "Loc Y" )
+	WorldSpaceCo = Menu( "Coordinates %t|Local Space %x0|World Space %x1|Center at CursorPos %x2", Btn_Evt, col[5], row[10], width[4], height[1], WorldSpaceCo.val, "x,y,z coordinates for noise, effect and height falloff " )
+
+	NType = Menu( noisetypemenu,       Btn_Evt, col[0], row[2], width[4], height[2], NType.val, "Noise type" )
+	if NType.val == 6:
+		voron[0] = Menu( voronitypemenu, Btn_Evt, col[0], row[3], width[4], height[1], voron[0].val, "Voronoi type" )
+	else:
+		if NType.val != 9:
+			Basis[0] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[0].val, "Noise Basis" )
+
+	if NType.val in [0,1,2,3,4,11,12,13,14,15,17,18,19,20,21]:
+		musgr[0] = Slider( "H: ",          Btn_Evt, col[0], row[5], width[4], height[1], musgr[0].val,  0.0, 3.0, 0 ,  "H" )
+		musgr[1] = Slider( "Lacu: ",       Btn_Evt, col[0], row[6], width[4], height[1], musgr[1].val,  0.0, 6.0, 0 ,  "Lacunarity" )
+		musgr[2] = Slider( "Octs: ",       Btn_Evt, col[0], row[4], width[4], height[1], musgr[2].val,    0, 12,  0 , "Octaves" )
+	if NType.val in [1,2,3,13,14,15,18,19,20,21]:
+		musgr[3] = Slider( "Offst: ",      Btn_Evt, col[0], row[7], width[4], height[1], musgr[3].val,  0.0, 6.0, 0 ,  "Offset" )
+	if NType.val in [1,2,13,15,18]:
+		musgr[4] = Slider( "Gain: ",       Btn_Evt, col[0], row[8], width[4], height[1], musgr[4].val,  0.0, 6.0, 0 ,  "Gain" )
+	if NType.val == 19:
+		musgr[5] = Slider( "Thresh: ",     Btn_Evt, col[0], row[8], width[4], height[1], musgr[5].val,  0.001, 2.0, 0 ,  "Threshold" )
+	if NType.val in [5,6,7,16]:
+		turbOne[0] = Number( "Depth:",     Btn_Evt, col[0], row[4], width[4], height[1], turbOne[0].val, 0, 12, "Octaves")
+		turbOne[1] = Toggle( "Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbOne[1].val,        "Soft noise / Hard noise")
+		turbOne[2] = Slider( "Amp:",       Btn_Evt, col[0], row[6], width[4], height[1], turbOne[2].val, 0.0, 3.0, 0, "Ampscale ")
+		turbOne[3] = Slider( "Freq:",      Btn_Evt, col[0], row[7], width[4], height[1], turbOne[3].val, 0.0, 6.0, 0, "Freqscale")
+	if NType.val in [18,19]:
+		tBasismod = Menu( tBasismodemenu,  Btn_Evt, col[0], row[9], width[4], height[1], tBasismod.val, "Terrain basis mode.")
+	if NType.val == 6:
+		if voron[0].val == 6:
+			voron[1] = Slider( "Exp: ",      Btn_Evt, col[0], row[8], width[4], height[1], voron[1].val, 0.0,10.0, 0, "Minkovsky exponent")
+	if NType.val in [7,11,12,14,20,21]:
+		vlnoi[0] = Slider( "Dist: ",       Btn_Evt, col[0], row[8], width[4], height[1], vlnoi[0].val,  0.0, 10.0, 0 , "Distort" )
+	if NType.val in [7,13,14,15,21]:
+		vlnoi[1] = Menu(noisebasismenu,    Btn_Evt, col[0], row[9], width[4], height[1], vlnoi[1].val, "Distortion Noise")
+	if NType.val == 10:
+		marbleOne[0] = Number(  "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleOne[0].val, 0, 12, "Octaves")
+		marbleOne[2] = Slider(  "Turb: ",  Btn_Evt, col[0], row[7], width[4], height[1], marbleOne[2].val,  0.0,20.0, 0, "Turbulence ")
+		marbleOne[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleOne[3].val, "Bias")
+		marbleOne[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleOne[5].val,  0.0,20.0, 0, "ReScale")
+		if marbleOne[3].val != 4:
+			marbleOne[4] = Menu(sharptypemenu, Btn_Evt ,col[0], row[5], width[4], height[1], marbleOne[4].val, "Sharpen")
+
+	RandMod = Menu( randomtypemenu, No_Evt, col[0], row[10], width[0], height[1], RandMod.val, "Random Type" )
+	rand_H = Toggle("TH",No_Evt ,col[1], row[10], width[0], height[1], rand_H.val, "Randomise Terrain Height ( in Height panel )")
+	rand_I = Toggle("NH",No_Evt ,col[2], row[10], width[0], height[1], rand_I.val, "Randomise Noise Height")
+	rand_S = Toggle("NS",No_Evt ,col[3], row[10], width[0], height[1], rand_S.val, "Randomise Noise Size")
+	rand_L = Toggle("NL",No_Evt ,col[4], row[10], width[0], height[1], rand_L.val, "Randomise Noise Location")
+
+###-------------------------
+## Effect Buttons:
+#
+def EffectButtons( col, row, width, height ):
+	global Effect_Type, Effect_Ctrl, Blend_Effect, CustomFX
+	global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy
+	global BasisTwo, turbTwo, marbleTwo, vlnoiTwo, musgrTwo
+
+	Effect_Ctrl[0] = Menu( '|'.join( effecttypemenu ), Btn_Evt, col[0], row[2], width[4], height[2], Effect_Ctrl[0].val, "Effect: Type" )
+	if Effect_Ctrl[0].val != 0:
+		Effect_Ctrl[1] = Menu( '|'.join( mixtypemenu ),    Btn_Evt, col[5], row[2], width[4], height[2], Effect_Ctrl[1].val, "Mix: Type" )
+		if Effect_Ctrl[1].val in [10,11]:
+			Effect_Ctrl[2] = Slider("Warp: ",   Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" )
+		else: Effect_Ctrl[2] = Slider("Mix: ",Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" )
+
+		iScale[1] = Number("iScale:",   Btn_Evt, col[5], row[4], width[3], height[1], iScale[1].val,   -20.0, 20.0 , "Effect: Intensity Scale " )
+		Invert[1] = Toggle("Inv.",      Btn_Evt, col[9], row[4], width[0], height[1], Invert[1].val, "Effect: Invert")
+		Offset[1] = Number("Offset:",   Btn_Evt, col[5], row[5], width[4], height[1], Offset[1].val,   -20.0, 20.0 , "Effect: Offset " )
+		NSize[1]  = Number("Frequency:",Btn_Evt, col[5], row[6], width[4], height[1], NSize[1].val, 0.001, 100.0, "Effect Frequency ( Scale )" )
+		Sx[1]     = Number("Freq X:",   Btn_Evt, col[5], row[7], width[4], height[1],  Sx[1].val,    -50.0, 50.0 , "Effect Frequency X ( ScaleX )" )
+		Sy[1]     = Number("Freq Y:",   Btn_Evt, col[5], row[8], width[4], height[1],  Sy[1].val,    -50.0, 50.0 , "Effect Frequency Y ( ScaleY )" )
+		Lx[1]     = Number("Loc X:",    Btn_Evt, col[5], row[9], width[4], height[1],  Lx[1].val, -1000.0, 1000.0 , "Effect Loc X" )
+		Ly[1]     = Number("Loc Y:",    Btn_Evt, col[5], row[10], width[4], height[1], Ly[1].val, -1000.0, 1000.0 , "Effect Loc Y" )
+
+		if Effect_Ctrl[0].val == 1:
+			PushButton("Load Image",   Load_Evt, col[0], row[4], width[4], height[2] , "Load Image")
+			PushButton("Select Image", Sel_Evt,  col[0], row[6], width[4], height[3] , "Select Image")
+			draw_Text( ( col[0]+5, row[7] ), effect_image, black, 1 )
+
+		if Effect_Ctrl[0].val in [2,3,4,5,6,7,8,9]:
+				Basis[1] = Menu( noisebasismenu,   Btn_Evt, col[0], row[3], width[4], height[1], Basis[1].val, "Basis" )
+
+		if Effect_Ctrl[0].val == 2:
+				turbTwo[0] = Number(  "Depth:",    Btn_Evt, col[0], row[4], width[4], height[1], turbTwo[0].val, 1, 12, "Octaves")
+				turbTwo[1] = Toggle("Hard noise",  Btn_Evt, col[0], row[5], width[4], height[1], turbTwo[1].val,        "Hard noise")
+				turbTwo[2] = Slider(    "Amp:",    Btn_Evt, col[0], row[6], width[4], height[1], turbTwo[2].val, 0.0, 3.0, 0, "Ampscale ")
+				turbTwo[3] = Slider(   "Freq:",    Btn_Evt, col[0], row[7], width[4], height[1], turbTwo[3].val, 0.0, 6.0, 0, "Freqscale")
+		if Effect_Ctrl[0].val == 3:
+				vlnoiTwo[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[4], width[4], height[1], vlnoiTwo[1].val, "Distortion Noise")
+				vlnoiTwo[0] = Slider( "Dist: ",    Btn_Evt, col[0], row[5], width[4], height[1], vlnoiTwo[0].val,  0.0, 10.0, 0 , "Distort" )
+		if Effect_Ctrl[0].val == 4:
+				marbleTwo[0] = Number(  "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleTwo[0].val, 1, 12, "Octaves")
+				marbleTwo[2] = Slider(  "Turb: ",  Btn_Evt, col[0], row[7], width[4], height[1], marbleTwo[2].val,  0.0,20.0, 0, "Turbulence")
+				marbleTwo[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleTwo[3].val, "Bias")
+				marbleTwo[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleTwo[5].val,  0.0,20.0, 0, "ReScale")
+				if marbleTwo[3].val != 4:
+					marbleTwo[4] = Menu(sharptypemenu,Btn_Evt ,col[0], row[5], width[4], height[1], marbleTwo[4].val, "Sharpen")
+
+		if Effect_Ctrl[0].val in [5,6,7,8,9]:
+			musgrTwo[0] = Slider( "H: ",     Btn_Evt, col[0], row[5], width[4], height[1], musgrTwo[0].val,  0.0, 3.0, 0 ,  "H" )
+			musgrTwo[1] = Slider( "Lacu: ",  Btn_Evt, col[0], row[6], width[4], height[1], musgrTwo[1].val,  0.0, 6.0, 0 ,  "Lacunarity" )
+			musgrTwo[2] = Slider( "Octs: ",  Btn_Evt, col[0], row[4], width[4], height[1], musgrTwo[2].val,    0, 12,  0 , "Octaves" )
+		if Effect_Ctrl[0].val in [6,7,8]:
+			musgrTwo[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgrTwo[3].val,  0.0, 6.0, 0 ,  "Offset" )
+		if Effect_Ctrl[0].val in [6,7]:
+			musgrTwo[4] = Slider( "Gain: ",  Btn_Evt, col[0], row[8], width[4], height[1], musgrTwo[4].val,  0.0, 6.0, 0 ,  "Gain" )
+
+		if Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31:
+				Effect_Ctrl[5] = Number("Depth:",  Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[5].val,   0, 12   ,  "Fractalize Effect: Octaves" )
+				Effect_Ctrl[4] = Number("Distort:",Btn_Evt, col[0], row[7], width[4], height[1], Effect_Ctrl[4].val, 0.0, 50.0 ,  "Distort Effect: Amount" )
+				Effect_Ctrl[6] = Slider("Freq:",   Btn_Evt, col[0], row[5], width[4], height[1], Effect_Ctrl[6].val, 0.0, 6.0, 0, "Fractalize Effect: Frequency" )
+				Effect_Ctrl[7] = Slider("Amp:",    Btn_Evt, col[0], row[6], width[4], height[1], Effect_Ctrl[7].val, 0.0, 3.0, 0, "Fractalize Effect: Amplitude" )
+				if Effect_Ctrl[0].val < 22:
+					Effect_Ctrl[3] = Menu(biastypemenu, Btn_Evt ,col[0], row[3], width[4], height[1], Effect_Ctrl[3].val, "Effect bias")
+		if Effect_Ctrl[0].val in [31,32]:
+				Effect_Ctrl[8] = Number("Amount:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[8].val, -20.0, 20.0, "Effect: Amount" )
+		if Effect_Ctrl[0].val == 33:
+			draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 )
+			CustomFX[0] = String(      "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFX[0].val,96, "a" )
+			CustomFX[1] = String(      "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFX[1].val,96, "b" )
+			CustomFX[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFX[2].val,96, "result" )
+	
+###-------------------------
+## Filter / Height Buttons:
+#
+def FilterButtons( col, row, width, height ):
+	global iScale, Offset, Invert, Min, Max, Falloff, CustomFilt
+	global Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, DefaultIpoName, Filter_Order
+
+	iScale[2] = Number("Height:", Btn_Evt, col[5], row[2], width[3], height[2], iScale[2].val,   -10.0, 10.0 , "Terrain Height:  Scale" )
+	Invert[2] = Toggle("Inv.",    Btn_Evt, col[9], row[2], width[0], height[2], Invert[2].val, "Terrain Height:  Invert")
+	Offset[2] = Number("Offset:", Btn_Evt, col[5], row[3], width[4], height[1], Offset[2].val,   -10.0, 10.0 , "Terrain Height:  Offset" )
+	Max = Number(    "Plateau:",  Btn_Evt, col[5], row[5], width[4], height[1], Max.val, Min.val, 1.0 , "Terrain Height:  Clamp Max. ( Plateau )" )
+	Min = Number(    "Sealevel:", Btn_Evt, col[5], row[6], width[4], height[1], Min.val, -1.0, Max.val , "Terrain Height:  Clamp Min. ( Sealevel )" )
+	Falloff[0] = Menu( falloftypemenu, Btn_Evt ,col[5], row[9], width[4], height[2], Falloff[0].val, "Terrain Height:  Edge falloff")
+	if Falloff[0].val !=0:
+		Falloff[1] = Number("X:",   Btn_Evt, col[5], row[10], width[1], height[1], Falloff[1].val , 0.01, 100.0 , "Edge falloff:  X Size" )		
+		Falloff[2] = Number("Y:",   Btn_Evt, col[8], row[10], width[1], height[1], Falloff[2].val , 0.01, 100.0 , "Edge falloff:  Y Size" )
+		Falloff[4] = Toggle("Inv.", Btn_Evt, col[7], row[10], width[0], height[1], Falloff[4].val, "Edge falloff:  Invert")
+		Falloff[3] = Toggle("Edge At Sealevel", Btn_Evt, col[5], row[7], width[4], height[1], Falloff[3].val, "Edge falloff:  Edge at Sealevel")
+
+	Filter_Mode = Menu( filtermodemenu,               No_Evt, col[0], row[2], width[4], height[2], Filter_Mode.val, "Filter:  Mode")
+	if Filter_Mode.val ==1:
+		Def_Filter_Ctrl[0] = Menu( filtertypemenu,     Btn_Evt, col[0], row[5], width[4], height[2], Def_Filter_Ctrl[0].val, "Filter:  Type")
+		Def_Filter_Ctrl[1] = Number("Amount: ",        Btn_Evt, col[0], row[6], width[4], height[1], Def_Filter_Ctrl[1].val, 0.1, 100.0 , "Filter:  Amount" )
+
+	if Filter_Mode.val ==2:
+		Ipo_Filter_Ctrl[0] = String("IP:",              Ipo_Evt, col[0], row[5], width[4], height[2], Ipo_Filter_Ctrl[0].val,20, "Ipo datablock name" )
+		if Ipo_Filter_Ctrl[0].val !='':
+			Ipo_Filter_Ctrl[1] = Number("Use This Curve:",Ipo_Evt, col[0], row[7], width[4], height[3], Ipo_Filter_Ctrl[1].val, 0, 29, "Select curve to use" )
+			Ipo_Filter_Ctrl[2] = Number("Curve Length:",  Ipo_Evt, col[0], row[8], width[4], height[1], Ipo_Filter_Ctrl[2].val, 0.0, 1000.0, "X: Length (number of frames) of the selected curve." )
+			Ipo_Filter_Ctrl[3] = Number("Curve Height:",  Ipo_Evt, col[0], row[9], width[4], height[1], Ipo_Filter_Ctrl[3].val, 0.0, 1000.0, "Y: Height (offset) of the selected curve." )
+		else:
+			draw_Text( ( col[0]+5, row[6] ), 'Enter Ipo DataBlock name,' , black, 0 )
+			draw_Text( ( col[0]+5, row[9] ), 'or else:' , black, 0 )
+		PushButton( "New IpoDataBlock/Object", New_Ipo_Evt, col[0], row[10], width[4], height[1], "Creates new Ipo Object(Empty), and Ipo DataBlock(curves)' to use as height filter")
+
+	if Filter_Mode.val ==3:
+		draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 )
+		CustomFilt[0] = String(      "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFilt[0].val,96, "a" )
+		CustomFilt[1] = String(      "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFilt[1].val,96, "b" )
+		CustomFilt[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFilt[2].val,96, "result" )
+	if Filter_Mode.val !=0:
+		Filter_Order = Toggle("Change Filter Order",   Btn_Evt, col[0], row[3], width[4], height[1], Filter_Order.val, "Filter Order: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff.")
+
+###-------------------------
+## Option / Generate Image Buttons:
+#
+def OptionButtons( col, row, width, height ):
+	global PreView, previewname
+
+	PreView[0] = Toggle("Make Image", No_Evt, col[0], row[2], width[4], height[2], PreView[0].val, "Image: On/Off (Make a new Image in UV/ImageEditor Window, and give a name to it)")
+	if PreView[0].val !=0:
+		previewname = String( "IM:", No_Evt, col[0], row[3], width[4], height[1] ,previewname.val, 16, "IM:Name, Render terrain height to this image" )
+		PreView[1] = Number("",      Im_Evt, col[0], row[4], width[1], height[1], PreView[1].val, 0.0, 10.0, "Image: Intensity Scale")
+		PreView[2] = Number("",      Im_Evt, col[3], row[4], width[1], height[1], PreView[2].val,-10.0, 10.0, "Image: Offset")
+		PushButton(   "Draw Image",  Im_Evt, col[0], row[5], width[4], height[1] , "Image: Update image ( KEY: V )")
+		draw_Text( ( col[5], row[1] ), 'Create yourself a new image', black, 0 )
+		draw_Text( ( col[5], row[2] ), 'in UV/Image Editor Window,', black, 0 )
+		draw_Text( ( col[5], row[3] ), 'give it a name,', black, 0 )
+		draw_Text( ( col[5], row[4] ), 'and save it manualy.', black, 0 )
+
+####--------------------------------------------------------------------------
+###--------------------------------------------------------------------------
+## Draw G.U.I. -------------------------------------------------------------
+#--------------------------------------------------------------------------
+def drawgui():
+	global guitabs, ledcolor, FullScreen, AutoUpd, RandMod, RSeed, filemessage
+	global Effect_Ctrl, Filter_Mode, Falloff, PreView, rand_H, rand_S, rand_L, rand_I
+
+	glClearColor(background[0],background[1],background[2],background[3])
+	glClear(GL_COLOR_BUFFER_BIT)
+	scissorbox=Buffer(GL_FLOAT,4)
+	glGetFloatv(GL_SCISSOR_BOX,scissorbox)
+	scissbleft=int(scissorbox[0])
+	scissbbase=int(scissorbox[1])
+	scissbwidth=int(scissorbox[2])
+	scissbheight=int(scissorbox[3])
+	xstart = 5
+	ystart = 5
+	xgap = 5
+	ygap = 5
+	if FullScreen.val==1:
+		guiwidth  = scissbwidth-10
+		guiheight = scissbheight-25
+		if guiwidth < size_x/2:
+			guiwidth = size_x/2
+		if guiheight < size_y/2:
+			guiheight = size_y/2
+	else:
+		guiwidth = size_x
+		guiheight = size_y
+	col,row = [],[]
+	xpart = ( ( guiwidth-xstart ) / columns )
+	ypart = ( ( guiheight-ystart ) / rows )
+	width = []
+	for c in xrange( columns ):
+		col.append( xgap + xpart * c + xstart )
+		width.append( xpart*(c+1)-xgap )
+	height = [ (ypart-ygap)/2 , ypart-ygap, (ypart*3-ygap)/2, ypart*2-ygap, (ypart*5-ygap)/2  ]
+	for r in xrange( rows ):
+		row.append( ygap + ypart * r + ystart )
+	row.reverse()
+
+	###-------------------------
+	## Draw G.U.I.:
+	draw_BackPanel( 'Another Noise Tool 1.05', xstart, ystart, guiwidth, guiheight + ygap, lightgrey )
+
+	FullScreen = Toggle("", Scrn_Evt, guiwidth-32, guiheight+ygap+3, 15, 15, FullScreen.val ,"FullScreen" )
+	PushButton( "X",         End_Evt, guiwidth-16, guiheight+ygap+3, 15, 15, "Exit" )
+	draw_Text(( guiwidth-(guiwidth/2)-width[0], guiheight+ygap+5 ), filemessage, white, 0 )
+
+	# gui tabs
+	guitabs[0] = Toggle("Main",    gt0_Evt, col[0], row[0], width[1], height[1], guitabs[0].val ,"Main / Mesh settings" )
+	guitabs[1] = Toggle("Noise",   gt1_Evt, col[2], row[0], width[1], height[1], guitabs[1].val ,"Noise settings" )
+	guitabs[2] = Toggle("Effect",  gt2_Evt, col[4], row[0], width[1], height[1], guitabs[2].val ,"Add Effect" )
+	guitabs[3] = Toggle("Height",  gt3_Evt, col[6], row[0], width[1], height[1], guitabs[3].val ,"Height Filter" )
+	guitabs[4] = Toggle("Options", gt4_Evt, col[8], row[0], width[1], height[1], guitabs[4].val ,"Options" )
+
+	if   guitabs[0].val !=0: MeshButtons(   col, row, width, height )
+	elif guitabs[1].val !=0: NoiseButtons(  col, row, width, height )
+	elif guitabs[2].val !=0: EffectButtons( col, row, width, height )
+	elif guitabs[3].val !=0: FilterButtons( col, row, width, height )
+	elif guitabs[4].val !=0: OptionButtons( col, row, width, height )
+	else: # some info
+		draw_Panel(  col[0], row[0]-5, col[9]+width[0], row[10]-10, black )
+		draw_Text( ( col[0]+5, row[1] ), 'Another Noise Tool v.1.05',                     ledcolors[0], 2 )
+		draw_Text( ( col[0]+5, row[2] ), 'by: Jimmy Hazevoet, 01/2005-03/2007',           ledcolors[1], 2 )
+		draw_Text( ( col[0]+5, row[3] ), 'v.1.05: build/tested in: Blender 2.43 (Wndws)', ledcolors[2], 1 )
+		draw_Text( ( col[0]+5, row[4] ), 'HotKeys: ----------------------------',         ledcolors[3], 2 )
+		draw_Text( ( col[0]+5, row[5] ), 'Space = Update mesh',                           ledcolors[4], 2 )
+		draw_Text( ( col[0]+5, row[6] ), 'V = Update Image',                              ledcolors[5], 2 )
+		draw_Text( ( col[0]+5, row[7] ), 'R = Randomise',                                 ledcolors[6], 2 )
+		draw_Text( ( col[0]+5, row[8] ), 'L = Load from file',                            ledcolors[7], 2 )
+		draw_Text( ( col[0]+5, row[9] ), 'S = Save to file',                              ledcolors[8], 2 )
+		draw_Text( ( col[0]+5, row[10] ),'Q = Quit',                                      ledcolors[9], 2 )
+
+	# auto/generate/randomise buttons
+	rand_on_off = 0
+	if rand_H.val !=0:   rand_on_off = 1
+	elif rand_I.val !=0: rand_on_off = 1
+	elif rand_S.val !=0: rand_on_off = 1
+	elif rand_L.val !=0: rand_on_off = 1
+	else:                rand_on_off = 0
+	if rand_on_off != 0:
+		if RandMod.val in [1,2]:
+			PushButton(     "Randomise", Rndm_Evt, col[2], row[12], width[2], height[2] , "Randomise Noise ( KEY: R )")
+		else: RSeed	= Number("Seed: ", Rndm_Evt, col[2], row[12], width[2], height[2], RSeed.val,  0, 255 , "Random Seed: If seed = 0, the current time will be used as seed." )
+		AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" )
+		PushButton("Update", Upd_Evt, col[5], row[12], width[4], height[2] , "Generate / Update. ( KEY: SPACE )")
+	else:
+		AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" )
+		PushButton("Update", Upd_Evt, col[2], row[12], width[7], height[2] , "Generate / Update. ( KEY: SPACE )")
+		####---------------------------------------------------------------------------
+
+###---------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+# Key Events:
+
+def events(evt, val):
+	global PreView, txtFile, AutoUpd, PreView
+
+	## hotkey: Q = Quit
+	if (evt == QKEY and not val):
+		name = "Quit ?%t|No %x0|Yes %x1"
+		result = Blender.Draw.PupMenu(name)
+		if result==1:
+			Exit()
+
+	## hotkey: Space = Generate/Update terrain
+	if (evt == SPACEKEY and not val):
+		do_it()
+
+	## hotkey: R = Randomise noise
+	if (evt in [ RKEY ] and not val):
+		if AutoUpd.val != 0:
+			do_it_random()
+		else:
+			randomiseNoise()
+			Draw()
+
+	## hotkey: V = Update image
+	if PreView[0].val != 0:
+		if (evt in [ VKEY, RKEY ] and not val):
+			do_it_preview()
+
+	## hotkey: L = Load from file
+	if (evt == LKEY and not val):
+		loadmenu = "Load file ?%t|" + txtFile.val
+		loadresult = Blender.Draw.PupMenu(loadmenu)
+		if loadresult==1:
+			LoadPreset(txtFile.val)
+			if AutoUpd.val != 0:
+				do_it()
+			else: Draw()
+
+	## hotkey: S = Save to file
+	if (evt == SKEY and not val):
+		savemenu = "Save file ?%t|" + txtFile.val
+		saveresult = Blender.Draw.PupMenu(savemenu)
+		if saveresult==1:
+			SavePreset(txtFile.val)
+			Draw()
+
+###---------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+# Button events:
+
+def bevents(evt):
+	global txtFile, effect_image, PreView, fileinfo, filemessage
+	global Filter_Mode, Ipo_Filter_Ctrl, iponame, thiscurve, selectedcurve
+	global antfilename, terrainname
+	global actob, actme
+
+	# quit/reset event
+	if (evt == End_Evt ):
+		name = "OK ?%t|Reset %x1|Quit %x2"
+		result = Blender.Draw.PupMenu(name)
+		if result==1:
+			Set_ReSet_Values()
+			Draw()
+		elif result==2:
+			Exit()
+
+	## file info string  event
+	if (evt == UseMe_Evt ):
+		result = Blender.Draw.PupStrInput("Info:  ", fileinfo, 96)
+		if result:
+			fileinfo = result
+			Draw()
+		else: return
+
+	## none event
+	if (evt in [No_Evt, Scrn_Evt] ):
+		Draw()
+
+	## image event
+	if (evt == Im_Evt ):
+		do_it_preview()
+
+	## generate/update event
+	if (evt == Upd_Evt ):
+		if PreView[0].val != 0:
+			do_it_preview()
+		do_it()
+
+	## mesh button event
+	if (evt == Msh_Evt):
+		if AutoUpd.val != 0:
+			do_it()
+		else: Draw()
+
+	## button event
+	if (evt == Btn_Evt ):
+		if AutoUpd.val != 0:
+			if PreView[0].val != 0:
+				do_it_preview()
+			do_it()
+		else: Draw()
+
+	## randomise event
+	if (evt == Rndm_Evt ):
+		if AutoUpd.val != 0:
+			do_it_random()
+		else:
+			randomiseNoise()
+			if PreView[0].val != 0:
+				do_it_preview()
+			Draw()
+
+	###---------------------------------------------------------
+	## Effect Image Load/Select:
+	if (evt == Load_Evt ):
+		Blender.Window.FileSelector ( load_image, 'LOAD IMAGE')
+	if (evt == Sel_Evt ):
+		try: effect_image = Image_Menu()
+		except: pass
+		if AutoUpd.val != 0:
+			do_it()
+		else: Draw()
+
+	###---------------------------------------------------------
+	## Make New IPOCurve to use as Filter:
+	if (evt == New_Ipo_Evt ):
+		objname = Create("ANT_Ipo_Empty")
+		iponame = Create("ANT_IPO")
+		block = []
+		block.append("Enter new names")
+		block.append("and hit OK button")
+		block.append(("OB: ", objname, 0, 30, "New Ipo Object Name. (Object type = 'Empty')"))
+		block.append(("IP: ", iponame, 0, 30, "New Ipo DataBlock Name"))
+		block.append("Open IpoCurveEditor")
+		block.append("select Ipo DataBlock" )
+		block.append("'Pin' the view" )
+		block.append("and edit the curves." )
+		retval = PupBlock("Make A.N.T. IpoCurve Object", block)
+		if retval !=0:
+			ANTAutoIpo(  objname.val, iponame.val )
+			Ipo_Filter_Ctrl[0].val = iponame.val
+
+	###---------------------------------------------------------
+	## get IPOCurve to use as Filter:
+	if (evt in [Ipo_Evt, New_Ipo_Evt] ):
+		if Filter_Mode.val == 2:
+			if AutoUpd.val != 0:				
+				try:
+					ipoblockname  = Ipo.Get( Ipo_Filter_Ctrl[0].val )
+					thiscurve     = ipoblockname.getCurves()
+					selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ]
+					if PreView[0].val != 0:
+						do_it_preview()
+					#if AutoUpd.val != 0:
+					do_it()
+				except: pass
+			else:
+					try:
+						ipoblockname  = Ipo.Get( Ipo_Filter_Ctrl[0].val )
+						thiscurve     = ipoblockname.getCurves()
+						selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ]
+						if PreView[0].val != 0:
+							do_it_preview()
+						else:
+							Draw()
+					except: pass
+
+	###---------------------------------------------------------
+	## gui tabs
+	if (evt == gt0_Evt ):
+		if guitabs[0].val == 1:
+			guitabs[1].val = ( 0 )
+			guitabs[2].val = ( 0 )
+			guitabs[3].val = ( 0 )
+			guitabs[4].val = ( 0 )
+		Draw()
+	if (evt == gt1_Evt ):
+		if guitabs[1].val == 1:
+			guitabs[0].val = ( 0 )
+			guitabs[2].val = ( 0 )
+			guitabs[3].val = ( 0 )
+			guitabs[4].val = ( 0 )
+		Draw()
+	if (evt == gt2_Evt ):
+		if guitabs[2].val == 1:
+			guitabs[0].val = ( 0 )
+			guitabs[1].val = ( 0 )
+			guitabs[3].val = ( 0 )
+			guitabs[4].val = ( 0 )
+		Draw()
+	if (evt == gt3_Evt ):
+		if guitabs[3].val == 1:
+			guitabs[0].val = ( 0 )
+			guitabs[1].val = ( 0 )
+			guitabs[2].val = ( 0 )
+			guitabs[4].val = ( 0 )
+		Draw()
+	if (evt == gt4_Evt ):
+		if guitabs[4].val == 1:
+			guitabs[0].val = ( 0 )
+			guitabs[1].val = ( 0 )
+			guitabs[2].val = ( 0 )
+			guitabs[3].val = ( 0 )
+		Draw()
+
+	###---------------------------------------------------------
+	## load and save all settings:
+	if (evt == SelFile_Evt ):
+		Blender.Window.FileSelector ( callback, "Select .ant File")
+	if (evt == LoadFile_Evt ):
+		loadmenu = "Load file ?%t|" + txtFile.val
+		loadresult = Blender.Draw.PupMenu(loadmenu)
+		if loadresult==1:
+			LoadPreset(txtFile.val)
+			Draw()
+			if AutoUpd.val != 0:
+				do_it()
+	if (evt == SaveFile_Evt ):
+		savemenu = "Save file ?%t|" + txtFile.val
+		saveresult = Blender.Draw.PupMenu(savemenu)
+		if saveresult==1:
+			SavePreset(txtFile.val)
+			Draw()
+
+	###---------------------------------------------------------
+	# New Grid
+	###-------------------------
+	if (evt == New_Evt):
+		scn = Blender.Scene.GetCurrent()
+		gridname = Create("Terrain")
+		gridres = Create(256)
+		curspos = Create(0)
+		block = []
+		block.append(("OB: ", gridname, 0, 30, "New Object Name."))
+		block.append(("Resol: ", gridres, 4, 1024, "New grid resolution"))
+		block.append(("At Cursor", curspos, "New grid at cursor position"))			
+		retval = PupBlock("New Grid Mesh", block)
+		if retval !=0:
+			MakeGridMesh( gridres.val, gridname.val, curspos.val, scn )
+			obj = scn.objects.active
+			if obj.type == 'Mesh':
+				actob=[]
+				actme=[]		
+				actob.append( obj )
+				actme.append( actob[0].getData(mesh=1) )
+				Blender.Redraw()
+
+	###---------------------------------------------------------
+	# Assign Grid
+	###-------------------------
+	if (evt == App_Evt):
+		scn = Blender.Scene.GetCurrent()
+		obj = scn.objects.active
+		if obj:
+			if obj.type == 'Mesh':
+				actob=[]
+				actme=[]		
+				actob.append( obj )
+				actme.append( actob[0].getData(mesh=1) )
+				Draw()
+
+	###-------------------------
+	if (evt not in [LoadFile_Evt,SaveFile_Evt] ):
+		filemessage = ''
+		#Draw()
+
+	### end events. -------------------------
+
+####-------------------------------------------------------------------------------------
+###-------------------------------------------------------------------------------------
+##-------------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------------
+
+##----------------------------------
+# A.N.T. Auto Ipo generator:
+def ANTAutoIpo( objname, iponame ):
+	scn=Scene.GetCurrent()
+	# Deselect all objects:
+	scn.objects.selected=[]
+	# Create new 'ANT_IPO_OBJECT':
+	obj = scn.objects.new('Empty', objname )
+	obj.setDrawMode(8)
+	obj.select(1)
+	obj.layers = Window.ViewLayers()
+	# Set current frame at 1:
+	frame = Get('curframe')
+	if frame !=1:
+		Set('curframe',1)
+		frame = Get('curframe')
+	# Insert IpoKeys:
+	obj.setLocation(0.0, 0.0, 0.0)
+	obj.insertIpoKey(0)
+	Set('curframe',101)
+	obj.setLocation(100.0, 100.0, 100.0)
+	obj.insertIpoKey(0)
+	Set('curframe',1)
+	# Set Ipo name:
+	ip = obj.getIpo()
+	ip.name = iponame
+	#-------------------------
+	print "New ANT_IPO: " + objname +" (Object) and " + iponame + " (Ipo DataBlock) Created!"
+	#-------------------------
+
+##-------------------------------------------------------------------------------------
+
+##-------------------------
+# Generate random numbers:
+def randnum(low,high):
+	global RandMod, RSeed
+	if RandMod.val == 0:
+		# Noise.random setRandomSeed
+		s = Noise.setRandomSeed( RSeed.val )
+		num = Noise.random()
+		num = num*(high-low)
+		num = num+low
+	elif RandMod.val == 1:
+		# Mathutils.Rand
+		num = Mathutils.Rand(low,high)
+	else:
+		# BPyMathutils  Mersenne Twister genrand
+		num = genrand()
+		num = num*(high-low)
+		num = num+low
+	return num
+
+##-------------------------
+# Randomise noise: height, size and location:
+def randomiseNoise():
+	global rand_I, rand_H, rand_S, rand_L, NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy
+
+	if rand_I.val !=0:
+		iScale[0] = Create( randnum( 0.2  , 3.0 ) )
+		Offset[0] = Create( randnum(-1.0 , 1.0 ) )
+	if rand_H.val !=0:
+		iScale[2] = Create( randnum( 0.10  , 1.0 ) )
+		Offset[2] = Create( randnum(-0.25 , 0.25 ) )
+	if rand_S.val !=0:
+		NSize[0]  = Create( randnum( 0.25 , 2.5 ) )
+		#Sx[0]     = Create( randnum( 0.5 , 1.5 ) )
+		#Sy[0]     = Create( randnum( 0.5 , 1.5 ) )
+	if rand_L.val !=0:
+		Lx[0]     = Create( randnum( -10000 , 10000 ) )
+		Ly[0]     = Create( randnum( -10000 , 10000 ) )
+
+##-------------------------------------------------------------------------------------
+
+###--------------------------
+# Load Image:
+def load_image( ImageFileName ):
+	Image.Load( ImageFileName )
+
+###--------------------------
+# Select Image Menu:
+def Image_Menu():
+	try:
+		names=[]
+		imagelist = Image.Get()
+		imagelist.reverse()
+		for numbers, obnames in enumerate( imagelist ):
+			n = obnames.getName()
+			names.append( n )
+		imlistText = string.join( [ '|' + str(names[key]) + '%x' + str(key)  for key in xrange(numbers+1) ], '' )
+		image_menu = Blender.Draw.PupMenu( "Images: %t" + imlistText )
+		if image_menu == -1:
+			return ''
+		return imagelist[ image_menu ].getName()
+	except:
+		return 'No image found!'
+
+###--------------------------
+# Get Image Pixels:
+def Image_Func( x,y ):
+	try:
+		pic  = Image.Get( effect_image )
+	except:
+		return 0.0
+	w, h = pic.getSize()
+	x, y = x,-y
+	x = int(w * ((x + 1.0) % 2.0) / 2.0)
+	y = int((h-1) - h * ((y + 1.0) % 2.0) / 2.0)	
+	c = pic.getPixelF( x,y )
+	return ( c[0] + c[1] + c[2] ) / 3.0
+
+##-------------------------------------------------------------------------------------
+
+# Transpose noise coords:
+def Trans((x,y,z), size, loc  ):
+	x = ( x / size[1] / size[0] + loc[0] )
+	y = ( y / size[2] / size[0] + loc[1] )
+	z = 0.0 #( z / size[3] / size[0] + loc[2] )
+	return x,y,z
+
+# Transpose effect coords:
+def Trans_Effect((x,y,z), size, loc  ):
+	x = ( x * size[1] * size[0] + loc[0] )
+	y = ( y * size[2] * size[0] + loc[1] )
+	z = 0.0
+	return x,y,z
+
+# Height scale:
+def HeightScale( input, iscale, offset, invert ):
+	if invert !=0:
+		return (1.0-input) * iscale + offset
+	else:
+		return input * iscale + offset
+
+# dist.
+def Dist(x,y):
+	return sqrt( (x*x)+(y*y) )
+
+##-----------------------------------
+# bias types:
+def no_bias(a):
+	return a
+def sin_bias(a):
+	return 0.5 + 0.5 * sin(a)
+def cos_bias(a):
+	return 0.5 + 0.5 * cos(a)
+def tri_bias(a):
+	b = 2 * phi
+	a = 1 - 2 * abs(floor((a * (1/b))+0.5) - (a*(1/b)))
+	return a
+def saw_bias(a):
+	b = 2 * phi
+	n = int(a/b)
+	a -= n * b
+	if a < 0: a += b
+	return a / b
+# sharpen types:
+def soft(a):
+	return a
+def sharp(a):
+	return a**0.5
+def sharper(a):
+	return sharp(sharp(a))
+Bias_Types  = [ sin_bias, cos_bias, tri_bias, saw_bias, no_bias ]
+Sharp_Types = [ soft, sharp, sharper ]
+
+##-----------------------------------
+# clamp height
+def clamp( height, min, max ):
+	if ( height < min ): height = min
+	if ( height > max ): height = max
+	return height
+
+##-----------------------------------
+# Mix modes
+def maximum( a, b ):
+	if ( a > b ): b = a
+	return b
+def minimum( a, b ):
+	if ( a < b ): b = a
+	return b
+
+def Mix_Modes( (i,j),(x,y,z) , a,b, mixfactor, mode ):
+	a = a * ( 1.0 - mixfactor )
+	b = b * ( 1.0 + mixfactor )
+	if   mode == 0:  return  ( b )                     #0  effect only
+	elif mode == 1:  return  ( a*(1.0-0.5) + (b*0.5) ) #1  mix
+	elif mode == 2:  return  ( a + b )                 #2  add
+	elif mode == 3:  return  ( a - b )                 #3  sub.
+	elif mode == 4:  return  ( a * b )                 #4  mult.
+	elif mode == 5:  return  (abs( a - b ))            #5  abs diff.
+	elif mode == 6:  return  1.0-((1.0-a)*(1.0-b)/1.0) #6  screen
+	elif mode == 7:  return  ( a + b ) % 1.0           #7  addmodulo
+	elif mode == 8:  return  min( a, b )           #8  min.
+	elif mode == 9:  return  max( a, b )           #9  max.
+	elif mode == 10:                                   #10 warp: effect
+		noise =  mixfactor * Noise_Function(x,y,z)
+		return    Effects( (i,j),(x+noise,y+noise,z) )
+	elif mode == 11:                                   #11 warp: noise
+		effect = mixfactor * Effects( (i,j),(x,y,z) )
+		return   Noise_Function( x+effect, y+effect, z )
+	else: return a
+
+###----------------------------------------------------------------------
+# Effect functions:
+
+# Effect_Basis_Function:
+def Effect_Basis_Function((x,y), type, bias ):
+
+	iscale = 1.0
+	offset = 0.0
+	## gradient:
+	if type == 0:
+		effect = offset + iscale * ( Bias_Types[ bias ]( x + y ) )
+	## waves / bumps:
+	if type == 1:
+		effect = offset + iscale * 0.5 * ( Bias_Types[ bias ]( x*phi ) + Bias_Types[ bias ]( y*phi ) )
+	## zigzag:
+	if type == 2:
+		effect = offset + iscale * Bias_Types[ bias ]( offset + iscale * sin( x*phi + sin( y*phi ) ) )
+	## wavy:	
+	if type == 3:
+		effect = offset + iscale * ( Bias_Types[ bias ]( cos( x ) + sin( y ) + cos( x*2+y*2 ) - sin( -x*4+y*4) ) )
+	## sine bump:	
+	if type == 4:
+		effect =   offset + iscale * 1-Bias_Types[ bias ](( sin( x*phi ) + sin( y*phi ) ))
+	## dots:
+	if type == 5:
+		effect = offset + iscale * ( Bias_Types[ bias ](x*phi*2) * Bias_Types[ bias ](y*phi*2) )-0.5
+	## rings / dome:
+	if type == 6:
+		effect = offset + iscale * ( Bias_Types[ bias ]( 1.0-(x*x+y*y) ) )
+	## spiral:
+	if type == 7:
+		effect = offset + iscale * Bias_Types[ bias ](( x*sin( x*x+y*y ) + y*cos( x*x+y*y ) ))*0.5
+	## square / piramide:
+	if type == 8:
+		effect = offset + iscale * Bias_Types[ bias ](1.0-sqrt( (x*x)**10 + (y*y)**10 )**0.1)
+	## blocks:	
+	if type == 9:
+		effect = ( 0.5-max( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) ))
+		if effect > 0.0: effect = 1.0
+		effect = offset + iscale * effect
+	## grid:	
+	if type == 10:
+		effect = ( 0.025-min( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) ))
+		if effect > 0.0: effect = 1.0
+		effect = offset + iscale * effect
+	## tech:
+	if type == 11:
+		a = ( max( Bias_Types[ bias ](x*pi) , Bias_Types[ bias ](y*pi) ))
+		b = ( max( Bias_Types[ bias ](x*pi*2+2) , Bias_Types[ bias ](y*pi*2+2) ))
+		effect = ( min( Bias_Types[ bias ](a) , Bias_Types[ bias ](b) ))*3.0-2.0
+		if effect > 0.5: effect = 1.0
+		effect = offset + iscale * effect
+
+	## crackle:	
+	if type == 12:
+		t = turbulence(( x, y, 0 ), 6, 0, 0 ) * 0.25
+		effect = vlNoise(( x, y, t ), 0.25, 0, 8 )
+		if effect > 0.5: effect = 0.5
+		effect = offset + iscale * ( effect )
+	## sparse cracks noise:
+	if type == 13:
+		effect = 2.5 * abs( noise((x*0.5,y*0.5, 0 ), 1 ) )-0.1
+		if effect > 0.25: effect = 0.25
+		effect = offset + iscale * ( effect * 2.5 )
+	## shattered rock noise:
+	if type == 14:
+		effect = 0.5 + noise((x,y,0), 7 )
+		if effect > 0.75: effect = 0.75
+		effect = offset + iscale * effect
+	## lunar noise:
+	if type == 15:
+		effect = 0.25 + 1.5 * voronoi(( x+2, y+2, 0 ), 1 )[0][0]
+		if effect > 0.5: effect = 0.5
+		effect = offset + iscale * ( effect * 2.0 )
+	## cosine noise:
+	if type == 16:
+		effect = cos( 5*noise(( x, y, 0 ), 0 ) )
+		effect = offset + iscale * ( effect*0.5 )
+	## spikey noise:
+	if type == 17:
+		n = 0.5 + 0.5 * turbulence(( x*5, y*5, 0 ), 8, 0, 0 )
+		effect = ( ( n*n )**5 )
+		effect = offset + iscale * effect
+	## stone noise:
+	if type == 18:
+		effect = offset + iscale *( noise((x*2,y*2, 0 ), 0 ) * 1.5 - 0.75)
+	## Flat Turb:
+	if type == 19:
+		t = turbulence(( x, y, 0 ), 6, 0, 0 )
+		effect = t*2.0
+		if effect > 0.25: effect = 0.25
+		effect = offset + iscale * ( effect )
+	## Flat Voroni:
+	if type == 20:
+		t = 1-noise(( x, y, 0 ), 3 )
+		effect = t*2-1.75
+		if effect > 0.25: effect = 0.25
+		effect = offset + iscale * ( effect )
+
+	if effect < 0.0: effect = 0.0
+	return effect
+
+# fractalize Effect_Basis_Function: ------------------------------ 
+def Effect_Function((x,y), type,bias, turb, depth,frequency,amplitude ):
+
+	## effect distortion:
+	if turb != 0.0:
+		t =  vTurbulence(( x, y, 0 ), 6, 0, 0 )
+		x = x + ( 0.5 + 0.5 * t[0] ) * turb
+		y = y + ( 0.5 + 0.5 * t[1] ) * turb
+
+	result = Effect_Basis_Function((x,y), type, bias )
+	## fractalize effect:
+	if depth != 0:
+		i=0
+		while i < depth:
+			i+=1
+			x *= frequency
+			y *= frequency
+			amplitude = amplitude / i
+			result += Effect_Basis_Function( (x,y), type, bias ) * amplitude
+	return result
+
+###--------------------------------------------------
+# Custom effect:
+def CustomEffect( x,y,z,h ):
+	global CustomFX
+	try:
+		a = eval( CustomFX[0].val )
+		b = eval( CustomFX[1].val )
+		result = eval( CustomFX[2].val )
+		return result
+	except:
+		return 0.0
+
+###--------------------------------------------------
+## Effect Selector:
+
+def Effects( (i,j),(x,y,z), h=0.0 ):
+	global Effect_Type, Effect_Ctrl, iScale, Offset, Invert
+	global NSize, Lx, Ly, Lz, Sx, Sy, Sz, marbleTwo, turbTwo, vlnoiTwo, Basis, musgrTwo
+
+	x,y,z = Trans_Effect((x,y,z),( NSize[1].val, Sx[1].val, Sy[1].val, 0 ),( Lx[1].val, Ly[1].val, 0 )  )
+	basis = Basis[1].val
+	if basis == 9: basis = 14
+	vbasis = vlnoiTwo[1].val
+	if vbasis == 9: vbasis = 14
+	if Effect_Ctrl[0].val == 1:
+		try: effect  = Image_Func( x,y )
+		except: effect =	0.0
+	elif Effect_Ctrl[0].val == 2: effect = 0.5+0.5*turbulence(( x,y,z ),turbTwo[0].val, turbTwo[1].val, basis, turbTwo[2].val, turbTwo[3].val )
+	elif Effect_Ctrl[0].val == 3: effect = 0.5+0.5*vlNoise(( x,y,z ),vlnoiTwo[0].val, vbasis, basis )
+	elif Effect_Ctrl[0].val == 4: effect = 0.5*marbleNoise((x,y,z), marbleTwo[0].val, basis, marbleTwo[2].val, marbleTwo[3].val, marbleTwo[4].val, marbleTwo[5].val )
+	elif Effect_Ctrl[0].val == 5:	effect = 0.5*multiFractal((   x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )
+	elif Effect_Ctrl[0].val == 6:	effect = 0.5*ridgedMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis )
+	elif Effect_Ctrl[0].val == 7:	effect = 0.5*hybridMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis )
+	elif Effect_Ctrl[0].val == 8:	effect = 0.5*heteroTerrain((  x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, basis )*0.5
+	elif Effect_Ctrl[0].val == 9:	effect = 0.5*fBm((            x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )+0.5
+	elif Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31:
+		effect = Effect_Function((x,y), Effect_Ctrl[0].val-10,  Effect_Ctrl[3].val,  Effect_Ctrl[4].val,  Effect_Ctrl[5].val,  Effect_Ctrl[6].val, Effect_Ctrl[7].val )
+	elif Effect_Ctrl[0].val == 31: effect = Effect_Ctrl[8].val * random()
+	elif Effect_Ctrl[0].val == 32: effect = Effect_Ctrl[8].val
+	elif Effect_Ctrl[0].val == 33: effect = CustomEffect( x,y,z, h )
+	effect = HeightScale( effect, iScale[1].val , Offset[1].val, Invert[1].val )
+	return  effect*2.0
+
+###----------------------------------------------------------------------
+# Noise:
+##-----------------------------------
+
+## voronoi_turbulence:
+def voroTurbMode((x,y,z), voro, mode ):
+	if mode == 0: # soft
+		return voronoi(( x,y,z ),voro[0], voro[1] )[0][0]
+	if mode == 1: # hard
+		return ( abs( 0.5-voronoi(( x,y,z ),voro[0], voro[1] )[0][0] ) )+0.5
+def voronoi_turbulence((x,y,z), voro, tur ):
+	result = voroTurbMode((x,y,z), voro, tur[1] )
+	depth  = tur[0]
+	amp    = tur[2]
+	freq   = tur[3]
+	i=0
+	for i in xrange( depth ):
+		i+=1
+		result += voroTurbMode( ( x*(freq*i), y*(freq*i), z ), voro, tur[1] )* ( amp*0.5/i )
+	return (result*4.0-2.0)
+
+## DistortedNoise / vlNoise_turbulence:
+def vlnTurbMode((x,y,z), vlno, basis, mode ):
+	if mode == 0: # soft
+		return vlNoise(( x,y,z ),vlno[0], vlno[1], basis )
+	if mode == 1: # hard
+		return ( abs( -vlNoise(( x,y,z ),vlno[0], vlno[1], basis ) ) )
+def vlNoise_turbulence((x,y,z), vlno, tur, basis ):
+	result = vlnTurbMode((x,y,z), vlno, basis, tur[1] )
+	depth  = tur[0]
+	amp    = tur[2]
+	freq   = tur[3]
+	i=0
+	for i in xrange( depth ):
+		i+=1
+		result += vlnTurbMode( ( x*(freq*i), y*(freq*i), z ), vlno, basis, tur[1] ) * ( amp*0.5/i )
+	return result*2.0+0.5
+
+## marbleNoise:
+def marbleNoise( (x,y,z), depth, basis, turb, bias, sharpnes, rescale ):
+	m = ( x * rescale + y * rescale + z ) * 5
+	height = m + turb * turbulence( ( x ,y ,z ), depth, 0, basis, 0.5, 2.0 )
+	height = Bias_Types[ bias ]( height )
+	if bias != 4:
+		height = Sharp_Types[ sharpnes ]( height )
+	return height*2.0
+
+## lava_multiFractal:
+def lava_multiFractal( ( x,y,z ),Ha, La, Oc, distort, Basis ):
+	m  = multiFractal( ( x,y,z ), Ha, La, Oc, Basis)
+	d = m * distort
+	m2 = 0.5 * multiFractal( ( x+d,y+d,d*0.5 ), Ha, La, Oc, Basis)
+	return (m * m2)**0.5
+
+## slopey_noise:
+def slopey_noise((x,y,z), H, lacunarity, octaves, distort, basis ):
+	x=x*2
+	y=y*2
+	turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.5
+	map = 0.5 + noise( ( x+turb, y+turb, z ), basis )
+	result = map + turb * distort
+	return result
+
+## duo_multiFractal:
+def double_multiFractal((x,y,z), H, lacunarity, octaves, offset, gain, basis ):
+	n1 = multiFractal( (x*1.5+1,y*1.5+1,z), 1.0, 1.0, 1.0, basis[0] ) * offset
+	n2 = multiFractal( (x-1,y-1,z), H, lacunarity, octaves, basis[1] ) * gain
+	result = ( n1*n1 + n2*n2 )*0.5
+	return result
+
+## distorted_heteroTerrain:
+def distorted_heteroTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ):
+	h1 = ( heteroTerrain((x,y,z), 1.0, 2.0, 1.0, 1.0, basis[0] ) * 0.5 )
+	h2 = ( heteroTerrain(( x, y, h1*distort ), H, lacunarity, octaves, offset, basis[1] ) * 0.25 )
+	result = ( h1*h1 + h2*h2 )
+	return  result
+
+## SlickRock:
+def SlickRock((x,y,z), H, lacunarity, octaves, offset, gain, basis ):
+	n = multiFractal( (x,y,z), 1.0, 2.0, 1.0, basis[0] )
+	r = ridgedMFractal((x,y,n*0.5), H, lacunarity, octaves, offset, gain, basis[1] )*0.5
+	return n+(n*r)
+
+## terra_turbulence:
+def terra_turbulence((x,y,z), depth, hard, basis, amp, freq ):
+	t2 = turbulence( ( x, y, z ), depth,  hard , basis, amp, freq )
+	return (t2*t2*t2)+0.5
+
+## rocky_fBm:
+def rocky_fBm((x,y,z), H, lacunarity, octaves, basis ):
+	turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.25
+	coords = ( x+turb, y+turb, z )
+	map = noise( coords, 7 )
+	result = map + fBm( coords, H, lacunarity, octaves, basis ) + 1.0
+	return result
+
+## Shattered_hTerrain:
+def Shattered_hTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ):
+	d = ( turbulence( ( x, y, z ), 6, 0, 0, 0.5, 2.0 ) * 0.5 + 0.5 )*distort*0.25
+	t0 = ( turbulence( ( x+d, y+d, z ), 0, 0, 7, 0.5, 2.0 ) + 0.5 )
+	t2 = ( heteroTerrain(( x*2, y*2, t0*0.5 ), H, lacunarity, octaves, offset, basis ) )
+	return (( t0*t2 )+t2*0.5)*0.75
+
+## vlhTerrain
+def vlhTerrain((x,y,z), H, lacunarity, octaves, offset, basis, vlbasis, distort ):
+	ht = heteroTerrain(( x, y, z ), H, lacunarity, octaves, offset, basis )*0.5
+	vl = ht * vlNoise((x,y,z), distort, basis, vlbasis )*0.5+0.5
+	return vl * ht
+
+####---------------------------------------.
+### StatsByAlt, double terrain  basis mode:
+def TerrainBasisMode((x,y,z), basis, mode ):
+	if mode == 0: # noise
+		return noise((x,y,z),basis)
+	if mode == 1: # noise ridged
+		return ( 1.0-abs( noise((x,y,z),basis) ) )-0.5
+	if mode == 2: # vlNoise
+		return vlNoise((x,y,z), 1.0, 0, basis )
+	else:         # vlNoise ridged
+		return ( 1.0-abs( vlNoise((x,y,z), 1.0, 0, basis ) ) )-0.5
+
+#### StatsByAlt terrain:
+def StatsByAltTerrain((x,y,z), exp, lacu, octs, offset, amp, basis, mode ):
+	result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+	octs = int( octs )
+	i = 0
+	for i in xrange( 1, octs ):
+		i += 1
+		result += result * amp * 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+		x *= lacu
+		y *= lacu
+		amp /= ( exp * 0.5 ) * i		
+	return result
+
+##### double terrain:
+def doubleTerrain((x,y,z), exp, lacu, octs, offset, threshold, basis, mode ):
+	result = amp = freq = 1.0
+	#octs = int( octs )
+	offset*=0.5
+	i = 1
+	signal = result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+	for i in xrange( 1, octs ):
+		i += 1
+		x = x * lacu
+		y = y * lacu
+		freq *= lacu
+		amp = pow( freq, -exp )
+		amp *= i
+		weight = signal / threshold
+		if weight > 1.0: weight = 1.0
+		if weight < 0.0: weigth = 0.0
+		signal = weight * 0.5 * ( offset + TerrainBasisMode((x,y,z), basis, mode ) )
+		result += amp * signal
+	return result * 2.0
+
+##------------------------------------------------------------
+# Noise Functions:
+def Noise_Function(x,y,z):
+	global Basis, NType, musgr, vlnoi, voron, turbOne, marbleOne, tBasismod
+	global vlBasis, Distort, VFunc, VExp, VDep
+	global iScale, Offset, Invert, NSize, Lx, Ly, Sx, Sy
+
+	x,y,z = Trans((x,y,z),( NSize[0].val, Sx[0].val, Sy[0].val, 0 ),( Lx[0].val, Ly[0].val, 0 )  )
+	basis = Basis[0].val
+	if basis == 9: basis = 14
+	vbasis = vlnoi[1].val
+	if vbasis == 9: vbasis = 14
+	if   NType.val == 0:	z = multiFractal((   x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )
+	elif NType.val == 1:	z = ridgedMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis )
+	elif NType.val == 2:	z = hybridMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis )
+	elif NType.val == 3:	z = heteroTerrain((  x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis )*0.5
+	elif NType.val == 4:	z = fBm((            x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )+0.5
+	elif NType.val == 5:	z = turbulence((     x,y,z ),turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )+0.5
+	elif NType.val == 6:	z = voronoi_turbulence((x,y,z),(voron[0].val,voron[1].val),(turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val) )*0.5+0.5
+	elif NType.val == 7:	z = vlNoise_turbulence((x,y,z),(vlnoi[0].val,vbasis), (turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val), basis )*0.5+0.5
+	elif NType.val == 8:	z = noise((          x,y,z ),basis )+0.5
+	elif NType.val == 9:	z = cellNoise((      x,y,z ))+0.5
+	elif NType.val == 10: z = marbleNoise((         x,y,z), marbleOne[0].val, basis, marbleOne[2].val, marbleOne[3].val, marbleOne[4].val, marbleOne[5].val )
+	elif NType.val == 11: z = lava_multiFractal((  x,y,z ), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )
+	elif NType.val == 12: z = slopey_noise((         x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )+0.5
+	elif NType.val == 13: z = double_multiFractal(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) )
+	elif NType.val == 14: z = distorted_heteroTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, (vbasis,basis) )
+	elif NType.val == 15: z = SlickRock((           x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis)  )
+	elif NType.val == 16: z = terra_turbulence((  x,y,z), turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )
+	elif NType.val == 17: z = rocky_fBm((           x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )
+	elif NType.val == 18: z = StatsByAltTerrain(   (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val*0.5, basis, tBasismod.val )
+	elif NType.val == 19: z = doubleTerrain(       (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[5].val, basis, tBasismod.val )
+	elif NType.val == 20: z = Shattered_hTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, basis )
+	elif NType.val == 21: z = vlhTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis, vbasis, vlnoi[0].val )
+	else:	z = 0.0
+	return HeightScale( z, iScale[0].val , Offset[0].val, Invert[0].val )
+
+###----------------------------------------------------------------------
+##-----------------------------------
+# Filter functions:
+
+##-----------------------------------
+# Filter: Clamp height
+def Clamp_Max( height, max ):
+	if ( height > max ): height = max
+	return height
+def Clamp_Min( height, min ):
+	if ( height < min ): height = min
+	return height
+
+##-----------------------------------
+# Filters: terrace / posterise / peaked / bias:
+def Def_Filter((x,y,z), input, numb, type ):
+	if   type == 0:
+		s = ( sin( input*numb*phi ) * ( 0.1/numb*phi ) )
+		return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+	elif type == 1:
+		s = -abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) )
+		return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+	elif type == 2:
+		s = abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) )
+		return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+	elif type == 3:
+		numb = numb*0.5
+		s = ( int( input*numb ) * 1.0/numb )
+		return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+	elif type == 4:
+		numb = numb*0.5
+		s = ( int( input*numb ) * 1.0/numb )
+		return ( s ) * 2.0
+	elif type == 5:
+		s = ( sin( input*(2*numb)*phi ) * ( 0.1/(2*numb)*phi ) )
+		l = ( input * (1.0-0.5) + s*0.5 ) * 2.0
+		p = ( ( l*numb*0.25 ) * ( l*numb*0.25 ) )**2
+		return ( l * (1.0-0.5) + p*0.5 ) * 2.0
+	elif type == 6:
+		return ( input*numb*0.25 )**4
+	elif type == 7:
+		return 2.0-exp( 1.0-(input*numb/3.0) )
+	elif type == 8:
+		return sin_bias( input*numb )*2.0
+	elif type == 9:
+		return cos_bias( input*numb )*2.0
+	elif type == 10:
+		return tri_bias( input*numb )*2.0
+	elif type == 11:
+		return saw_bias( input*numb )*2.0
+	elif type == 12:
+		return Clamp_Max( input, numb )
+	else:
+		return input
+
+##-----------------------------------
+# Filter: Edge falloff
+def EdgeFalloff( (x,y,z), height, type ):
+	global Falloff, iScale, Offset
+
+	x = x / Falloff[1].val
+	y = y / Falloff[2].val
+
+	if Falloff[3].val != 0:
+		sealevel = (Min.val-Offset[2].val)*2.0/iScale[2].val
+	else:
+		sealevel = 0.0
+
+	falltypes = ( 0, sqrt(x*x+y*y), sqrt((x*x)**2+(y*y)**2), sqrt((x*x)**10+(y*y)**10), sqrt(y*y), sqrt(x*x), abs(x-y), abs(x+y), ((x*x)**10+(y*y)**10)**0.1, ((x*x)+(y*y)) )
+
+	dist = falltypes[ type ]
+	if Falloff[4].val != 0:
+		dist = 1.0 - dist
+	radius = 1.0
+	height = height - sealevel
+	if( dist < radius ):
+		dist = dist / radius
+		dist = ( (dist) * (dist) * ( 3-2*(dist) ) )
+		height = ( height - height * dist ) + sealevel
+	else:
+		height = sealevel
+
+	if Falloff[3].val != 0:
+		height = Clamp_Min( height, sealevel )
+	else:
+		height = Clamp_Min( height, Min.val )
+
+	return height
+
+##-----------------------------------
+# Filter: Custom height filter:
+def CustomFilter( x,y,z, h ):
+	global CustomFilt
+	try:
+		a = eval(CustomFilt[0].val)
+		b = eval(CustomFilt[1].val)
+		result = eval(CustomFilt[2].val)
+		return result
+	except:
+		return 0.0
+
+#####-------------------------------------------------------------------------------------#####
+####-------------------------------------------------------------------------------------####
+### Combine Functions: (get noise, Add effect, filter height and return result)         ###
+##-------------------------------------------------------------------------------------##
+
+def Combine_Functions( (i,j),(x,y,z) ):
+	global Effect_Ctrl, Blend_Effect, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+	global iScale, Offset, Invert, Min, Max, Falloff
+
+	# get noise height:
+	height = Noise_Function(x,y,0.0)
+
+	### Filter On
+	if Filter_Mode.val !=0:
+		### 0= Default Filter Order: Noise>Effect>Filter ---------------------
+		if Filter_Order.val ==0:
+			# mix noise with effect:
+			if Effect_Ctrl[0].val !=0:
+				height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+			# edge fallof:
+			if Falloff[0].val !=0:
+				height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+		#else: pass
+
+		if Filter_Mode.val !=0:
+			# height Def_Filter (Terrace/peaked/bias):
+			if Filter_Mode.val ==1:
+				height = Def_Filter((x,y,z), height, Def_Filter_Ctrl[ 1 ].val, Def_Filter_Ctrl[ 0 ].val )
+
+			## 'IPOCurve' height filter:
+			elif Filter_Mode.val ==2:
+				try:
+					height = selectedcurve.evaluate( 1 + ( height*Ipo_Filter_Ctrl[2].val/2 ) )*2.0/Ipo_Filter_Ctrl[3].val
+				except:
+					height = height
+
+			## Custom filter:
+			elif Filter_Mode.val ==3:
+					height = CustomFilter( x,y,z, height )
+
+		### 1= Changed Filter Order: Noise>Filter>Effect ---------------------
+		if Filter_Order.val !=0:
+			# mix noise with effect:
+			if Effect_Ctrl[0].val !=0:
+				height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+			# edge fallof:
+			if Falloff[0].val !=0:
+				height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+		#else: pass
+
+	### Filter Off ---------------------
+	else:
+		# mix noise with effect:
+		if Effect_Ctrl[0].val !=0:
+			height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+		# edge fallof:
+		if Falloff[0].val !=0:
+			height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+
+	# height scale:	
+	height = HeightScale( height, 0.5*iScale[2].val , Offset[2].val, Invert[2].val )
+
+	# clamp height min. max.:
+	if Falloff[0].val !=1:
+		height = Clamp_Min( height, Min.val )
+	height = Clamp_Max( height, Max.val )
+
+	# return height:
+	return height
+
+
+#------------------------------------------------------------
+##------------------------------------------------------------
+###  Render Noise to a Image('NAME') (you must create one first)
+##------------------------------------------------------------
+#------------------------------------------------------------
+
+def HeightFieldImage():
+	global PreView, previewname
+
+	iname = previewname.val
+	try: 
+		pic = Image.Get( iname )
+	except:
+		#print iname, ' No Image with this name'
+		PupMenu( 'No Image with this name' )
+		return
+	res = pic.getMaxXY()
+	for i in xrange( res[0] ):
+		x = i - (res[0]) / 2.0
+		x = (x*2.0) / (res[0])
+		for j in xrange( res[1] ):
+			y = j - (res[1]) / 2.0
+			y = (y*2.0) / (res[1])
+			height = PreView[2].val + PreView[1].val * Combine_Functions( (i,j),(x,y,0) )
+			if height > 1.0: height = 1.0
+			if height < 0.0: height = 0.0
+			pic.setPixelF( i, j, ( height,height,height, 1.0 ) )
+
+
+#------------------------------------------------------------
+##------------------------------------------------------------
+###  Mesh
+##------------------------------------------------------------
+#------------------------------------------------------------
+
+#------------------------------------------------------------
+## Mesh: make new grid
+###------------------------------------------------------------
+
+def MakeGridMesh( RESOL=32, NAME='GridMesh', CURSORPOS=0, SCENE=None ):
+	# scene, object, mesh ---------------------------------------
+	if not SCENE:
+		SCENE = Blender.Scene.GetCurrent()
+	SCENE.objects.selected=[]
+	newme = Blender.Mesh.New( NAME )
+	newob = SCENE.objects.new( newme, NAME )
+	n = RESOL
+	# verts ---------------------------------------
+	v=[]
+	for i in xrange( n ):
+		x = i-(n-1)/2.0
+		x = x*2.0/(n-1)
+		for j in xrange( n ):
+			y = j-(n-1)/2.0
+			y = y*2.0/(n-1)
+			v.append( [ x, y, 0 ] )
+	newme.verts.extend(v)
+	# faces ---------------------------------------
+	f=[]
+	for i in xrange( n-1 ):
+		for j in xrange( n-1 ):
+			f.append( [	i*n+j,\
+						(i+1)*n+j,\
+						(i+1)*n+j+1,\
+						i*n+j+1 ] )
+	
+	newme.faces.extend(f, smooth=True)
+	#---------------------------------------
+	newme.calcNormals()
+	#---------------------------------------
+	if CURSORPOS !=0:
+		newob.loc = Window.GetCursorPos()
+	newob.select(1)
+
+#------------------------------------------------------------
+## Mesh: Grid vert displace / update terrain
+###------------------------------------------------------------
+
+def displace( OB, ME, WORLD=0  ):
+	if WORLD == 1:
+		wx,wy,wz = OB.getLocation( 'worldspace' )
+	elif WORLD ==2:
+		l = OB.getLocation( 'worldspace' )
+		w = Window.GetCursorPos()
+		wx,wy,wz = l[0]-w[0], l[1]-w[1], l[2]-w[2]
+	else:
+		wx,wy,wz = 0,0,0
+
+	for v in ME.verts:
+		co = v.co
+		co[2] = Combine_Functions( (co[0]+wx,co[1]+wy),(co[0]+wx, co[1]+wy, 0.0+wz) )
+	ME.update()
+	ME.calcNormals()	
+	#OB.makeDisplayList()
+
+
+#----------------------------------------------------------------------------------------------------
+##----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+####----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+## Do_it:
+#--------------------------------------
+
+#--------------------------------------
+def do_it():
+	global PreView, actme, actob, WorldSpaceCo
+	if actme !=[]:	
+		if print_time !=0:
+			t= sys.time()
+		Window.WaitCursor(1)
+		in_editmode = Window.EditMode()
+		if in_editmode: Window.EditMode(0)
+		if PreView[0].val != 0:
+			do_it_preview()
+			displace( actob[0], actme[0], WorldSpaceCo.val  )
+			Window.RedrawAll()
+		else:
+			displace( actob[0], actme[0], WorldSpaceCo.val  )
+			Window.RedrawAll()
+		if in_editmode: Window.EditMode(1)
+		Window.WaitCursor(0)			
+		if print_time !=0:
+			print 'Generate Mesh: done in %.6f' % (sys.time()-t)
+
+#--------------------------------------
+def do_it_random():
+	global PreView, actme, actob
+	if actme !=[]:	
+		if print_time !=0:
+			t= sys.time()
+		Window.WaitCursor(1)
+		in_editmode = Window.EditMode()
+		if in_editmode: Window.EditMode(0)
+		randomiseNoise()
+		if PreView[0].val != 0:
+			do_it_preview()
+			displace( actob[0], actme[0], WorldSpaceCo.val  )
+			Window.RedrawAll()
+		else:
+			displace( actob[0], actme[0], WorldSpaceCo.val  )
+			Window.RedrawAll()
+		if in_editmode: Window.EditMode(1)
+		Window.WaitCursor(0)
+		if print_time !=0:
+			print 'Generate Mesh: done in %.6f' % (sys.time()-t)
+
+#--------------------------------------
+def do_it_preview():
+	if print_time !=0:
+		t= sys.time()
+	HeightFieldImage()
+	Window.RedrawAll()
+	if print_time !=0:
+		print 'Generate Image: done in %.6f' % (sys.time()-t)
+
+###---------------------------------------------------------
+###---------------------------------------------------------
+## load and save:
+#-------------------------
+
+def callback( filename ):
+	txtFile.val = filename
+	Register(drawgui, events, bevents)
+def writeln(f,x):
+  f.write(str(x))
+  f.write("\n")
+def readint(f):
+  return int(f.readline())
+def readfloat(f):
+  return float(f.readline())
+def readstr(f):
+  s = (f.readline())
+  return strip(s)
+
+#--------------------------------------------------
+# Save settings to .ant file
+def SavePreset(FName):
+	global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly
+	global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo
+	global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+	global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo
+
+	try:
+		f = open(FName,'w')
+		writeln(f,CurVersion)
+	except:
+		filemessage = "Unable to save file."
+		return
+
+	writeln(f,fileinfo)
+	writeln(f,iScale[0].val)
+	writeln(f,iScale[1].val)
+	writeln(f,iScale[2].val)
+	writeln(f,Offset[0].val)
+	writeln(f,Offset[1].val)
+	writeln(f,Offset[2].val)
+	writeln(f,Invert[0].val)
+	writeln(f,Invert[1].val)
+	writeln(f,Invert[2].val)
+	writeln(f,NSize[0].val)
+	writeln(f,NSize[1].val)
+	writeln(f,Sx[0].val)
+	writeln(f,Sx[1].val)
+	writeln(f,Sy[0].val)
+	writeln(f,Sy[1].val)
+	writeln(f,Lx[0].val)
+	writeln(f,Lx[1].val)
+	writeln(f,Ly[0].val)
+	writeln(f,Ly[1].val)
+	writeln(f,NType.val)
+	writeln(f,Basis[0].val)
+	writeln(f,Basis[1].val)
+	writeln(f,musgr[0].val)
+	writeln(f,musgr[1].val)
+	writeln(f,musgr[2].val)
+	writeln(f,musgr[3].val)
+	writeln(f,musgr[4].val)
+	writeln(f,musgr[5].val)
+	writeln(f,tBasismod.val)
+	writeln(f,vlnoi[0].val)
+	writeln(f,vlnoi[1].val)
+	writeln(f,vlnoiTwo[0].val)
+	writeln(f,vlnoiTwo[1].val)
+	writeln(f,voron[0].val)
+	writeln(f,voron[1].val)
+	writeln(f,turbOne[0].val)
+	writeln(f,turbOne[1].val)
+	writeln(f,turbOne[2].val)	
+	writeln(f,turbOne[3].val)
+	writeln(f,turbTwo[0].val)
+	writeln(f,turbTwo[1].val)	
+	writeln(f,turbTwo[2].val)	
+	writeln(f,turbTwo[3].val)	
+	writeln(f,marbleOne[0].val)
+	writeln(f,marbleOne[1].val)
+	writeln(f,marbleOne[2].val)
+	writeln(f,marbleOne[3].val)
+	writeln(f,marbleOne[4].val)
+	writeln(f,marbleOne[5].val)
+	writeln(f,marbleTwo[0].val)
+	writeln(f,marbleTwo[1].val)		
+	writeln(f,marbleTwo[2].val)
+	writeln(f,marbleTwo[3].val)
+	writeln(f,marbleTwo[4].val)
+	writeln(f,marbleTwo[5].val)
+	writeln(f,musgrTwo[0].val)
+	writeln(f,musgrTwo[1].val)
+	writeln(f,musgrTwo[2].val)
+	writeln(f,musgrTwo[3].val)
+	writeln(f,musgrTwo[4].val)
+	writeln(f,effect_image)
+	writeln(f,Effect_Ctrl[0].val)
+	writeln(f,Effect_Ctrl[1].val)
+	writeln(f,Effect_Ctrl[2].val)
+	writeln(f,Effect_Ctrl[3].val)
+	writeln(f,Effect_Ctrl[4].val)
+	writeln(f,Effect_Ctrl[5].val)
+	writeln(f,Effect_Ctrl[6].val)
+	writeln(f,Effect_Ctrl[7].val)
+	writeln(f,Effect_Ctrl[8].val)
+	writeln(f,CustomFX[0].val)
+	writeln(f,CustomFX[1].val)
+	writeln(f,CustomFX[2].val)
+	writeln(f,Min.val)
+	writeln(f,Max.val)
+	writeln(f,Falloff[0].val)
+	writeln(f,Falloff[1].val)
+	writeln(f,Falloff[2].val)
+	writeln(f,Falloff[3].val)
+	writeln(f,Falloff[4].val)
+	writeln(f,Filter_Mode.val)
+	writeln(f,Filter_Order.val)
+	writeln(f,CustomFilt[0].val)
+	writeln(f,CustomFilt[1].val)
+	writeln(f,CustomFilt[2].val)
+	writeln(f,Def_Filter_Ctrl[0].val)
+	writeln(f,Def_Filter_Ctrl[1].val)
+	writeln(f,Ipo_Filter_Ctrl[0].val)
+	writeln(f,Ipo_Filter_Ctrl[1].val)
+	writeln(f,Ipo_Filter_Ctrl[2].val)
+	writeln(f,Ipo_Filter_Ctrl[3].val)
+	writeln(f,RandMod.val)
+	writeln(f,RSeed.val)
+	writeln(f,rand_H.val)
+	writeln(f,rand_I.val)
+	writeln(f,rand_S.val)
+	writeln(f,rand_L.val)
+	filemessage = 'Settings saved to file.'
+	f.close()
+
+#--------------------------------------------------
+# load settings from .ant file
+def LoadPreset(FName):
+	global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly
+	global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo
+	global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+	global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo
+
+	try:
+		f = open(FName,'r')
+		FVersion = readstr(f)
+	except:
+		filemessage = "Unable to open file."
+		return
+
+	fileinfo = readstr(f)
+	iScale[0].val = readfloat(f)
+	iScale[1].val = readfloat(f)
+	iScale[2].val = readfloat(f)
+	Offset[0].val = readfloat(f)
+	Offset[1].val = readfloat(f)
+	Offset[2].val = readfloat(f)
+	Invert[0].val = readint(f)
+	Invert[1].val = readint(f)
+	Invert[2].val = readint(f)
+	NSize[0].val = readfloat(f)
+	NSize[1].val = readfloat(f)
+	Sx[0].val = readfloat(f)
+	Sx[1].val = readfloat(f)
+	Sy[0].val = readfloat(f)
+	Sy[1].val = readfloat(f)
+	Lx[0].val = readfloat(f)
+	Lx[1].val = readfloat(f)
+	Ly[0].val = readfloat(f)
+	Ly[1].val = readfloat(f)
+	NType.val = readint(f)
+	Basis[0].val = readint(f)
+	Basis[1].val = readint(f)
+	musgr[0].val = readfloat(f)
+	musgr[1].val = readfloat(f)
+	musgr[2].val = readint(f)
+	musgr[3].val = readfloat(f)
+	musgr[4].val = readfloat(f)
+	musgr[5].val = readfloat(f)
+	tBasismod.val  = readint(f)
+	vlnoi[0].val = readfloat(f)
+	vlnoi[1].val = readint(f)
+	vlnoiTwo[0].val = readfloat(f)
+	vlnoiTwo[1].val = readint(f)
+	voron[0].val = readint(f)
+	voron[1].val = readfloat(f)
+	turbOne[0].val = readint(f)
+	turbOne[1].val = readint(f)
+	turbOne[2].val = readfloat(f)
+	turbOne[3].val = readfloat(f)
+	turbTwo[0].val = readint(f)
+	turbTwo[1].val = readint(f)
+	turbTwo[2].val = readfloat(f)
+	turbTwo[3].val = readfloat(f)
+	marbleOne[0].val = readint(f)
+	marbleOne[1].val = readint(f)
+	marbleOne[2].val = readfloat(f)
+	marbleOne[3].val = readint(f)
+	marbleOne[4].val = readint(f)
+	marbleOne[5].val = readfloat(f)
+	marbleTwo[0].val = readint(f)
+	marbleTwo[1].val = readint(f)
+	marbleTwo[2].val = readfloat(f)
+	marbleTwo[3].val = readint(f)
+	marbleTwo[4].val = readint(f)
+	marbleTwo[5].val = readfloat(f)
+	musgrTwo[0].val = readfloat(f)
+	musgrTwo[1].val = readfloat(f)
+	musgrTwo[2].val = readint(f)
+	musgrTwo[3].val = readfloat(f)
+	musgrTwo[4].val = readfloat(f)
+	effect_image = readstr(f)
+	Effect_Ctrl[0].val = readint(f)
+	Effect_Ctrl[1].val = readint(f)
+	Effect_Ctrl[2].val = readfloat(f)
+	Effect_Ctrl[3].val = readint(f)
+	Effect_Ctrl[4].val = readfloat(f)
+	Effect_Ctrl[5].val = readint(f)
+	Effect_Ctrl[6].val = readfloat(f)
+	Effect_Ctrl[7].val = readfloat(f)
+	Effect_Ctrl[8].val = readfloat(f)
+	CustomFX[0].val = readstr(f)
+	CustomFX[1].val = readstr(f)
+	CustomFX[2].val = readstr(f)
+	Min.val = readfloat(f)
+	Max.val = readfloat(f)
+	Falloff[0].val = readint(f)
+	Falloff[1].val = readfloat(f)
+	Falloff[2].val = readfloat(f)
+	Falloff[3].val = readint(f)
+	Falloff[4].val = readint(f)
+	Filter_Mode.val = readint(f)
+	Filter_Order.val = readint(f)
+	CustomFilt[0].val = readstr(f)
+	CustomFilt[1].val = readstr(f)
+	CustomFilt[2].val = readstr(f)
+	Def_Filter_Ctrl[0].val = readint(f)
+	Def_Filter_Ctrl[1].val = readfloat(f)
+	Ipo_Filter_Ctrl[0].val = readstr(f)
+	Ipo_Filter_Ctrl[1].val = readint(f)
+	Ipo_Filter_Ctrl[2].val = readfloat(f)
+	Ipo_Filter_Ctrl[3].val = readfloat(f)
+	RandMod.val = readint(f)
+	RSeed.val = readint(f)
+	rand_H.val = readint(f)
+	rand_I.val = readint(f)	
+	rand_S.val = readint(f)
+	rand_L.val = readint(f)
+	filemessage = 'Settings loaded from file.'
+	f.close()
+
+##---------------------------------------------------------------------------
+# Register:
+
+Register( drawgui, events, bevents )
+###--------------------------------------------------------------------------
+		
\ No newline at end of file
diff --git a/release/scripts/xfig_export.py b/release/scripts/xfig_export.py
deleted file mode 100644
index ddc0dd4dceab83e539c2d1ff811ae30c4b71c036..0000000000000000000000000000000000000000
--- a/release/scripts/xfig_export.py
+++ /dev/null
@@ -1,234 +0,0 @@
-#!BPY
-"""
-Name: 'xfig export (.fig)'
-Blender: 244
-Group: 'Export'
-Tooltip: 'Export selected mesh to xfig Format (.fig)'
-"""
-
-__author__ = 'Dino Ghilardi',  'Campbell Barton AKA Ideasman42'
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.1"
-
-__bpydoc__ = """\
-		This script exports the selected mesh to xfig (www.xfig.org) file format (i.e.: .fig)
-
-		The starting point of this script was Anthony D'Agostino's raw triangle format export.
-		(some code is still here and there, cut'n pasted from his script)
-
-		Usage:<br>
-			Select the mesh to be exported and run this script from "File->Export" menu.
-			The toggle button 'export 3 files' enables the generation of 4 files: one global
-			and three with the three different views of the object.
-			This script is licensed under the GPL license. (c) Dino Ghilardi, 2005
-			
-"""
-
-# .fig export, mostly brutally cut-n pasted from the 
-# 'Raw triangle export' (Anthony D'Agostino, http://www.redrival.com/scorpius)|
-
-import Blender
-from Blender import Draw
-import BPyObject
-#, meshtools
-import sys
-import bpy
-#import time
-
-# =================================
-# === Write xfig Format.===
-# =================================
-
-def collect_edges(edges):
-	"""Gets the max-min coordinates of the mesh"""
-	
-	"""Getting the extremes of the mesh to be exported"""
-	
-	maxX=maxY=maxZ = -1000000000
-	minX=minY=minZ =  1000000000
-	
-	FGON= Blender.Mesh.EdgeFlags.FGON
-	
-	me = bpy.data.meshes.new()
-	for ob_base in bpy.data.scenes.active.objects.context:
-		for ob in BPyObject.getDerivedObjects(ob_base):
-			me.verts = None
-			try:	me.getFromObject(ob[0])
-			except: pass
-			
-			if me.edges:
-				me.transform(ob[1])
-				
-				for ed in me.edges:
-					if not ed.flag & FGON:
-						x,y,z = v1 = tuple(ed.v1.co)
-						maxX = max(maxX, x)
-						maxY = max(maxY, y)
-						maxZ = max(maxZ, z)
-						minX = min(minX, x)
-						minY = min(minY, y)
-						minZ = min(minZ, z)
-						
-						x,y,z = v2 = tuple(ed.v2.co)
-						maxX = max(maxX, x)
-						maxY = max(maxY, y)
-						maxZ = max(maxZ, z)
-						minX = min(minX, x)
-						minY = min(minY, y)
-						minZ = min(minZ, z)
-						
-						edges.append( (v1, v2) )
-					
-	me.verts = None # free memory
-	return maxX,maxY,maxZ,minX,minY,minZ
-
-def xfigheader(file):
-	file.write('#FIG 3.2  Produced by xfig version 3.2.5-alpha5\n')
-	file.write('Landscape\n')
-	file.write('Center\n')
-	file.write('Metric\n')
-	file.write('A4\n')
-	file.write('100.00\n')
-	file.write('Single\n')
-	file.write('-2\n')
-	file.write('1200 2\n')
-
-def figdata(file, edges, expview, bounds, scale, space):
-	maxX,maxY,maxZ,minX,minY,minZ = bounds
-	
-	def xytransform(ed):
-		"""gives the face vertexes coordinates in the xfig format/translation (view xy)"""	
-		x1,y1,z1 = ed[0]
-		x2,y2,z2 = ed[1]
-		y1=-y1; y2=-y2
-		return x1,y1,z1,x2,y2,z2
-
-	def xztransform(ed):
-		"""gives the face vertexes coordinates in the xfig format/translation (view xz)"""
-		x1,y1,z1 = ed[0]
-		x2,y2,z2 = ed[1]
-		y1=-y1
-		y2=-y2
-		
-		z1=-z1+maxZ-minY +space
-		z2=-z2+maxZ-minY +space
-		return x1,y1,z1,x2,y2,z2
-
-	def yztransform(ed):
-		"""gives the face vertexes coordinates in the xfig format/translation (view xz)"""
-		x1,y1,z1 = ed[0]
-		x2,y2,z2 = ed[1]
-		y1=-y1; y2=-y2
-		z1=-(z1-maxZ-maxX-space)
-		z2=-(z2-maxZ-maxX-space)
-		return x1,y1,z1,x2,y2,z2
-
-	def transform(ed, expview, scale):
-		if		expview=='xy':
-			x1,y1,z1,x2,y2,z2 = xytransform(ed)
-			return int(x1*scale),int(y1*scale),int(x2*scale),int(y2*scale)
-		elif	expview=='xz':
-			x1,y1,z1,x2,y2,z2 = xztransform(ed)
-			return int(x1*scale),int(z1*scale),int(x2*scale),int(z2*scale)
-		elif	expview=='yz':
-			x1,y1,z1,x2,y2,z2 = yztransform(ed)
-			return int(z1*scale),int(y1*scale),int(z2*scale),int(y2*scale)
-	
-	
-	"""Prints all the xfig data (no header)"""
-	for ed in edges:
-		file.write('2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n')
-		file.write('\t %i %i %i %i\n' % transform(ed, expview, scale))
-
-def writexy(edges, bounds, filename, scale, space):
-	"""writes the x-y view file exported"""
-	
-	file = open(filename, 'wb')
-	xfigheader(file)
-	figdata(file, edges, 'xy', bounds, scale, space)
-	file.close()
-	print 'Successfully exported ', Blender.sys.basename(filename)# + seconds
-
-def writexz(edges, bounds, filename, scale, space):
-	"""writes the x-z view file exported"""
-	#start = time.clock()
-	file = open(filename, 'wb')
-	xfigheader(file)
-	figdata(file, edges, 'xz', bounds, scale, space)
-	file.close()
-	print 'Successfully exported ', Blender.sys.basename(filename)# + seconds
-
-def writeyz(edges, bounds, filename, scale, space):
-	"""writes the y-z view file exported"""
-	
-	#start = time.clock()
-	file = open(filename, 'wb')
-	xfigheader(file)
-	figdata(file, edges, 'yz', bounds, scale, space)
-	file.close()
-	#end = time.clock()
-	#seconds = " in %.2f %s" % (end-start, "seconds")
-	print 'Successfully exported ', Blender.sys.basename(filename)# + seconds
-
-def writeall(edges, bounds, filename, scale=450, space=2.0):
-	"""writes all 3 views
-	
-	Every view is a combined object in the resulting xfig. file."""
-	
-	maxX,maxY,maxZ,minX,minY,minZ = bounds
-	
-	file = open(filename, 'wb')
-
-	xfigheader(file)
-	file.write('#upper view (7)\n')
-	file.write('6 % i % i % i % i ')
-	file.write('%.6f %.6f %.6f %.6f\n' % (minX, minY, maxX, maxY))
-	
-	figdata(file, edges, 'xy', bounds, scale, space)
-	file.write('-6\n')
-	file.write('#bottom view (1)\n')
-	file.write('6 %i %i %i %i ')
-	file.write('%.6f %.6f %.6f %.6f\n' % (minX, -minZ+maxZ-minY +space, maxX,-maxZ+maxZ-minY +space))
-	
-	figdata(file, edges, 'xz', bounds, scale, space)
-	file.write('-6\n')
-	
-	file.write('#right view (3)\n')
-	file.write('6 %i %i %i %i ')
-	file.write('%.6f %.6f %.6f %.6f\n' % (minX, -minZ+maxZ-minY +space, maxX,-maxZ+maxZ-minY +space))
-	figdata(file, edges, 'yz', bounds, scale, space)
-	file.write('-6\n')
-	
-	file.close()
-	print 'Successfully exported ', Blender.sys.basename(filename)# + seconds
-
-import BPyMessages
-
-def write_ui(filename):
-	if filename.lower().endswith('.fig'): filename = filename[:-4]
-	
-	PREF_SEP= Draw.Create(0)
-	PREF_SCALE= Draw.Create(1200)
-	PREF_SPACE= Draw.Create(2.0)
-	
-	block = [\
-		("Separate Files", PREF_SEP, "Export each view axis as a seperate file"),\
-		("Space: ", PREF_SPACE, 0.0, 10.0, "Space between views in blender units"),\
-		("Scale: ", PREF_SCALE, 10, 100000, "Scale, 1200 is a good default")]
-	
-	if not Draw.PupBlock("Export FIG", block):
-		return
-	
-	edges = []
-	bounds = collect_edges(edges)
-	
-	if PREF_SEP.val:
-		writexy(edges, bounds, filename + '_XY.fig', PREF_SCALE.val, PREF_SPACE.val)
-		writexz(edges, bounds, filename + '_XZ.fig', PREF_SCALE.val, PREF_SPACE.val)
-		writeyz(edges, bounds, filename + '_YZ.fig', PREF_SCALE.val, PREF_SPACE.val)
-	
-	writeall(edges, bounds, filename + '.fig', PREF_SCALE.val, PREF_SPACE.val)
-
-if __name__ == '__main__':
-	Blender.Window.FileSelector(write_ui, 'Export XFIG', Blender.sys.makename(ext='.fig'))
-	
\ No newline at end of file
diff --git a/source/Makefile b/source/Makefile
index d8dee601998a9f86dffa9121542f06047f29df9a..7374ef3e7d67614cdad78d07ce8ccc041b1e7576 100644
--- a/source/Makefile
+++ b/source/Makefile
@@ -83,7 +83,7 @@ GRPLIB += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
 GRPLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender.a
 GRPLIB += $(OCGDIR)/blender/radiosity/$(DEBUG_DIR)libradiosity.a
 GRPLIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a
-GRPLIB += $(NAN_SUPERLU)/lib/$(DEBUG_DIR)libsuperlu.a	
+GRPLIB += $(NAN_SUPERLU)/lib/$(DEBUG_DIR)libsuperlu.a
 GRPLIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a
 
 # nlin: the reason that some libraries appear more than once below is
@@ -154,6 +154,9 @@ ifneq ($(NAN_NO_KETSJI),true)
     COMLIB += $(NAN_BULLET2)/lib/libbullet2.a
 endif
 
+# Cloth requires bullet2, gameegine does not matter anymore
+#COMLIB += $(NAN_BULLET2)/lib/libbullet2.a
+
 COMLIB += $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a
 COMLIB += $(NAN_MEMUTIL)/lib/libmemutil.a
 COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a
@@ -258,6 +261,7 @@ SPLIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
 # can I just not check them? nm claims they aren't...
 SPLIB += $(OCGDIR)/blender/blenkernel/blenkernel_blc/$(DEBUG_DIR)libblenkernel_blc.a
 SPLIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a
+SPLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
 
 # These three need to be explicitly mentioned on the cl, because 
 # if they are offered as a lib, they are optimized away. (nzc)
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 5a1e266adeb204520c15be8b66850e49d445cf9e..7ee8a424d03986346b07ca6222dd63900b7be7e3 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -44,6 +44,7 @@
 
 #include "DNA_customdata_types.h"
 #include "BKE_customdata.h"
+#include "BKE_bvhutils.h"
 
 struct MVert;
 struct MEdge;
@@ -69,6 +70,7 @@ struct DerivedMesh {
 	int numVertData, numEdgeData, numFaceData;
 	int needsFree; /* checked on ->release, is set to 0 for cached results */
 	int deformedOnly; /* set by modifier stack if only deformed from original */
+	BVHCache bvhCache;
 
 	/* Misc. Queries */
 
@@ -442,6 +444,9 @@ DerivedMesh *mesh_create_derived_no_deform(struct Object *ob,
 DerivedMesh *mesh_create_derived_no_deform_render(struct Object *ob,
                                                   float (*vertCos)[3],
                                                   CustomDataMask dataMask);
+/* for gameengine */
+DerivedMesh *mesh_create_derived_no_virtual(struct Object *ob, float (*vertCos)[3],
+                                            CustomDataMask dataMask);
 
 DerivedMesh *editmesh_get_derived_base(void);
 DerivedMesh *editmesh_get_derived_cage(CustomDataMask dataMask);
diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h
index 93bfb2339beeee51c2283c210660f082c105c8bb..71f8aee8e99a4881197f125198979f9e137020e5 100644
--- a/source/blender/blenkernel/BKE_bad_level_calls.h
+++ b/source/blender/blenkernel/BKE_bad_level_calls.h
@@ -92,6 +92,7 @@ int pytype_is_pynode(struct PyObject *pyob);
 struct Oops;
 void free_oops(struct Oops *oops);
 void error(char *str, ...);
+int okee(char *str, ...);
 
 /* anim.c */
 extern struct ListBase editNurb;
@@ -160,8 +161,8 @@ void bglEnd(void);
 struct Object;
 
 /* booleanops.c */
-struct DerivedMesh *NewBooleanDerivedMesh(struct Object *ob,
-                                struct Object *ob_select, int int_op_type);
+struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob, struct DerivedMesh *dm_select, struct Object *ob_select,
+                                   int int_op_type);
 
 /* verse_*.c */
 struct VerseVert;
diff --git a/source/blender/blenkernel/BKE_booleanops.h b/source/blender/blenkernel/BKE_booleanops.h
index b83b9c89ae847739d24f289b1fcba1b3eb893850..118066e380617f426a6efe70af4368159f93dc78 100644
--- a/source/blender/blenkernel/BKE_booleanops.h
+++ b/source/blender/blenkernel/BKE_booleanops.h
@@ -42,8 +42,7 @@ int NewBooleanMesh(struct Base *base, struct Base *base_select, int op);
 /* Performs a boolean between two mesh objects, it is assumed that both objects
    are in fact mesh object. On success returns a DerivedMesh. On failure
    returns NULL and reports an error. */
-struct DerivedMesh *NewBooleanDerivedMesh(struct Object *ob,
-                                          struct Object *ob_select,
-                                          int op);
+struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob, struct DerivedMesh *dm_select, struct Object *ob_select,
+                                   int int_op_type);
 #endif
 
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index dd9ea61f24b0b539d69aab085b7eb12533583268..66c8d99959a896d7ef3c908830659f880f51b0ad 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -31,6 +31,7 @@
 #define BKE_BVHUTILS_H
 
 #include "BLI_kdopbvh.h"
+#include "BLI_linklist.h"
 
 /*
  * This header encapsulates necessary code to buld a BVH
@@ -52,7 +53,7 @@ typedef struct BVHTreeFromMesh
 	BVHTree_RayCastCallback      raycast_callback;
 
 	/* Mesh represented on this BVHTree */
-	struct DerivedMesh *mesh; 
+	struct DerivedMesh *mesh;
 
 	/* Vertex array, so that callbacks have instante access to data */
 	struct MVert *vert;
@@ -61,6 +62,9 @@ typedef struct BVHTreeFromMesh
 	/* radius for raycast */
 	float sphere_radius;
 
+	/* Private data */
+	int cached;
+
 } BVHTreeFromMesh;
 
 /*
@@ -74,7 +78,7 @@ typedef struct BVHTreeFromMesh
  * 
  * free_bvhtree_from_mesh should be called when the tree is no longer needed.
  */
-void bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree* bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
 
 /*
  * Builds a bvh tree where nodes are the faces of the given mesh.
@@ -84,15 +88,50 @@ void bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *m
  * so that the coordinates and rays are first translated on the mesh local coordinates.
  * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becames possible to reuse
  * a BVHTree.
+ *
+ * The returned value is the same as in data->tree, its only returned to make it easier to test
+ * the success 
  * 
  * free_bvhtree_from_mesh should be called when the tree is no longer needed.
  */
-void bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree* bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
 
 /*
  * Frees data allocated by a call to bvhtree_from_mesh_*.
  */
 void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data);
 
+
+/*
+ * BVHCache
+ */
+
+//Using local coordinates
+#define BVHTREE_FROM_FACES		0
+#define BVHTREE_FROM_VERTICES	1
+
+typedef LinkNode* BVHCache;
+
+
+/*
+ * Queries a bvhcache for the chache bvhtree of the request type
+ */
+BVHTree *bvhcache_find(BVHCache *cache, int type);
+
+/*
+ * Inserts a BVHTree of the given type under the cache
+ * After that the caller no longer needs to worry when to free the BVHTree
+ * as that will be done when the cache is freed.
+ *
+ * A call to this assumes that there was no previous cached tree of the given type
+ */
+void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type);
+
+/*
+ * inits and frees a bvhcache
+ */
+void bvhcache_init(BVHCache *cache);
+void bvhcache_free(BVHCache *cache);
+
 #endif
 
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index a8d4ece7a2180092a12b6859a81a0bc23abeaedc..79f4708fd41875d07be641b37a1a4b015d50f34d 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -47,7 +47,7 @@ struct BevList;
 #define SEGMENTSV(nu)	    ( ((nu)->flagv & CU_CYCLIC) ? (nu)->pntsv : (nu)->pntsv-1 )
 
 #define CU_DO_TILT(cu, nu) (((nu->type & CU_2D) && (cu->flag & CU_3D)==0) ? 0 : 1)
-#define CU_DO_RADIUS(cu, nu) ((CU_DO_TILT(cu, nu) || cu->bevobj) ? 1:0)
+#define CU_DO_RADIUS(cu, nu) ((CU_DO_TILT(cu, nu) || cu->bevobj || cu->ext1!=0.0 || cu->ext2!=0.0) ? 1:0)
 
 
 void unlink_curve( struct Curve *cu);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 5dbfe2fe520ecbb9a5775dedc474314828d12eeb..5f5635bae1f03edabc755465a6d18f58d99f7fec 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -173,7 +173,7 @@ typedef struct ParticleThreadContext {
 
 	/* path caching */
 	int editupdate, between, steps;
-	int totchild, totparent;
+	int totchild, totparent, parent_pass;
 
 	float cfra;
 
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 2bd528ab8c8abc0ddd167a43a3a0f1a9690e9e7a..647f7e95fd97d3ab1d52b69e53ae6060e4a70201 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -35,6 +35,7 @@ struct bglMats;
 struct Scene;
 struct Object;
 struct Base;
+struct Text;
 struct AviCodecData;
 struct QuicktimeCodecData;
 struct SculptData;
@@ -86,5 +87,7 @@ int get_render_child_particle_number(struct RenderData *r, int num);
 int get_render_shadow_samples(struct RenderData *r, int samples);
 float get_render_aosss_error(struct RenderData *r, float error);
 
+void free_dome_warp_text(struct Text *txt);
+
 #endif
 
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index eed22ff9d8e3dda2609fcc6ac4485bf780807f19..6ce449f78240e69d7379343b50b00d2f365b4236 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -95,6 +95,8 @@ void space_transform_invert_normal(const SpaceTransform *data, float *no);
 
 struct Object;
 struct DerivedMesh;
+struct MVert;
+struct MDeformVert;
 struct ShrinkwrapModifierData;
 struct MDeformVert;
 struct BVHTree;
@@ -105,8 +107,8 @@ typedef struct ShrinkwrapCalcData
 	ShrinkwrapModifierData *smd;	//shrinkwrap modifier data
 
 	struct Object *ob;				//object we are applying shrinkwrap to
-	struct DerivedMesh *original;	//mesh before shrinkwrap
 
+	MVert *vert;					//Array of verts being projected (to fetch normals or other data)
 	float (*vertexCos)[3];			//vertexs being shrinkwraped
 	int numVerts;
 
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index a7e4d8807b2429175f6596be47fe25a63dd8c530..f68e2b70c86c1083b71ec04ffb7926251b786ffb 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -15,56 +15,58 @@ incs += ' ../gpu #/extern/glew/include'
 incs += ' ' + env['BF_OPENGL_INC']
 incs += ' ' + env['BF_ZLIB_INC']
 
-defs = ''
+defs = []
 
 if not env['WITH_BF_PYTHON']:
-	defs += 'DISABLE_PYTHON'
+	defs.append('DISABLE_PYTHON')
 else:
 	incs += ' ../python'
 	incs += ' ' + env['BF_PYTHON_INC']
+	if env['BF_DEBUG']:
+		defs.append('_DEBUG')
 
 if env['WITH_BF_QUICKTIME']:
-    incs += ' ../quicktime'
+	incs += ' ../quicktime'
 
 if env['WITH_BF_SDL']:
 	incs += ' ' + env['BF_SDL_INC']
 else:
-	defs += ' DISABLE_SDL'
+	defs.append('DISABLE_SDL')
 
 if env['WITH_BF_INTERNATIONAL']:
-	defs += ' WITH_FREETYPE2'
+	defs.append('WITH_FREETYPE2')
 
 if env['WITH_BF_VERSE']:
-	defs += ' WITH_VERSE'
+	defs.append('WITH_VERSE')
 	incs += ' ' + env['BF_VERSE_INCLUDE']
 
 if env['WITH_BF_VERSE']:
-	defs += ' WITH_VERSE'
+	defs.append('WITH_VERSE')
 	
 if env['WITH_BF_OPENEXR']:
-    defs += ' WITH_OPENEXR'
+	defs.append('WITH_OPENEXR')
 
 if env['WITH_BF_OPENJPEG']:
-    defs += ' WITH_OPENJPEG'
+	defs.append('WITH_OPENJPEG')
 
 if env['WITH_BF_DDS']:
-    defs += ' WITH_DDS'
+	defs.append('WITH_DDS')
 
 if env['WITH_BF_FFMPEG']:
-    defs += ' WITH_FFMPEG'
-    incs += ' ' + env['BF_FFMPEG_INC']
+	defs.append('WITH_FFMPEG')
+	incs += ' ' + env['BF_FFMPEG_INC']
 
 if env['WITH_BF_QUICKTIME']:
-    defs += ' WITH_QUICKTIME'
-    incs += ' ' + env['BF_QUICKTIME_INC']
+	defs.append('WITH_QUICKTIME')
+	incs += ' ' + env['BF_QUICKTIME_INC']
 
 if env['WITH_BF_BULLET']:
-    defs += ' WITH_BULLET'
+	defs.append('WITH_BULLET')
 
 if env['BF_NO_ELBEEM']:
-    defs += ' DISABLE_ELBEEM'
+	defs.append('DISABLE_ELBEEM')
 
 if env['WITH_BF_PLAYER']:
-    SConscript(['bad_level_call_stubs/SConscript'])
+	SConscript(['bad_level_call_stubs/SConscript'])
 
-env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core','player'], priority = [65, 20] )
+env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [65, 20] )
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index fecead66bda2858f2f6014bc7a3b4b9a5046a33c..3012c19ff02788e987b7bf5eca6bafbd401cd384 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -160,6 +160,7 @@ void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTa
 void free_oops(struct Oops *oops){}
 void exit_posemode(int freedata){}
 void error(char *str, ...){}
+int okee(char *str, ...){}
 
 /* anim.c */
 ListBase editNurb;
@@ -240,7 +241,8 @@ void bglVertex3f(float x, float y, float z) {}
 void bglEnd(void) {}
 
 /* booleanops.c */
-struct DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select, int int_op_type) { return 0; }
+struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob, struct DerivedMesh *dm_select, struct Object *ob_select,
+                                   int int_op_type) { return 0; }
 
 /* LOD_decimation.cpp */
 int LOD_LoadMesh(struct LOD_Decimation_Info* info) { return 0;};
@@ -326,7 +328,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove) {}
 /* imagetexture.c stub */
 void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result) {}
 
-void update_for_newframe() {}
+void update_for_newframe(void) {}
 
 struct FileList;
 void BIF_filelist_freelib(struct FileList* filelist) {};
@@ -335,7 +337,8 @@ void BIF_filelist_freelib(struct FileList* filelist) {};
 TimeMarker *get_frame_marker(int frame){return 0;};
 
 /* editseq.c */
-Sequence *get_forground_frame_seq(int frame){return 0;};
+#include "BIF_editseq.h" // And fix the missing void there
+Sequence *get_foreground_frame_seq(int frame){return 0;};
 void clear_last_seq(Sequence *seq){};
     
 
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index c934f7d9fe7d4b3ad9195cb0b6b82ae8e114d3f6..ddb7d853f2f8af7773c2da05c35a349a9e65d219 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -77,6 +77,7 @@
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 #include "BKE_particle.h"
+#include "BKE_bvhutils.h"
 
 #include "BLO_sys_types.h" // for intptr_t support
 
@@ -182,6 +183,8 @@ void DM_init_funcs(DerivedMesh *dm)
 	dm->getVertDataArray = DM_get_vert_data_layer;
 	dm->getEdgeDataArray = DM_get_edge_data_layer;
 	dm->getFaceDataArray = DM_get_face_data_layer;
+
+	bvhcache_init(&dm->bvhCache);
 }
 
 void DM_init(DerivedMesh *dm,
@@ -218,6 +221,8 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
 int DM_release(DerivedMesh *dm)
 {
 	if (dm->needsFree) {
+		bvhcache_free(&dm->bvhCache);
+
 		CustomData_free(&dm->vertData, dm->numVertData);
 		CustomData_free(&dm->edgeData, dm->numEdgeData);
 		CustomData_free(&dm->faceData, dm->numFaceData);
@@ -904,7 +909,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
 	glShadeModel(GL_SMOOTH);
 
 	for (i=0,eve=em->verts.first; eve; eve= eve->next)
-		eve->tmp.l = (long) i++;
+		eve->tmp.l = (intptr_t) i++;
 
 #define PASSATTRIB(efa, eve, vert) {											\
 	if(attribs.totorco) {														\
@@ -2106,6 +2111,11 @@ static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *
 		DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
 }
 
+/* new value for useDeform -1  (hack for the gameengine):
+ * - apply only the modifier stack of the object, skipping the virtual modifiers,
+ * - don't apply the key
+ * - apply deform modifiers and input vertexco
+ */
 static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                                 DerivedMesh **deform_r, DerivedMesh **final_r,
                                 int useRenderParams, int useDeform,
@@ -2120,7 +2130,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
 	int numVerts = me->totvert;
 	int required_mode;
 
-	md = firstmd = modifiers_getVirtualModifierList(ob);
+	md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob);
 
 	modifiers_clearErrors(ob);
 
@@ -2137,8 +2147,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
 	else required_mode = eModifierMode_Realtime;
 
 	if(useDeform) {
-		if(do_ob_key(ob)) /* shape key makes deform verts */
+		if(useDeform > 0 && do_ob_key(ob)) /* shape key makes deform verts */
 			deformedVerts = mesh_getVertexCos(me, &numVerts);
+		else if(inputVertexCos)
+			deformedVerts = inputVertexCos;
 		
 		/* Apply all leading deforming modifiers */
 		for(;md; md = md->next, curr = curr->next) {
@@ -2146,6 +2158,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
 
 			if((md->mode & required_mode) != required_mode) continue;
 			if(mti->isDisabled && mti->isDisabled(md)) continue;
+			if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
 
 			if(mti->type == eModifierTypeType_OnlyDeform) {
 				if(!deformedVerts)
@@ -2216,6 +2229,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
 		}
 		if(mti->isDisabled && mti->isDisabled(md)) continue;
 		if(needMapping && !modifier_supportsMapping(md)) continue;
+		if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
 
 		/* add an orco layer if needed by this modifier */
 		if(dm && mti->requiredDataMask) {
@@ -2942,6 +2956,16 @@ DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3],
 	return final;
 }
 
+DerivedMesh *mesh_create_derived_no_virtual(Object *ob, float (*vertCos)[3],
+                                            CustomDataMask dataMask)
+{
+	DerivedMesh *final;
+	
+	mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1);
+
+	return final;
+}
+
 DerivedMesh *mesh_create_derived_no_deform_render(Object *ob,
                                                   float (*vertCos)[3],
                                                   CustomDataMask dataMask)
diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile
index 226e416dad795aa43057717a77cc4d083f10a084..75f75b0c3c526649149713081a48242b917d4aa5 100644
--- a/source/blender/blenkernel/intern/Makefile
+++ b/source/blender/blenkernel/intern/Makefile
@@ -82,7 +82,7 @@ CPPFLAGS += -I../../gpu
 CPPFLAGS += -I..
 
 # path to bullet2, for cloth
-CPPFLAGS += -I../../../../extern/bullet2/src
+CPPFLAGS += -I$(NAN_BULLET2)/include
 
 ifeq ($(WITH_FREETYPE2), true)
     CPPFLAGS += -DWITH_FREETYPE2
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 5dcccc56d06223841d8d47c115eb68a917f38355..107953138c6b880c8af51c08a9a47bad28276503 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -423,18 +423,29 @@ static void setup_app_data(BlendFileData *bfd, char *filename)
 	MEM_freeN(bfd);
 }
 
-static void handle_subversion_warning(Main *main)
+static int handle_subversion_warning(Main *main)
 {
 	if(main->minversionfile > BLENDER_VERSION ||
 	   (main->minversionfile == BLENDER_VERSION && 
 		 main->minsubversionfile > BLENDER_SUBVERSION)) {
 		
 		char str[128];
-		
-		sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile);
-		error(str);
+
+		/* XXX DO NOT PORT OVER TO 2.5 BRANCH! */
+		if(main->minversionfile >= 250) {
+			sprintf(str, "You have opened a %d file, key information will get lost, like animation data. Continue?", main->minversionfile);
+			
+			if(G.background) {
+				printf("ERROR: cannot render %d file\n", main->versionfile);
+			}
+			return okee(str);
+		}
+		else {
+			sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile);
+			error(str);
+		}
 	}
-		
+	return 1;
 }
 
 /* returns:
@@ -458,9 +469,15 @@ int BKE_read_file(char *dir, void *type_r)
 		if (type_r)
 			*((BlenFileType*)type_r)= bfd->type;
 		
-		setup_app_data(bfd, dir);
+		if(0==handle_subversion_warning(bfd->main)) {
+			free_main(bfd->main);
+			MEM_freeN(bfd);
+			bfd= NULL;
+			retval= 0;
+		}
+		else
+			setup_app_data(bfd, dir); // frees BFD
 		
-		handle_subversion_warning(G.main);
 	} 
 	else {
 		error("Loading %s failed: %s", dir, BLO_bre_as_string(bre));
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
index 0af54b86ed6a3209b05110ae82456206e9df2db5..09770b2b4baeaba082b17dcf1a33a20c22bb4239 100644
--- a/source/blender/blenkernel/intern/bmfont.c
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -178,7 +178,7 @@ void detectBitmapFont(ImBuf *ibuf)
 {
 	unsigned char * rect;
 	unsigned short version;
-	long i;
+	int i;
 	
 	if (ibuf != NULL) {
 	        // bitmap must have an x size that is a power of two
diff --git a/source/blender/blenkernel/intern/bullet.c b/source/blender/blenkernel/intern/bullet.c
index b389f8c0536aa912e8fb0195138e478c2213925b..44e8ed1f08c6bb29cb365cd86c83eeb618c47877 100644
--- a/source/blender/blenkernel/intern/bullet.c
+++ b/source/blender/blenkernel/intern/bullet.c
@@ -82,6 +82,7 @@ BulletSoftBody *bsbNew(void)
 	bsb->collisionflags = 0;
 	//bsb->collisionflags = OB_BSB_COL_CL_RS + OB_BSB_COL_CL_SS;
 	bsb->numclusteriterations = 64;
+	bsb->welding = 0.f;
 
 	return bsb;
 }
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index ae449843d2a7f668660e46a2e1ee07c48cf59099..d9e005811d0078e16ca68d75d86331c87566dbf3 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
+#include <assert.h>
 
 #include "BKE_bvhutils.h"
 
@@ -45,6 +46,8 @@
 #include "BKE_global.h"
 
 #include "BLI_arithb.h"
+#include "BLI_linklist.h"
+#include "MEM_guardedalloc.h"
 
 /* Math stuff for ray casting on mesh faces and for nearest surface */
 
@@ -480,30 +483,47 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
  * BVH builders
  */
 // Builds a bvh tree.. where nodes are the vertexs of the given mesh
-void bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
+BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
 {
-	int i;
-	int numVerts= mesh->getNumVerts(mesh);
-	MVert *vert	= mesh->getVertDataArray(mesh, CD_MVERT);
-	BVHTree *tree = NULL;
+	BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_VERTICES);
 
-	memset(data, 0, sizeof(*data));
+	//Not in cache
+	if(tree == NULL)
+	{
+		int i;
+		int numVerts= mesh->getNumVerts(mesh);
+		MVert *vert	= mesh->getVertDataArray(mesh, CD_MVERT);
 
-	if(vert == NULL)
+		if(vert != NULL)
+		{
+			tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);
+
+			if(tree != NULL)
+			{
+				for(i = 0; i < numVerts; i++)
+					BLI_bvhtree_insert(tree, i, vert[i].co, 1);
+
+				BLI_bvhtree_balance(tree);
+
+				//Save on cache for later use
+//				printf("BVHTree built and saved on cache\n");
+				bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_VERTICES);
+			}
+		}
+	}
+	else
 	{
-		printf("bvhtree cant be build: cant get a vertex array");
-		return;
+//		printf("BVHTree is already build, using cached tree\n");
 	}
 
-	tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);
-	if(tree != NULL)
-	{
-		for(i = 0; i < numVerts; i++)
-			BLI_bvhtree_insert(tree, i, vert[i].co, 1);
 
-		BLI_bvhtree_balance(tree);
+	//Setup BVHTreeFromMesh
+	memset(data, 0, sizeof(*data));
+	data->tree = tree;
 
-		data->tree = tree;
+	if(data->tree)
+	{
+		data->cached = TRUE;
 
 		//a NULL nearest callback works fine
 		//remeber the min distance to point is the same as the min distance to BV of point
@@ -516,43 +536,62 @@ void bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float eps
 
 		data->sphere_radius = epsilon;
 	}
+
+	return data->tree;
 }
 
 // Builds a bvh tree.. where nodes are the faces of the given mesh.
-void bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
+BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
 {
-	int i;
-	int numFaces= mesh->getNumFaces(mesh);
-	MVert *vert	= mesh->getVertDataArray(mesh, CD_MVERT);
-	MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
-	BVHTree *tree = NULL;
-
-	memset(data, 0, sizeof(*data));
+	BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_FACES);
 
-	if(vert == NULL && face == NULL)
+	//Not in cache
+	if(tree == NULL)
 	{
-		printf("bvhtree cant be build: cant get a vertex/face array");
-		return;
-	}
+		int i;
+		int numFaces= mesh->getNumFaces(mesh);
+		MVert *vert	= mesh->getVertDataArray(mesh, CD_MVERT);
+		MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
 
-	/* Create a bvh-tree of the given target */
-	tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
-	if(tree != NULL)
-	{
-		for(i = 0; i < numFaces; i++)
+		if(vert != NULL && face != NULL)
 		{
-			float co[4][3];
-			VECCOPY(co[0], vert[ face[i].v1 ].co);
-			VECCOPY(co[1], vert[ face[i].v2 ].co);
-			VECCOPY(co[2], vert[ face[i].v3 ].co);
-			if(face[i].v4)
-				VECCOPY(co[3], vert[ face[i].v4 ].co);
+			/* Create a bvh-tree of the given target */
+			tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
+			if(tree != NULL)
+			{
+				for(i = 0; i < numFaces; i++)
+				{
+					float co[4][3];
+					VECCOPY(co[0], vert[ face[i].v1 ].co);
+					VECCOPY(co[1], vert[ face[i].v2 ].co);
+					VECCOPY(co[2], vert[ face[i].v3 ].co);
+					if(face[i].v4)
+						VECCOPY(co[3], vert[ face[i].v4 ].co);
 			
-			BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+					BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+				}
+				BLI_bvhtree_balance(tree);
+
+				//Save on cache for later use
+//				printf("BVHTree built and saved on cache\n");
+				bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_FACES);
+			}
 		}
-		BLI_bvhtree_balance(tree);
+	}
+	else
+	{
+//		printf("BVHTree is already build, using cached tree\n");
+	}
+
+
+	//Setup BVHTreeFromMesh
+	memset(data, 0, sizeof(*data));
+	data->tree = tree;
+
+	if(data->tree)
+	{
+		data->cached = TRUE;
 
-		data->tree = tree;
 		data->nearest_callback = mesh_faces_nearest_point;
 		data->raycast_callback = mesh_faces_spherecast;
 
@@ -562,6 +601,8 @@ void bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float eps
 
 		data->sphere_radius = epsilon;
 	}
+	return data->tree;
+
 }
 
 // Frees data allocated by a call to bvhtree_from_mesh_*.
@@ -569,9 +610,78 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
 {
 	if(data->tree)
 	{
-		BLI_bvhtree_free(data->tree);
+		if(!data->cached)
+			BLI_bvhtree_free(data->tree);
+
 		memset( data, 0, sizeof(data) );
 	}
 }
 
 
+/* BVHCache */
+typedef struct BVHCacheItem
+{
+	int type;
+	BVHTree *tree;
+
+} BVHCacheItem;
+
+static void bvhcacheitem_set_if_match(void *_cached, void *_search)
+{
+	BVHCacheItem * cached = (BVHCacheItem *)_cached;
+	BVHCacheItem * search = (BVHCacheItem *)_search;
+
+	if(search->type == cached->type)
+	{
+		search->tree = cached->tree;		
+	}
+} 
+
+BVHTree *bvhcache_find(BVHCache *cache, int type)
+{
+	BVHCacheItem item;
+	item.type = type;
+	item.tree = NULL;
+
+	BLI_linklist_apply(*cache, bvhcacheitem_set_if_match, &item);
+	return item.tree;
+}
+
+void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type)
+{
+	BVHCacheItem *item = NULL;
+
+	assert( tree != NULL );
+	assert( bvhcache_find(cache, type) == NULL );
+
+	item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem");
+	assert( item != NULL );
+
+	item->type = type;
+	item->tree = tree;
+
+	BLI_linklist_prepend( cache, item );
+}
+
+
+void bvhcache_init(BVHCache *cache)
+{
+	*cache = NULL;
+}
+
+static void bvhcacheitem_free(void *_item)
+{
+	BVHCacheItem *item = (BVHCacheItem *)_item;
+
+	BLI_bvhtree_free(item->tree);
+	MEM_freeN(item);
+}
+
+
+void bvhcache_free(BVHCache *cache)
+{
+	BLI_linklist_free(*cache, (LinkNodeFreeFP)bvhcacheitem_free);
+	*cache = NULL;
+}
+
+
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index b668a1f214db8864b8e794f9eabaf2a612c059c7..6b6f4a58e79691ee1539caad0418cae471b2e4ba 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -40,6 +40,7 @@
 
 #include "DNA_armature_types.h"
 #include "DNA_constraint_types.h"
+#include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_action_types.h"
 #include "DNA_curve_types.h"
@@ -63,6 +64,7 @@
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_idprop.h"
+#include "BKE_shrinkwrap.h"
 
 #ifndef DISABLE_PYTHON
 #include "BPY_extern.h"
@@ -540,6 +542,7 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
 	float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3];
 	float imat[3][3], tmat[3][3];
 	int dgroup;
+	short freeDM = 0;
 	
 	/* initialize target matrix using target matrix */
 	Mat4CpyMat4(mat, ob->obmat);
@@ -552,10 +555,19 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
 	if ((G.obedit == ob) && (G.editMesh)) {
 		/* target is in editmode, so get a special derived mesh */
 		dm = CDDM_from_editmesh(G.editMesh, ob->data);
+		freeDM= 1;
 	}
 	else {
-		/* when not in EditMode, this should exist */
-		dm = (DerivedMesh *)ob->derivedFinal;
+		/* when not in EditMode, use the 'final' derived mesh 
+		 *	- check if the custom data masks for derivedFinal mean that we can just use that
+		 *	  (this is more effficient + sufficient for most cases)
+		 */
+		if (ob->lastDataMask != CD_MASK_DERIVEDMESH) {
+			dm = mesh_get_derived_final(ob, CD_MASK_DERIVEDMESH);
+			freeDM= 1;
+		}
+		else 
+			dm = (DerivedMesh *)ob->derivedFinal;
 	}
 	
 	/* only continue if there's a valid DerivedMesh */
@@ -620,10 +632,9 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
 		}
 	}
 	
-	/* free temporary DerivedMesh created (in EditMode case) */
-	if (G.editMesh) {
-		if (dm) dm->release(dm);
-	}
+	/* free temporary DerivedMesh created */
+	if (dm && freeDM) 
+		dm->release(dm);
 }
 
 /* function that sets the given matrix based on given vertex group in lattice */
@@ -3230,6 +3241,165 @@ static bConstraintTypeInfo CTI_TRANSFORM = {
 	transform_evaluate /* evaluate */
 };
 
+/* ---------- Shrinkwrap Constraint ----------- */
+
+static int shrinkwrap_get_tars (bConstraint *con, ListBase *list)
+{
+	if (con && list) {
+		bShrinkwrapConstraint *data = con->data;
+		bConstraintTarget *ct;
+		
+		SINGLETARGETNS_GET_TARS(con, data->target, ct, list)
+		
+		return 1;
+	}
+	
+	return 0;
+}
+
+
+static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+	if (con && list) {
+		bShrinkwrapConstraint *data = con->data;
+		bConstraintTarget *ct= list->first;
+		
+		SINGLETARGETNS_FLUSH_TARS(con, data->target, ct, list, nocopy)
+	}
+}
+
+
+static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+	bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
+	
+	if( VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) )
+	{
+		int fail = FALSE;
+		float co[3] = {0.0f, 0.0f, 0.0f};
+		float no[3] = {0.0f, 0.0f, 0.0f};
+		float dist;
+
+		SpaceTransform transform;
+		DerivedMesh *target = object_get_derived_final(ct->tar, CD_MASK_BAREMESH);
+		BVHTreeRayHit hit;
+		BVHTreeNearest nearest;
+
+		BVHTreeFromMesh treeData;
+		memset( &treeData, 0, sizeof(treeData) );
+
+		nearest.index = -1;
+		nearest.dist = FLT_MAX;
+
+		hit.index = -1;
+		hit.dist = 100000.0f;  //TODO should use FLT_MAX.. but normal projection doenst yet supports it
+
+		Mat4One(ct->matrix);
+
+		if(target != NULL)
+		{
+			space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat);
+
+			switch(scon->shrinkType)
+			{
+				case MOD_SHRINKWRAP_NEAREST_SURFACE:
+				case MOD_SHRINKWRAP_NEAREST_VERTEX:
+
+					if(scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX)
+						bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6);
+					else
+						bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6);
+
+					if(treeData.tree == NULL)
+					{
+						fail = TRUE;
+						break;
+					}
+
+					space_transform_apply(&transform, co);
+
+					BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
+					
+					dist = VecLenf(co, nearest.co);
+					VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist);	/* linear interpolation */
+					space_transform_invert(&transform, co);
+				break;
+
+				case MOD_SHRINKWRAP_PROJECT:
+					if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) no[0] = 1.0f;
+					if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) no[1] = 1.0f;
+					if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) no[2] = 1.0f;
+
+					if(INPR(no,no) < FLT_EPSILON)
+					{
+						fail = TRUE;
+						break;
+					}
+
+					Normalize(no);
+
+
+					bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6);
+					if(treeData.tree == NULL)
+					{
+						fail = TRUE;
+						break;
+					}
+
+					if(normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE)
+					{
+						fail = TRUE;
+						break;
+					}
+					VECCOPY(co, hit.co);
+				break;
+			}
+
+			free_bvhtree_from_mesh(&treeData);
+
+			target->release(target);
+
+			if(fail == TRUE)
+			{
+				/* Don't move the point */
+				co[0] = co[1] = co[2] = 0.0f;
+			}
+
+			/* co is in local object coordinates, change it to global and update target position */
+			VecMat4MulVecfl(co, cob->matrix, co);
+			VECCOPY(ct->matrix[3], co);
+		}
+	}
+}
+
+static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+	bConstraintTarget *ct= targets->first;
+	
+	/* only evaluate if there is a target */
+	if (VALID_CONS_TARGET(ct))
+	{
+		VECCOPY(cob->matrix[3], ct->matrix[3]);
+	}
+}
+
+static bConstraintTypeInfo CTI_SHRINKWRAP = {
+	CONSTRAINT_TYPE_SHRINKWRAP, /* type */
+	sizeof(bShrinkwrapConstraint), /* size */
+	"Shrinkwrap", /* name */
+	"bShrinkwrapConstraint", /* struct name */
+	NULL, /* free data */
+	NULL, /* relink data */
+	NULL, /* copy data */
+	NULL, /* new data */
+	shrinkwrap_get_tars, /* get constraint targets */
+	shrinkwrap_flush_tars, /* flush constraint targets */
+	shrinkwrap_get_tarmat, /* get a target matrix */
+	shrinkwrap_evaluate /* evaluate */
+};
+
+
+
 /* ************************* Constraints Type-Info *************************** */
 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
  * and operations that involve constraint specifc code.
@@ -3261,6 +3431,7 @@ static void constraints_init_typeinfo () {
 	constraintsTypeInfo[17]= &CTI_RIGIDBODYJOINT;	/* RigidBody Constraint */
 	constraintsTypeInfo[18]= &CTI_CLAMPTO; 			/* ClampTo Constraint */	
 	constraintsTypeInfo[19]= &CTI_TRANSFORM;		/* Transformation Constraint */
+	constraintsTypeInfo[20]= &CTI_SHRINKWRAP;		/* Shrinkwrap Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only
@@ -3380,6 +3551,8 @@ void copy_constraints (ListBase *dst, ListBase *src)
 		/* make a new copy of the constraint's data */
 		con->data = MEM_dupallocN(con->data);
 		
+		id_us_plus((ID *)con->ipo);
+		
 		/* only do specific constraints if required */
 		if (cti && cti->copy_data)
 			cti->copy_data(con, srccon);
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 05271aa59a7a2ebb645d55d50d43c123af7875c8..6d5b86fa874ba6e2ac8ddb80265b6e60d3b4b208 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -626,7 +626,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
 			number++;
 
 		if(layer->flag & CD_FLAG_NOCOPY) continue;
-		else if(!(mask & (1 << type))) continue;
+		else if(!((int)mask & (int)(1 << (int)type))) continue;
 		else if(number < CustomData_number_of_layers(dest, type)) continue;
 
 		if((alloctype == CD_ASSIGN) && (layer->flag & CD_FLAG_NOFREE))
@@ -1144,7 +1144,7 @@ void CustomData_set_only_copy(const struct CustomData *data,
 	int i;
 
 	for(i = 0; i < data->totlayer; ++i)
-		if(!(mask & (1 << data->layers[i].type)))
+		if(!((int)mask & (int)(1 << (int)data->layers[i].type)))
 			data->layers[i].flag |= CD_FLAG_NOCOPY;
 }
 
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 7716d71225eb9d76889b7bf785ed68fae63e7348..91eea56c9e75f76defc6260bd23d718083916875 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -937,7 +937,7 @@ void filldisplist(ListBase *dispbase, ListBase *to)
 	DispList *dlnew=0, *dl;
 	float *f1;
 	int colnr=0, charidx=0, cont=1, tot, a, *index;
-	long totvert;
+	intptr_t totvert;
 	
 	if(dispbase==0) return;
 	if(dispbase->first==0) return;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 0338ec92414ab4f4ba5c4b1770df87f5bc8d532c..cca5d68167e74084b2fe0aed94a02a938cb2a822 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -298,24 +298,22 @@ static float wind_func(struct RNG *rng, float strength)
 	return ret;
 }
 
-
+/* maxdist: zero effect from this distance outwards (if usemax) */
+/* mindist: full effect up to this distance (if usemin) */
+/* power: falloff with formula 1/r^power */
 static float falloff_func(float fac, int usemin, float mindist, int usemax, float maxdist, float power)
 {
-	if(!usemin)
-		mindist= 0.0f;
+	/* first quick checks */
+	if(usemax && fac > maxdist)
+		return 0.0f;
 
-	if(fac < mindist) {
+	if(usemin && fac < mindist)
 		return 1.0f;
-	}
-	else if(usemax) {
-		if(fac>maxdist || (maxdist-mindist)<=0.0f)
-			return 0.0f;
 
-		fac= (fac-mindist)/(maxdist-mindist);
-		return 1.0f - (float)pow((double)fac, (double)power);
-	}
-	else
-		return pow((double)1.0f+fac-mindist, (double)-power);
+	if(!usemin)
+		mindist = 0.0;
+
+	return pow((double)1.0+fac-mindist, (double)-power);
 }
 
 static float falloff_func_dist(PartDeflect *pd, float fac)
@@ -442,14 +440,11 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
 			else
 				VecCopyf(mag_vec,vec_to_part);
 
-			Normalize(mag_vec);
-
 			VecMulf(mag_vec,force_val*falloff);
 			VecSubf(field,field,mag_vec);
 
 			VecCopyf(mag_vec,velocity);
-			/* 1.9 is an experimental value to get critical damping at damp=1.0 */
-			VecMulf(mag_vec,damp*1.9f*(float)sqrt(force_val));
+			VecMulf(mag_vec,damp*2.0f*(float)sqrt(force_val));
 			VecSubf(field,field,mag_vec);
 			break;
 		case PFIELD_CHARGE:
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
index ee3fd59fe9fd5c6cf6cd042c55b9d9a017a3e085..76ad0cf07c39d5223b194bfeda62971df497a71a 100644
--- a/source/blender/blenkernel/intern/exotic.c
+++ b/source/blender/blenkernel/intern/exotic.c
@@ -1131,7 +1131,7 @@ static int iv_finddata(struct IvNode *iv, char *field, int fieldnr)
 	float *fp;
 	int len, stackcount, skipdata=0;
 	char *cpa, terminator, str[64];
-	long i;
+	intptr_t i;
 	
 	len= strlen(field);
 
@@ -2592,7 +2592,7 @@ static void write_videoscape_mesh(Object *ob, char *str)
 	unsigned int kleur[32];
 	float co[3];
 	int a;
-	long tot;
+	intptr_t tot;
 	char *cp;
 	
 	if(ob && ob->type==OB_MESH);
@@ -2642,17 +2642,17 @@ static void write_videoscape_mesh(Object *ob, char *str)
 
 			if(evl->v4==0) {
 				fprintf(fp, "3 %ld %ld %ld 0x%x\n", 
-						(long int) evl->v1->tmp.l,
-						(long int) evl->v2->tmp.l,
-						(long int) evl->v3->tmp.l, 
+						(intptr_t) evl->v1->tmp.l,
+						(intptr_t) evl->v2->tmp.l,
+						(intptr_t) evl->v3->tmp.l, 
 						kleur[evl->mat_nr]);
 			}
 			else {
 				fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", 
-						(long int) evl->v1->tmp.l, 
-						(long int) evl->v2->tmp.l, 
-						(long int) evl->v3->tmp.l, 
-						(long int) evl->v4->tmp.l, 
+						(intptr_t) evl->v1->tmp.l, 
+						(intptr_t) evl->v2->tmp.l, 
+						(intptr_t) evl->v3->tmp.l, 
+						(intptr_t) evl->v4->tmp.l, 
 						kleur[evl->mat_nr]);
 			}
 			evl= evl->next;
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 52275e507dde916be38794beef77814408a613c6..45b52f5af8e350611d68c025bb63e3f523fdf7ac 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -1131,7 +1131,7 @@ struct chartrans *text_to_curve(Object *ob, int mode)
 		ct= chartransdata;
 		if (cu->sepchar==0) {
 		for (i= 0; i<slen; i++) {
-			cha = (unsigned long) mem[i];
+			cha = (uintptr_t) mem[i];
 			info = &(cu->strinfo[i]);
 			if (info->mat_nr > (ob->totcol)) {
 				/* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index e817c38618f3a2e389e7fe7202675aa2553d64db..444c7c080ea1df59ac1c7e7fb206e42f2b5b2718 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -407,7 +407,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int floatbuf, sho
 	unsigned char *rect= NULL;
 	float *rect_float= NULL;
 	int x, y;
-	int checkerwidth=21, dark=1;
+	int checkerwidth=32, dark=1;
 	
 	if (floatbuf) {
 		ibuf= IMB_allocImBuf(width, height, 24, IB_rectfloat, 0);
@@ -640,6 +640,11 @@ static uintptr_t image_mem_size(Image *ima)
 	uintptr_t size = 0;
 
 	size= 0;
+	
+	/* viewers have memory depending on other rules, has no valid rect pointer */
+	if(ima->source==IMA_SRC_VIEWER)
+		return 0;
+	
 	for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) {
 		if(ibuf->rect) size += MEM_allocN_len(ibuf->rect);
 		else if(ibuf->rect_float) size += MEM_allocN_len(ibuf->rect_float);
@@ -1024,7 +1029,7 @@ static void stampdata(StampData *stamp_data, int do_prefix)
 	}
 	
 	if (G.scene->r.stamp & R_STAMP_SEQSTRIP) {
-		Sequence *seq = get_forground_frame_seq(CFRA);
+		Sequence *seq = get_foreground_frame_seq(CFRA);
 	
 		if (seq) strcpy(text, seq->name+2);
 		else 		strcpy(text, "<none>");
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 29db0ddd808bb7f30d8c0e284989dba55b0dccfa..0077cf95262dd091b3acc314be1e333539cc752b 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -2876,7 +2876,7 @@ float IPO_GetFloatValue (Ipo *ipo, IPO_Channel channel, float ctime)
 	calc_ipo_spec(ipo, channel, &ctime);
 	
 	/* unapply rotation hack, as gameengine doesn't use it */
-	if ((OB_ROT_X <= channel) && (channel <= OB_DROT_Z))
+	if ((ipo->blocktype == ID_OB) && (OB_ROT_X <= channel) && (channel <= OB_DROT_Z))
 		ctime *= (float)(M_PI_2/9.0); 
 
 	/* return the value of this channel */
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index b3892a515af70629931003f90de1ba418cb5c9fa..c9f6bc18abd39bb2018bace1e1e319a506ec9feb 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -6016,6 +6016,80 @@ static void collisionModifier_deformVerts(
 }
 
 
+
+/* Surface */
+
+static void surfaceModifier_initData(ModifierData *md) 
+{
+	SurfaceModifierData *surmd = (SurfaceModifierData*) md;
+	
+	surmd->bvhtree = NULL;
+}
+
+static void surfaceModifier_freeData(ModifierData *md)
+{
+	SurfaceModifierData *surmd = (SurfaceModifierData*) md;
+	
+	if (surmd)
+	{
+		if(surmd->bvhtree) {
+			free_bvhtree_from_mesh(surmd->bvhtree);
+			MEM_freeN(surmd->bvhtree);
+		}
+
+		surmd->dm->release(surmd->dm);
+		
+		surmd->bvhtree = NULL;
+		surmd->dm = NULL;
+	}
+}
+
+static int surfaceModifier_dependsOnTime(ModifierData *md)
+{
+	return 1;
+}
+
+static void surfaceModifier_deformVerts(
+					  ModifierData *md, Object *ob, DerivedMesh *derivedData,
+       float (*vertexCos)[3], int numVerts)
+{
+	SurfaceModifierData *surmd = (SurfaceModifierData*) md;
+	unsigned int numverts = 0, i = 0;
+	
+	if(surmd->dm)
+		surmd->dm->release(surmd->dm);
+
+	/* if possible use/create DerivedMesh */
+	if(derivedData) surmd->dm = CDDM_copy(derivedData);
+	else if(ob->type==OB_MESH) surmd->dm = CDDM_from_mesh(ob->data, ob);
+	
+	if(!ob->pd)
+	{
+		printf("surfaceModifier_deformVerts: Should not happen!\n");
+		return;
+	}
+	
+	if(surmd->dm)
+	{
+		CDDM_apply_vert_coords(surmd->dm, vertexCos);
+		CDDM_calc_normals(surmd->dm);
+		
+		numverts = surmd->dm->getNumVerts ( surmd->dm );
+
+		/* convert to global coordinates */
+		for(i = 0; i<numverts; i++)
+			Mat4MulVecfl(ob->obmat, CDDM_get_vert(surmd->dm, i)->co);
+
+		if(surmd->bvhtree)
+			free_bvhtree_from_mesh(surmd->bvhtree);
+		else
+			surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");
+
+		bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
+	}
+}
+
+
 /* Boolean */
 
 static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
@@ -6064,22 +6138,44 @@ static DerivedMesh *booleanModifier_applyModifier(
 {
 	// XXX doesn't handle derived data
 	BooleanModifierData *bmd = (BooleanModifierData*) md;
+	DerivedMesh *dm = mesh_get_derived_final(bmd->object, CD_MASK_BAREMESH);
 
 	/* we do a quick sanity check */
-	if(((Mesh *)ob->data)->totface > 3
-		    && bmd->object && ((Mesh *)bmd->object->data)->totface > 3) {
-		DerivedMesh *result = NewBooleanDerivedMesh(bmd->object, ob,
+	if(dm && (derivedData->getNumFaces(derivedData) > 3)
+		    && bmd->object && dm->getNumFaces(dm) > 3) {
+		DerivedMesh *result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
 				1 + bmd->operation);
 
+		if(dm)
+			dm->release(dm);
+
 		/* if new mesh returned, return it; otherwise there was
 		* an error, so delete the modifier object */
 		if(result)
 			return result;
 		else
 			bmd->object = NULL;
-		    }
+	}
+	
+	if(dm)
+			dm->release(dm);
 
-		    return derivedData;
+	return derivedData;
+}
+
+CustomDataMask booleanModifier_requiredDataMask(ModifierData *md)
+{
+	CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE);
+
+	dataMask |= (1 << CD_MDEFORMVERT);
+	
+	/* particles only need this if they are after a non deform modifier, and
+	* the modifier stack will only create them in that case. */
+// 	dataMask |= CD_MASK_ORIGSPACE;
+
+// 	dataMask |= CD_MASK_ORCO;
+	
+	return dataMask;
 }
 
 /* Particles */
@@ -6160,6 +6256,48 @@ static int is_last_displist(Object *ob)
 
 	return 0;
 }
+
+static DerivedMesh *get_original_dm(Object *ob, float (*vertexCos)[3], int orco)
+{
+	DerivedMesh *dm= NULL;
+
+	if(ob->type==OB_MESH) {
+		dm = CDDM_from_mesh((Mesh*)(ob->data), ob);
+
+		if(vertexCos) {
+			CDDM_apply_vert_coords(dm, vertexCos);
+			//CDDM_calc_normals(dm);
+		}
+		
+		if(orco)
+			DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
+	}
+	else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) {
+		Object *tmpobj;
+		Curve *tmpcu;
+
+		if(is_last_displist(ob)) {
+			/* copies object and modifiers (but not the data) */
+			tmpobj= copy_object(ob);
+			tmpcu = (Curve *)tmpobj->data;
+			tmpcu->id.us--;
+
+			/* copies the data */
+			tmpobj->data = copy_curve((Curve *) ob->data);
+
+			makeDispListCurveTypes(tmpobj, 1);
+			nurbs_to_mesh(tmpobj);
+
+			dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj);
+			//CDDM_calc_normals(dm);
+
+			free_libblock_us(&G.main->object, tmpobj);
+		}
+	}
+
+	return dm;
+}
+
 /* saves the current emitter state for a particle system and calculates particles */
 static void particleSystemModifier_deformVerts(
 					       ModifierData *md, Object *ob, DerivedMesh *derivedData,
@@ -6187,43 +6325,13 @@ static void particleSystemModifier_deformVerts(
 	if(!psys_check_enabled(ob, psys))
 		return;
 
-	if(dm==0){
-		if(ob->type==OB_MESH){
-			dm = CDDM_from_mesh((Mesh*)(ob->data), ob);
-
-			CDDM_apply_vert_coords(dm, vertexCos);
-			//CDDM_calc_normals(dm);
-			
-			DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
-
-			needsFree=1;
-		}
-		else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)){
-			Object *tmpobj;
-			Curve *tmpcu;
-
-			if(is_last_displist(ob)){
-				/* copies object and modifiers (but not the data) */
-				tmpobj= copy_object( ob );
-				tmpcu = (Curve *)tmpobj->data;
-				tmpcu->id.us--;
-
-				/* copies the data */
-				tmpobj->data = copy_curve( (Curve *) ob->data );
-
-				makeDispListCurveTypes( tmpobj, 1 );
-				nurbs_to_mesh( tmpobj );
+	if(dm==0) {
+		dm= get_original_dm(ob, vertexCos, 1);
 
-				dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj);
-				//CDDM_calc_normals(dm);
-
-				free_libblock_us( &G.main->object, tmpobj );
+		if(!dm)
+			return;
 
-				needsFree=1;
-			}
-			else return;
-		}
-		else return;
+		needsFree= 1;
 	}
 
 	/* clear old dm */
@@ -7193,7 +7301,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
 			pa= pars+i;
 
 			/* get particle state */
-			psys_particle_on_emitter(psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,loc0,nor,0,0,0,0);
+			psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc0,nor,0,0,0,0);
 			Mat4MulVecfl(ob->obmat,loc0);
 
 			state.time=cfra;
@@ -7249,7 +7357,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
 
 		*mf = source;
 
-		test_index_face(mf, &explode->faceData, i, (mf->v4 ? 4 : 3));
+		test_index_face(mf, &explode->faceData, i, (orig_v4 ? 4 : 3));
 	}
 
 	MEM_printmemlist_stats();
@@ -7560,6 +7668,14 @@ static void meshdeformModifier_do(
 	}
 	else
 		cagedm= mmd->object->derivedFinal;
+
+	/* if we don't have one computed, use derivedmesh from data
+	 * without any modifiers */
+	if(!cagedm) {
+		cagedm= get_original_dm(mmd->object, NULL, 0);
+		if(cagedm)
+			cagedm->needsFree= 1;
+	}
 	
 	if(!cagedm)
 		return;
@@ -7799,7 +7915,7 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived
 		else if(ob->type==OB_LATTICE) dm = NULL;
 		else return;
 
-		if(dm != NULL && (dataMask & CD_MVERT))
+		if(dm != NULL && (dataMask & (1<<CD_MVERT)))
 		{
 			CDDM_apply_vert_coords(dm, vertexCos);
 			CDDM_calc_normals(dm);
@@ -7824,7 +7940,7 @@ static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditM
 		else if(ob->type==OB_LATTICE) dm = NULL;
 		else return;
 
-		if(dm != NULL && (dataMask & CD_MVERT))
+		if(dm != NULL && (dataMask & (1<<CD_MVERT)))
 		{
 			CDDM_apply_vert_coords(dm, vertexCos);
 			CDDM_calc_normals(dm);
@@ -8217,16 +8333,24 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
 		mti->deformVerts = collisionModifier_deformVerts;
 		// mti->copyData = collisionModifier_copyData;
 
+		mti = INIT_TYPE(Surface);
+		mti->type = eModifierTypeType_OnlyDeform;
+		mti->initData = surfaceModifier_initData;
+		mti->flags = eModifierTypeFlag_AcceptsMesh;
+		mti->dependsOnTime = surfaceModifier_dependsOnTime;
+		mti->freeData = surfaceModifier_freeData; 
+		mti->deformVerts = surfaceModifier_deformVerts;
+
 		mti = INIT_TYPE(Boolean);
 		mti->type = eModifierTypeType_Nonconstructive;
 		mti->flags = eModifierTypeFlag_AcceptsMesh
-				| eModifierTypeFlag_RequiresOriginalData
 				| eModifierTypeFlag_UsesPointCache;
 		mti->copyData = booleanModifier_copyData;
 		mti->isDisabled = booleanModifier_isDisabled;
 		mti->applyModifier = booleanModifier_applyModifier;
 		mti->foreachObjectLink = booleanModifier_foreachObjectLink;
 		mti->updateDepgraph = booleanModifier_updateDepgraph;
+		mti->requiredDataMask = booleanModifier_requiredDataMask;
 
 		mti = INIT_TYPE(MeshDeform);
 		mti->type = eModifierTypeType_OnlyDeform;
@@ -8740,8 +8864,10 @@ void modifier_freeTemporaryData(ModifierData *md)
 	if(md->type == eModifierType_Armature) {
 		ArmatureModifierData *amd= (ArmatureModifierData*)md;
 
-		if(amd->prevCos)
+		if(amd->prevCos) {
 			MEM_freeN(amd->prevCos);
+			amd->prevCos= NULL;
+		}
 	}
 }
 
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 4d312632b1a8645880d57fca706d0d02f9fb0d63..ee9255df837ada3a9d1309355a29adb59aec41e9 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -111,7 +111,8 @@ void multires_free(Multires *mr)
 			lvl= lvl->next;
 		}
 
-		MEM_freeN(mr->verts);
+		if(mr->verts)
+			MEM_freeN(mr->verts);
 
 		BLI_freelistN(&mr->levels);
 
@@ -965,9 +966,9 @@ void multires_update_levels(Mesh *me, const int render)
 	multires_update_colors(me, em);
 }
 
-static void check_colors(Mesh *me)
+static void check_colors(Mesh *me, const int render)
 {
-	CustomData *src= G.obedit ? &G.editMesh->fdata : &me->fdata;
+	CustomData *src= (!render && G.obedit)? &G.editMesh->fdata : &me->fdata;
 	const char col= CustomData_has_layer(src, CD_MCOL);
 
 	/* Check if vertex colors have been deleted or added */
@@ -1109,7 +1110,7 @@ void multires_add_level(Object *ob, Mesh *me, const char subdiv_type)
 	lvl= MEM_callocN(sizeof(MultiresLevel), "multireslevel");
 	if(me->pv) mesh_pmv_off(ob, me);
 
-	check_colors(me);
+	check_colors(me, 0);
 	multires_update_levels(me, 0);
 
 	++me->mr->level_count;
@@ -1275,7 +1276,7 @@ void multires_set_level(Object *ob, Mesh *me, const int render)
 {
 	if(me->pv) mesh_pmv_off(ob, me);
 
-	check_colors(me);
+	check_colors(me, render);
 	multires_update_levels(me, render);
 
 	me->mr->current= me->mr->newlvl;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 9a78f8ea02aa1ebea941f3888ed2f23c2a7d8cc2..413c2fc20f591417dbcc301e69e72733aba1f0a4 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1644,7 +1644,8 @@ void ntreeSolveOrder(bNodeTree *ntree)
 		might be different for editor or for "real" use... */
 }
 
-/* should be callback! */
+/* Should be callback! */
+/* Do not call execs here */
 void NodeTagChanged(bNodeTree *ntree, bNode *node)
 {
 	if(ntree->type==NTREE_COMPOSIT) {
@@ -1664,8 +1665,6 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node)
 		}
 		node->need_exec= 1;
 	}
-	else if(ntree->type == NTREE_TEXTURE)
-		ntreeTexUpdatePreviews(ntree);
 }
 
 void NodeTagIDChanged(bNodeTree *ntree, ID *id)
@@ -1983,9 +1982,9 @@ static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack)
 	}
 }
 
+/* notes below are ancient! (ton) */
 /* stack indices make sure all nodes only write in allocated data, for making it thread safe */
 /* only root tree gets the stack, to enable instances to have own stack entries */
-/* only two threads now! */
 /* per tree (and per group) unique indices are created */
 /* the index_ext we need to be able to map from groups to the group-node own stack */
 
@@ -2000,14 +1999,9 @@ static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread)
 	ListBase *lb= &ntree->threadstack[thread];
 	bNodeThreadStack *nts;
 	
-	/* for material shading this is called quite a lot (perhaps too much locking unlocking)
-	 * however without locking we get bug #18058 - Campbell */
-	BLI_lock_thread(LOCK_CUSTOM1); 
-	
 	for(nts=lb->first; nts; nts=nts->next) {
 		if(!nts->used) {
 			nts->used= 1;
-			BLI_unlock_thread(LOCK_CUSTOM1);
 			return nts;
 		}
 	}
@@ -2015,7 +2009,7 @@ static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread)
 	nts->stack= MEM_dupallocN(ntree->stack);
 	nts->used= 1;
 	BLI_addtail(lb, nts);
-	BLI_unlock_thread(LOCK_CUSTOM1);
+
 	return nts;
 }
 
@@ -2067,6 +2061,11 @@ void ntreeBeginExecTree(bNodeTree *ntree)
 		/* tag used outputs, so we know when we can skip operations */
 		for(node= ntree->nodes.first; node; node= node->next) {
 			bNodeSocket *sock;
+			
+			/* composite has own need_exec tag handling */
+			if(ntree->type!=NTREE_COMPOSIT)
+				node->need_exec= 1;
+
 			for(sock= node->inputs.first; sock; sock= sock->next) {
 				if(sock->link) {
 					ns= ntree->stack + sock->link->fromsock->stack_index;
@@ -2075,9 +2074,22 @@ void ntreeBeginExecTree(bNodeTree *ntree)
 				}
 				else
 					sock->ns.sockettype= sock->type;
+				
+				if(sock->link) {
+					bNodeLink *link= sock->link;
+					/* this is the test for a cyclic case */
+					if(link->fromnode && link->tonode) {
+						if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF);
+						else {
+							node->need_exec= 0;
+						}
+					}
+				}
 			}
+			
 			if(node->type==NODE_GROUP && node->id)
 				group_tag_used_outputs(node, ntree->stack);
+			
 		}
 		
 		if(ntree->type==NTREE_COMPOSIT)
@@ -2160,13 +2172,15 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
 	}
 	
 	for(node= ntree->nodes.first; node; node= node->next) {
-		if(node->typeinfo->execfunc) {
-			node_get_stack(node, stack, nsin, nsout);
-			node->typeinfo->execfunc(callerdata, node, nsin, nsout);
-		}
-		else if(node->type==NODE_GROUP && node->id) {
-			node_get_stack(node, stack, nsin, nsout);
-			node_group_execute(stack, callerdata, node, nsin, nsout); 
+		if(node->need_exec) {
+			if(node->typeinfo->execfunc) {
+				node_get_stack(node, stack, nsin, nsout);
+				node->typeinfo->execfunc(callerdata, node, nsin, nsout);
+			}
+			else if(node->type==NODE_GROUP && node->id) {
+				node_get_stack(node, stack, nsin, nsout);
+				node_group_execute(stack, callerdata, node, nsin, nsout); 
+			}
 		}
 	}
 
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 0b153c3c065a9b1ec4400d492a55cfcd7c1248bc..bffbcf736720a5d491f7b3c7bb561143bc590180 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1169,6 +1169,9 @@ static void copy_object_pose(Object *obn, Object *ob)
 			 * is changed to object->proxy_from when evaluating the driver. */
 			if(con->ipo && !con->ipo->id.lib) {
 				IpoCurve *icu;
+				
+				con->ipo= copy_ipo(con->ipo);
+				
 				for(icu= con->ipo->curve.first; icu; icu= icu->next) {
 					if(icu->driver && icu->driver->ob==ob)
 						icu->driver->ob= obn;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 4eabb82f6cb9dde4b791a175647abe5cd0cbe87e..0ebdcdf58e0cb051e8b24548a922398186f079f2 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -1461,7 +1461,7 @@ static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, flo
 		case PART_KINK_WAVE:
 			vec[axis]=1.0;
 			if(obmat)
-				Mat4MulVecfl(obmat,vec);
+				Mat4Mul3Vecfl(obmat,vec);
 
 			if(par_rot)
 				QuatMulVecf(par_rot,vec);
@@ -1805,10 +1805,13 @@ void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSys
 	int from=PART_FROM_FACE;
 	totparent=(int)(totchild*part->parents*0.3);
 
+	if(G.rendering && part->child_nbr && part->ren_child_nbr)
+		totparent*=(float)part->child_nbr/(float)part->ren_child_nbr;
+
 	tree=BLI_kdtree_new(totparent);
 
 	for(p=0,cpa=psys->child; p<totparent; p++,cpa++){
-		psys_particle_on_emitter(psmd,from,cpa->num,-1,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
+		psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
 		BLI_kdtree_insert(tree, p, orco, NULL);
 	}
 
@@ -1872,6 +1875,10 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate)
 
 	if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
 		totparent=(int)(totchild*part->parents*0.3);
+		
+		if(G.rendering && part->child_nbr && part->ren_child_nbr)
+			totparent*=(float)part->child_nbr/(float)part->ren_child_nbr;
+
 		/* part->parents could still be 0 so we can't test with totparent */
 		between=1;
 	}
@@ -1904,6 +1911,7 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate)
 	ctx->steps= steps;
 	ctx->totchild= totchild;
 	ctx->totparent= totparent;
+	ctx->parent_pass= 0;
 	ctx->cfra= cfra;
 
 	psys->lattice = psys_get_lattice(ob, psys);
@@ -1941,14 +1949,14 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
 	ParticleCacheKey *state, *par = NULL, *key[4];
 	ParticleData *pa=NULL;
 	ParticleTexture ptex;
-	float *cpa_fuv=0;
+	float *cpa_fuv=0, *par_rot=0;
 	float co[3], orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3];
 	float branch_begin, branch_end, branch_prob, branchfac, rough_rand;
 	float pa_rough1, pa_rough2, pa_roughe;
 	float length, pa_length, pa_clump, pa_kink, pa_effector;
 	float max_length = 1.0f, cur_length = 0.0f;
 	float eff_length, eff_vec[3];
-	int k, cpa_num, guided=0;
+	int k, cpa_num, guided = 0;
 	short cpa_from;
 
 	if(part->flag & PART_BRANCHING) {
@@ -2138,15 +2146,16 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
 		t=(float)k/(float)ctx->steps;
 
 		if(ctx->totparent){
-			if(i>=ctx->totparent)
-				/* this is not threadsafe, but should only happen for
-				 * branching particles particles, which are not threaded */
+			if(i>=ctx->totparent) {
+				/* this is now threadsafe, virtual parents are calculated before rest of children */
 				par = cache[cpa->parent] + k;
+			}
 			else
 				par=0;
 		}
 		else if(cpa->parent>=0){
 			par=pcache[cpa->parent]+k;
+			par_rot = par->rot;
 		}
 
 		/* apply different deformations to the child path */
@@ -2156,7 +2165,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
 
 		if(guided==0){
 			if(part->kink)
-				do_prekink((ParticleKey*)state, (ParticleKey*)par, par->rot, t,
+				do_prekink((ParticleKey*)state, (ParticleKey*)par, par_rot, t,
 				part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat);
 					
 			do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump);
@@ -2255,10 +2264,15 @@ static void *exec_child_path_cache(void *data)
 	ParticleSystem *psys= ctx->psys;
 	ParticleCacheKey **cache= psys->childcache;
 	ChildParticle *cpa;
-	int i, totchild= ctx->totchild;
+	int i, totchild= ctx->totchild, first= 0;
+
+	if(thread->tot > 1){
+		first= ctx->parent_pass? 0 : ctx->totparent;
+		totchild= ctx->parent_pass? ctx->totparent : ctx->totchild;
+	}
 	
-	cpa= psys->child + thread->num;
-	for(i=thread->num; i<totchild; i+=thread->tot, cpa+=thread->tot)
+	cpa= psys->child + first + thread->num;
+	for(i=first+thread->num; i<totchild; i+=thread->tot, cpa+=thread->tot)
 		psys_thread_create_path(thread, cpa, cache[i], i);
 
 	return 0;
@@ -2297,6 +2311,22 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed
 	totthread= pthreads[0].tot;
 
 	if(totthread > 1) {
+
+		/* make virtual child parents thread safe by calculating them first */
+		if(totparent) {
+			BLI_init_threads(&threads, exec_child_path_cache, totthread);
+			
+			for(i=0; i<totthread; i++) {
+				pthreads[i].ctx->parent_pass = 1;
+				BLI_insert_thread(&threads, &pthreads[i]);
+			}
+
+			BLI_end_threads(&threads);
+
+			for(i=0; i<totthread; i++)
+				pthreads[i].ctx->parent_pass = 0;
+		}
+
 		BLI_init_threads(&threads, exec_child_path_cache, totthread);
 
 		for(i=0; i<totthread; i++)
@@ -3495,6 +3525,10 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
 		
 		if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
 			totparent=(int)(totchild*part->parents*0.3);
+			
+			if(G.rendering && part->child_nbr && part->ren_child_nbr)
+				totparent*=(float)part->child_nbr/(float)part->ren_child_nbr;
+			
 			/* part->parents could still be 0 so we can't test with totparent */
 			between=1;
 		}
@@ -3940,4 +3974,4 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
 
 	VECADDFAC(center, bb->vec, xvec, bb->offset[0]);
 	VECADDFAC(center, center, yvec, bb->offset[1]);
-}
\ No newline at end of file
+}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 7bda29ebcaf670d4079a457edae63f37285c5bc8..f74e32acdbfdab98391b89852a3e308a35625835 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -77,6 +77,7 @@
 #include "BKE_mesh.h"
 #include "BKE_modifier.h"
 #include "BKE_scene.h"
+#include "BKE_bvhutils.h"
 
 #include "PIL_time.h"
 
@@ -202,8 +203,11 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart)
 		if(psys->particles->keys)
 			MEM_freeN(psys->particles->keys);
 
-		for(i=0, pa=psys->particles; i<totsaved; i++, pa++)
-			if(pa->keys) pa->keys= NULL;
+		for(i=totsaved, pa=psys->particles+totsaved; i<psys->totpart; i++, pa++)
+			if(pa->keys) {
+				pa->keys= NULL;
+				pa->totkey= 0;
+			}
 
 		for(i=totsaved, pa=psys->particles+totsaved; i<psys->totpart; i++, pa++)
 			if(pa->hair) MEM_freeN(pa->hair);
@@ -1301,7 +1305,8 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
 	MEM_freeN(sum);
 
 	/* for hair, sort by origindex, allows optimizations in rendering */
-	if(part->type == PART_HAIR) {
+	/* however with virtual parents the children need to be in random order */
+	if(part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0)) {
 		COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
 		if(COMPARE_ORIG_INDEX)
 			qsort(index, totpart, sizeof(int), compare_orig_index);
@@ -1615,7 +1620,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps
 
 	NormalQuat(pa->r_rot);
 
-	if(part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){
+	if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){
 		/* any unique random number will do (r_ave[0]) */
 		if(ptex.exist < 0.5*(1.0+pa->r_ave[0]))
 			pa->flag |= PARS_UNEXIST;
@@ -1734,6 +1739,8 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
 		VECSUB(p_vel,pa->r_ve,p_vel);
 		Normalize(p_vel);
 		VecMulf(p_vel,speed);
+
+		VECCOPY(pa->fuv,loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */
 	}
 	else{
 		/* get precise emitter matrix if particle is born */
@@ -2003,7 +2010,6 @@ static void set_keyed_keys(Object *ob, ParticleSystem *psys)
 	Object *kob = ob;
 	ParticleSystem *kpsys = psys;
 	ParticleData *pa;
-	ParticleKey state;
 	int totpart = psys->totpart, i, k, totkeys = psys->totkeyed + 1;
 	float prevtime, nexttime, keyedtime;
 
@@ -2027,10 +2033,11 @@ static void set_keyed_keys(Object *ob, ParticleSystem *psys)
 	}
 	
 	psys->flag &= ~PSYS_KEYED;
-	state.time=-1.0;
 
 	for(k=0; k<totkeys; k++) {
 		for(i=0,pa=psys->particles; i<totpart; i++, pa++) {
+			(pa->keys + k)->time = -1.0; /* use current time */
+
 			if(kpsys->totpart > 0)
 				psys_get_particle_state(kob, kpsys, i%kpsys->totpart, pa->keys + k, 1);
 
@@ -2444,7 +2451,6 @@ void psys_end_effectors(ParticleSystem *psys)
 			
 			if(ec->rng)
 				rng_free(ec->rng);
-			
 		}
 
 		BLI_freelistN(lb);
@@ -2483,7 +2489,12 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo
 				ec->locations=MEM_callocN(totpart*3*sizeof(float),"particle locations");
 
 				for(p=0,pa=psys->particles; p<totpart; p++, pa++){
-					psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0);
+					if(part->from == PART_FROM_PARTICLE) {
+						VECCOPY(loc, pa->fuv);
+					}
+					else
+						psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0);
+
 					Mat4MulVecfl(ob->obmat,loc);
 					ec->distances[p]=VecLenf(loc,vec);
 					VECSUB(loc,loc,vec);
@@ -2536,6 +2547,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
 	ParticleData *epa;
 	ParticleKey estate;
 	PartDeflect *pd;
+	SurfaceModifierData *surmd = NULL;
 	ListBase *lb=&psys->effectors;
 	ParticleEffectorCache *ec;
 	float distance, vec_to_part[3];
@@ -2563,8 +2575,34 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
 				if(psys->part->type!=PART_HAIR && psys->part->integrator)
 					where_is_object_time(eob,cfra);
 
-				/* use center of object for distance calculus */
-				VecSubf(vec_to_part, state->co, eob->obmat[3]);
+				if(pd && pd->flag&PFIELD_SURFACE) {
+					surmd = (SurfaceModifierData *)modifiers_findByType ( eob, eModifierType_Surface );
+				}
+				if(surmd) {
+					/* closest point in the object surface is an effector */
+					BVHTreeNearest nearest;
+					float velocity[3];
+
+					nearest.index = -1;
+					nearest.dist = FLT_MAX;
+
+					/* using velocity corrected location allows for easier sliding over effector surface */
+					VecCopyf(velocity, state->vel);
+					VecMulf(velocity, psys_get_timestep(psys->part));
+					VecAddf(vec_to_part, state->co, velocity);
+
+					BLI_bvhtree_find_nearest(surmd->bvhtree->tree, vec_to_part, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree);
+
+					if(nearest.index != -1) {
+						VecSubf(vec_to_part, state->co, nearest.co);
+					}
+					else
+						vec_to_part[0] = vec_to_part[1] = vec_to_part[2] = 0.0f;
+				}
+				else 
+					/* use center of object for distance calculus */
+					VecSubf(vec_to_part, state->co, eob->obmat[3]);
+
 				distance = VecLength(vec_to_part);
 
 				falloff=effector_falloff(pd,eob->obmat[2],vec_to_part);
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index a50fbf125ad7ae0fdd7e24492d8420a3ab8ea4e4..5def3577218b89ca256f860fcfb84cf987e89008 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -780,3 +780,14 @@ float get_render_aosss_error(RenderData *r, float error)
 		return error;
 }
 
+void free_dome_warp_text(struct Text *txt)
+{
+	Scene *scene;
+
+	scene = G.main->scene.first;
+	while(scene) {
+		if (scene->r.dometext == txt)
+			scene->r.dometext = NULL;
+		scene = scene->id.next;
+	}
+}
\ No newline at end of file
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index ab98fb1f0078c79a915351189aca2d0bdddec291..69ce9f3d5cd9c4a1f43bbc4c6758088af4a07bd6 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -148,6 +148,7 @@ static float squared_dist(const float *a, const float *b)
 void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
 {
 
+	DerivedMesh *ss_mesh	= NULL;
 	ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
 
 	//remove loop dependencies on derived meshs (TODO should this be done elsewhere?)
@@ -158,15 +159,14 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
 	//Configure Shrinkwrap calc data
 	calc.smd = smd;
 	calc.ob = ob;
-	calc.original = dm;
 	calc.numVerts = numVerts;
 	calc.vertexCos = vertexCos;
 
 	//DeformVertex
 	calc.vgroup = get_named_vertexgroup_num(calc.ob, calc.smd->vgroup_name);
-	if(calc.original)
+	if(dm)
 	{
-		calc.dvert = calc.original->getVertDataArray(calc.original, CD_MDEFORMVERT);
+		calc.dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
 	}
 	else if(calc.ob->type == OB_LATTICE)
 	{
@@ -176,17 +176,54 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
 
 	if(smd->target)
 	{
-		//TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array
-		calc.target = CDDM_copy( object_get_derived_final(smd->target, CD_MASK_BAREMESH) );
+		calc.target = object_get_derived_final(smd->target, CD_MASK_BAREMESH);
 
-		//TODO there might be several "bugs" on non-uniform scales matrixs.. because it will no longer be nearest surface, not sphere projection
+		//TODO there might be several "bugs" on non-uniform scales matrixs
+		//because it will no longer be nearest surface, not sphere projection
 		//because space has been deformed
 		space_transform_setup(&calc.local2target, ob, smd->target);
 
-		calc.keepDist = smd->keepDist;	//TODO: smd->keepDist is in global units.. must change to local
+		//TODO: smd->keepDist is in global units.. must change to local
+		calc.keepDist = smd->keepDist;
 	}
 
 
+
+	calc.vgroup = get_named_vertexgroup_num(calc.ob, smd->vgroup_name);
+
+	if(dm != NULL && smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
+	{
+		//Setup arrays to get vertexs positions, normals and deform weights
+		calc.vert   = dm->getVertDataArray(dm, CD_MVERT);
+		calc.dvert  = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+		//Using vertexs positions/normals as if a subsurface was applied 
+		if(smd->subsurfLevels)
+		{
+			SubsurfModifierData ssmd;
+			memset(&ssmd, 0, sizeof(ssmd));
+			ssmd.subdivType	= ME_CC_SUBSURF;		//catmull clark
+			ssmd.levels		= smd->subsurfLevels;	//levels
+
+			ss_mesh = subsurf_make_derived_from_derived(dm, &ssmd, FALSE, NULL, 0, 0);
+
+			if(ss_mesh)
+			{
+				calc.vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT);
+				if(calc.vert)
+				{
+					//TRICKY: this code assumes subsurface will have the transformed original vertices
+					//in their original order at the end of the vert array.
+					calc.vert = calc.vert + ss_mesh->getNumVerts(ss_mesh) - dm->getNumVerts(dm);
+				}
+			}
+
+			//Just to make sure we are not letting any memory behind
+			assert(ssmd.emCache == NULL);
+			assert(ssmd.mCache == NULL);
+		}
+	}
+
 	//Projecting target defined - lets work!
 	if(calc.target)
 	{
@@ -207,8 +244,8 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
 	}
 
 	//free memory
-	if(calc.target)
-		calc.target->release( calc.target );
+	if(ss_mesh)
+		ss_mesh->release(ss_mesh);
 }
 
 /*
@@ -244,8 +281,17 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
 		float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup);
 		if(weight == 0.0f) continue;
 
-		VECCOPY(tmp_co, co);
-		space_transform_apply(&calc->local2target, tmp_co); //Convert the coordinates to the tree coordinates
+
+		//Convert the vertex to tree coordinates
+		if(calc->vert)
+		{
+			VECCOPY(tmp_co, calc->vert[i].co);
+		}
+		else
+		{
+			VECCOPY(tmp_co, co);
+		}
+		space_transform_apply(&calc->local2target, tmp_co);
 
 		//Use local proximity heuristics (to reduce the nearest search)
 		//
@@ -348,172 +394,115 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
 	int i;
 
 	//Options about projection direction
-	const char use_normal    = calc->smd->shrinkOpts;
-	float proj_axis[3] = {0.0f, 0.0f, 0.0f};
-	MVert *vert  = NULL; //Needed in case of vertex normal
-	DerivedMesh* ss_mesh = NULL;
+	const char use_normal	= calc->smd->shrinkOpts;
+	float proj_axis[3]		= {0.0f, 0.0f, 0.0f};
 
 	//Raycast and tree stuff
 	BVHTreeRayHit hit;
-	BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; 	//target
+	BVHTreeFromMesh treeData= NULL_BVHTreeFromMesh;
 
 	//auxiliar target
-	DerivedMesh * aux_mesh = NULL;
-	BVHTreeFromMesh auxData= NULL_BVHTreeFromMesh;
+	DerivedMesh *auxMesh	= NULL;
+	BVHTreeFromMesh auxData	= NULL_BVHTreeFromMesh;
 	SpaceTransform local2aux;
 
-do
-{
+	//If the user doesn't allows to project in any direction of projection axis
+	//then theres nothing todo.
+	if((use_normal & (MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)) == 0)
+		return;
+
 
 	//Prepare data to retrieve the direction in which we should project each vertex
 	if(calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL)
 	{
-		//No Mvert information: jump to "free memory and return" part
-		if(calc->original == NULL) break;
-
-		if(calc->smd->subsurfLevels)
-		{
-			SubsurfModifierData smd;
-			memset(&smd, 0, sizeof(smd));
-			smd.subdivType = ME_CC_SUBSURF;			//catmull clark
-			smd.levels = calc->smd->subsurfLevels;	//levels
-
-			ss_mesh = subsurf_make_derived_from_derived(calc->original, &smd, FALSE, NULL, 0, 0);
-
-			if(ss_mesh)
-			{
-				vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT);
-				if(vert)
-				{
-					//TRICKY: this code assumes subsurface will have the transformed original vertices
-					//in their original order at the end of the vert array.
-					vert = vert
-						 + ss_mesh->getNumVerts(ss_mesh)
-						 - calc->original->getNumVerts(calc->original);
-				}
-			}
-
-			//To make sure we are not letting any memory behind
-			assert(smd.emCache == NULL);
-			assert(smd.mCache == NULL);
-		}
-		else
-			vert = calc->original->getVertDataArray(calc->original, CD_MVERT);
-
-		//Not able to get vert information: jump to "free memory and return" part
-		if(vert == NULL) break;
+		if(calc->vert == NULL) return;
 	}
 	else
 	{
-		//The code supports any axis that is a combination of X,Y,Z.. altought currently UI only allows to set the 3 diferent axis
+		//The code supports any axis that is a combination of X,Y,Z
+		//altought currently UI only allows to set the 3 diferent axis
 		if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) proj_axis[0] = 1.0f;
 		if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) proj_axis[1] = 1.0f;
 		if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) proj_axis[2] = 1.0f;
 
 		Normalize(proj_axis);
 
-		//Invalid projection direction: jump to "free memory and return" part
-		if(INPR(proj_axis, proj_axis) < FLT_EPSILON) break; 
+		//Invalid projection direction
+		if(INPR(proj_axis, proj_axis) < FLT_EPSILON)
+			return; 
 	}
 
-	//If the user doesn't allows to project in any direction of projection axis... then theres nothing todo.
-	if((use_normal & (MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)) == 0)
-		break; //jump to "free memory and return" part
-
-
-	//Build target tree
-	BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6));
-	if(treeData.tree == NULL)
-		break; //jump to "free memory and return" part
-
-
-	//Build auxiliar target
 	if(calc->smd->auxTarget)
 	{
+		auxMesh = object_get_derived_final(calc->smd->auxTarget, CD_MASK_BAREMESH);
 		space_transform_setup( &local2aux, calc->ob, calc->smd->auxTarget);
-
-		aux_mesh = CDDM_copy( object_get_derived_final(calc->smd->auxTarget, CD_MASK_BAREMESH) ); 		//TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array
-		if(aux_mesh)
-			BENCH(bvhtree_from_mesh_faces(&auxData, aux_mesh, 0.0, 4, 6));
-		else
-			printf("Auxiliar target finalDerived mesh is null\n");
 	}
 
-
-	//Now, everything is ready to project the vertexs!
-#pragma omp parallel for private(i,hit) schedule(static)
-	for(i = 0; i<calc->numVerts; ++i)
+	//After sucessufuly build the trees, start projection vertexs
+	if( bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6)
+	&&  (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6)))
 	{
-		float *co = calc->vertexCos[i];
-		float tmp_co[3], tmp_no[3];
-		float lim = 10000.0f; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that
-		float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup);
-
-		if(weight == 0.0f) continue;
 
-		if(ss_mesh)
-		{
-			VECCOPY(tmp_co, vert[i].co);
-		}
-		else
+#pragma omp parallel for private(i,hit) schedule(static)
+		for(i = 0; i<calc->numVerts; ++i)
 		{
-			VECCOPY(tmp_co, co);
-		}
+			float *co = calc->vertexCos[i];
+			float tmp_co[3], tmp_no[3];
+			float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup);
 
+			if(weight == 0.0f) continue;
 
-		if(vert)
-			NormalShortToFloat(tmp_no, vert[i].no);
-		else
-			VECCOPY( tmp_no, proj_axis );
-
+			if(calc->vert)
+			{
+				VECCOPY(tmp_co, calc->vert[i].co);
+				if(calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL)
+					NormalShortToFloat(tmp_no, calc->vert[i].no);
+				else
+					VECCOPY(tmp_no, proj_axis);
+			}
+			else
+			{
+				VECCOPY(tmp_co, co);
+				VECCOPY(tmp_no, proj_axis);
+			}
 
-		hit.index = -1;
-		hit.dist = lim;
 
+			hit.index = -1;
+			hit.dist = 10000.0f; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that
 
-		//Project over positive direction of axis
-		if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR)
-		{
+			//Project over positive direction of axis
+			if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR)
+			{
 
-			if(auxData.tree)
-				normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
+				if(auxData.tree)
+					normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
 
-			normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
-		}
+				normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
+			}
 
-		//Project over negative direction of axis
-		if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)
-		{
-			float inv_no[3] = { -tmp_no[0], -tmp_no[1], -tmp_no[2] };
+			//Project over negative direction of axis
+			if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)
+			{
+				float inv_no[3] = { -tmp_no[0], -tmp_no[1], -tmp_no[2] };
 
 
-			if(auxData.tree)
-				normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
+				if(auxData.tree)
+					normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
 
-			normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
-		}
+				normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
+			}
 
 
-		if(hit.index != -1)
-		{
-			VecLerpf(co, co, hit.co, weight);
+			if(hit.index != -1)
+			{
+				VecLerpf(co, co, hit.co, weight);
+			}
 		}
 	}
 
-
-//Simple do{} while(0) structure to allow to easily jump to the "free memory and return" part
-} while(0);
-
 	//free data structures
-
 	free_bvhtree_from_mesh(&treeData);
 	free_bvhtree_from_mesh(&auxData);
-
-	if(aux_mesh)
-		aux_mesh->release(aux_mesh);
-
-	if(ss_mesh)
-		ss_mesh->release(ss_mesh);
 }
 
 /*
@@ -529,8 +518,6 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
 	BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
 	BVHTreeNearest  nearest  = NULL_BVHTreeNearest;
 
-
-
 	//Create a bvh-tree of the given target
 	BENCH(bvhtree_from_mesh_faces( &treeData, calc->target, 0.0, 2, 6));
 	if(treeData.tree == NULL)
@@ -554,7 +541,14 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
 		if(weight == 0.0f) continue;
 
 		//Convert the vertex to tree coordinates
-		VECCOPY(tmp_co, co);
+		if(calc->vert)
+		{
+			VECCOPY(tmp_co, calc->vert[i].co);
+		}
+		else
+		{
+			VECCOPY(tmp_co, co);
+		}
 		space_transform_apply(&calc->local2target, tmp_co);
 
 		//Use local proximity heuristics (to reduce the nearest search)
@@ -593,7 +587,6 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
 		}
 	}
 
-
 	free_bvhtree_from_mesh(&treeData);
 }
 
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 2e89ce3f80536010e2bdea24b317391ef151ec4e..6635ef29d51f50d830f728f3c185990184cecfdd 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -106,6 +106,8 @@ World *add_world(char *name)
 	wrld->ao_approx_error= 0.25f;
 	
 	wrld->physicsEngine= WOPHY_BULLET;//WOPHY_SUMO; Bullet by default
+	wrld->mode = WO_DBVT_CULLING;	// DBVT culling by default
+	wrld->occlusionRes = 128;
 	wrld->preview = NULL;
 
 	return wrld;
diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h
index 13d5b5fe8290aea17a1186dceb401e9a5506cd1f..c131dd93c720c3201eb2787d57163f8440a82b98 100644
--- a/source/blender/blenlib/BLI_blenlib.h
+++ b/source/blender/blenlib/BLI_blenlib.h
@@ -387,6 +387,7 @@ void BLI_setInterruptCallBack(int (*f)(void));
 char *BLI_strcasestr(const char *s, const char *find);
 int BLI_strcasecmp(const char *s1, const char *s2);
 int BLI_strncasecmp(const char *s1, const char *s2, int n);
+int BLI_natstrcmp(const char *s1, const char *s2);
 void BLI_timestr(double _time, char *str); /* time var is global */
 
 /** 
diff --git a/source/blender/blenlib/BLI_vfontdata.h b/source/blender/blenlib/BLI_vfontdata.h
index 8838b1992e4e360ee4db40019f98a248375e38b1..bd89959801ad21db4dbe272adfd45b3ace949028 100644
--- a/source/blender/blenlib/BLI_vfontdata.h
+++ b/source/blender/blenlib/BLI_vfontdata.h
@@ -54,7 +54,7 @@ typedef struct VFontData {
 typedef struct VChar {
 	struct VChar    *next, *prev;
  	ListBase        nurbsbase;
-	unsigned long   index;
+	intptr_t   index;
 	float           resol;
 	float           width;
 	float           *points;
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 8ba03ad1343ac7e593b353fd5233c02c021a7671..088b5e40a517c70f95476955bbd244b5d3a3c5e5 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -153,7 +153,7 @@ int BLI_compare(struct direntry *entry1, struct direntry *entry2)
 	if( strcmp(entry2->relname, ".")==0 ) return (1);
 	if( strcmp(entry1->relname, "..")==0 ) return (-1);
 	
-	return (BLI_strcasecmp(entry1->relname,entry2->relname));
+	return (BLI_natstrcmp(entry1->relname,entry2->relname));
 }
 
 
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
index 013b9e0bb1b49fde7ffa8c615e793edfd48eacbc..842ebc4c0a96b4d9955e1d7f97f07d62af1a481f 100644
--- a/source/blender/blenlib/intern/util.c
+++ b/source/blender/blenlib/intern/util.c
@@ -1985,6 +1985,55 @@ int BLI_strncasecmp(const char *s1, const char *s2, int n) {
 	return 0;
 }
 
+/* natural string compare, keeping numbers in order */
+int BLI_natstrcmp(const char *s1, const char *s2)
+{
+	int d1= 0, d2= 0;
+	
+	/* if both chars are numeric, to a strtol().
+	   then increase string deltas as long they are 
+	   numeric, else do a tolower and char compare */
+	
+	while(1) {
+		char c1 = tolower(s1[d1]);
+		char c2 = tolower(s2[d2]);
+		
+		if( isdigit(c1) && isdigit(c2) ) {
+			int val1, val2;
+			
+			val1= (int)strtol(s1+d1, (char **)NULL, 10);
+			val2= (int)strtol(s2+d2, (char **)NULL, 10);
+			
+			if (val1<val2) {
+				return -1;
+			} else if (val1>val2) {
+				return 1;
+			}
+			d1++;
+			while( isdigit(s1[d1]) )
+				d1++;
+			d2++;
+			while( isdigit(s2[d2]) )
+				d2++;
+			
+			c1 = tolower(s1[d1]);
+			c2 = tolower(s2[d2]);
+		}
+		
+		if (c1<c2) {
+			return -1;
+		} else if (c1>c2) {
+			return 1;
+		} else if (c1==0) {
+			break;
+		}
+		d1++;
+		d2++;
+	}
+	
+}
+
+
 
 #ifdef WITH_ICONV
 #include "iconv.h"
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index d03bcfa09e58030b0505892bea77c218c891d1fc..ce154755651658e256093ee62109b76efea1f55b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1850,6 +1850,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
 				data->tar = newlibadr(fd, id->lib, data->tar);
 			}
 			break;
+		case CONSTRAINT_TYPE_SHRINKWRAP:
+			{
+				bShrinkwrapConstraint *data;
+				data= ((bShrinkwrapConstraint*)con->data);
+				data->target = newlibadr(fd, id->lib, data->target);
+			}
+			break;
 		case CONSTRAINT_TYPE_NULL:
 			break;
 		}
@@ -2869,6 +2876,18 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
 			lvl->map_mem= NULL;
 		}
 	}
+
+	/* Gracefully handle corrupted mesh */
+	if(mesh->mr && !mesh->mr->verts) {
+		/* If totals match, simply load the current mesh verts into multires */
+		if(mesh->totvert == ((MultiresLevel*)mesh->mr->levels.last)->totvert)
+			mesh->mr->verts = MEM_dupallocN(mesh->mvert);
+		else {
+			/* Otherwise, we can't recover the data, silently remove multires */
+			multires_free(mesh->mr);
+			mesh->mr = NULL;
+		}
+	}
 	
 	if((fd->flags & FD_FLAGS_SWITCH_ENDIAN) && mesh->tface) {
 		TFace *tf= mesh->tface;
@@ -3157,6 +3176,11 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
 
 			smd->emCache = smd->mCache = 0;
 		}
+		else if (md->type==eModifierType_Armature) {
+			ArmatureModifierData *amd = (ArmatureModifierData*) md;
+			
+			amd->prevCos= NULL;
+		}
 		else if (md->type==eModifierType_Cloth) {
 			ClothModifierData *clmd = (ClothModifierData*) md;
 			
@@ -3207,6 +3231,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
 			collmd->mfaces = NULL;
 			
 		}
+		else if (md->type==eModifierType_Surface) {
+			SurfaceModifierData *surmd = (SurfaceModifierData*) md;
+
+			surmd->dm = NULL;
+			surmd->bvhtree = NULL;
+		}
 		else if (md->type==eModifierType_Hook) {
 			HookModifierData *hmd = (HookModifierData*) md;
 
@@ -8039,6 +8069,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 	
 	if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 4)) {
 		Scene *sce;
+		World *wrld;
 
 		/*  Dome (Fisheye) default parameters  */
 		for (sce= main->scene.first; sce; sce= sce->id.next) {
@@ -8048,6 +8079,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 			sce->r.domeres = 4;
 			sce->r.domeresbuf = 1.0f;
 		}
+		/* DBVT culling by default */
+		for(wrld=main->world.first; wrld; wrld= wrld->id.next) {
+			wrld->mode |= WO_DBVT_CULLING;
+			wrld->occlusionRes = 128;
+		}
 	}
 
 	/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
@@ -8621,6 +8657,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
 				expand_doit(fd, mainvar, data->tar);
 			}
 			break;
+		case CONSTRAINT_TYPE_SHRINKWRAP:
+			{
+				bShrinkwrapConstraint *data = (bShrinkwrapConstraint*)curcon->data;
+				expand_doit(fd, mainvar, data->target);
+			}
+			break;
 		default:
 			break;
 		}
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 3c1c280a7275e2940275c7b0048add88309a7fa6..6925186d63a527cc2c9e0b9211a17184fd747fd6 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -79,30 +79,56 @@ void GPU_render_text(MTFace *tface, int mode,
 	const char *textstr, int textlen, unsigned int *col,
 	float *v1, float *v2, float *v3, float *v4, int glattrib)
 {
-	if (mode & TF_BMFONT) {
-		Image* ima;
-		int characters, index, character;
+	if ((mode & TF_BMFONT) && (textlen>0) && tface->tpage) {
+		Image* ima = (Image*)tface->tpage;
+		int index, character;
 		float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
+		float advance_tab;
+		
+		/* multiline */
+		float line_start= 0.0f, line_height;
+		
+		if (v4)
+			line_height= MAX4(v1[1], v2[1], v3[1], v4[2]) - MIN4(v1[1], v2[1], v3[1], v4[2]);
+		else
+			line_height= MAX3(v1[1], v2[1], v3[1]) - MIN3(v1[1], v2[1], v3[1]);
+		line_height *= 1.2; /* could be an option? */
+		/* end multiline */
 
-		characters = textlen;
-
-		ima = (Image*)tface->tpage;
-		if (ima == NULL)
-			characters = 0;
-
-		// color has been set
+		
+		/* color has been set */
 		if (tface->mode & TF_OBCOL)
 			col= NULL;
 		else if (!col)
 			glColor3f(1.0f, 1.0f, 1.0f);
 
 		glPushMatrix();
-		for (index = 0; index < characters; index++) {
+		
+		/* get the tab width */
+		matrixGlyph((ImBuf *)ima->ibufs.first, ' ', & centerx, &centery,
+			&sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
+		
+		advance_tab= advance * 4; /* tab width could also be an option */
+		
+		
+		for (index = 0; index < textlen; index++) {
 			float uv[4][2];
 
 			// lets calculate offset stuff
 			character = textstr[index];
 			
+			if (character=='\n') {
+				glTranslatef(line_start, -line_height, 0.0);
+				line_start = 0.0f;
+				continue;
+			}
+			else if (character=='\t') {
+				glTranslatef(advance_tab, 0.0, 0.0);
+				line_start -= advance_tab; /* so we can go back to the start of the line */
+				continue;
+				
+			}
+			
 			// space starts at offset 1
 			// character = character - ' ' + 1;
 			matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, &centery,
@@ -143,6 +169,7 @@ void GPU_render_text(MTFace *tface, int mode,
 			glEnd();
 
 			glTranslatef(advance, 0.0, 0.0);
+			line_start -= advance; /* so we can go back to the start of the line */
 		}
 		glPopMatrix();
 	}
diff --git a/source/blender/imbuf/intern/anim5.c b/source/blender/imbuf/intern/anim5.c
index ab203fe80de9c17300582a84a0030808a5e5a1d2..b6f29b6a1457e813df68e48c99b7e0b58c92a391 100644
--- a/source/blender/imbuf/intern/anim5.c
+++ b/source/blender/imbuf/intern/anim5.c
@@ -425,7 +425,7 @@ int startanim5(struct anim * anim) {
 	/* de hele file wordt in het geheugen gemapped */
 
 	totlen = BLI_filesize(file);
-	if (totlen && file>=0) {
+	if (totlen>0 && file>=0) {
 		lseek(file, 0L, SEEK_SET);
 		
 		mem= MEM_mallocN(totlen, "mmap");
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index fe7e26eac2b427c15ab18811783d76e6b49f5c34..6be257ff737fdb7ba909fbe4a1c3d445d47f8e17 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -294,10 +294,12 @@ void bilinear_interpolation_color(struct ImBuf *in, unsigned char *outI, float *
 		b= v-floor(v);
 		a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b);
 		
-		outI[0]= ma_mb*row1I[0] + a_mb*row3I[0] + ma_b*row2I[0]+ a_b*row4I[0];
-		outI[1]= ma_mb*row1I[1] + a_mb*row3I[1] + ma_b*row2I[1]+ a_b*row4I[1];
-		outI[2]= ma_mb*row1I[2] + a_mb*row3I[2] + ma_b*row2I[2]+ a_b*row4I[2];
-		outI[3]= ma_mb*row1I[3] + a_mb*row3I[3] + ma_b*row2I[3]+ a_b*row4I[3];
+		/* need to add 0.5 to avoid rounding down (causes darken with the smear brush)
+		 * tested with white images and this should not wrap back to zero */
+		outI[0]= (ma_mb*row1I[0] + a_mb*row3I[0] + ma_b*row2I[0]+ a_b*row4I[0]) + 0.5f;
+		outI[1]= (ma_mb*row1I[1] + a_mb*row3I[1] + ma_b*row2I[1]+ a_b*row4I[1]) + 0.5f;
+		outI[2]= (ma_mb*row1I[2] + a_mb*row3I[2] + ma_b*row2I[2]+ a_b*row4I[2]) + 0.5f;
+		outI[3]= (ma_mb*row1I[3] + a_mb*row3I[3] + ma_b*row2I[3]+ a_b*row4I[3]) + 0.5f;
 	}
 }
 
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 3e618a483e352ca8b8ebf981b5de9cd84035d941..9e077cbc8093aabc977a0afcca716d1fc1648edb 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -570,13 +570,17 @@ void IMB_exr_write_channels(void *handle)
 	FrameBuffer frameBuffer;
 	ExrChannel *echan;
 	
-	for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next)
-		frameBuffer.insert (echan->name, Slice (FLOAT,  (char *)echan->rect, 
-												echan->xstride*sizeof(float), echan->ystride*sizeof(float)));
-	
-	data->ofile->setFrameBuffer (frameBuffer);
-	data->ofile->writePixels (data->height);	
-	
+	if(data->channels.first) {
+		for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next)
+			frameBuffer.insert (echan->name, Slice (FLOAT,  (char *)echan->rect, 
+													echan->xstride*sizeof(float), echan->ystride*sizeof(float)));
+		
+		data->ofile->setFrameBuffer (frameBuffer);
+		data->ofile->writePixels (data->height);	
+	}
+	else {
+		printf("Error: attempt to save MultiLayer without layers.\n");
+	}
 }
 
 void IMB_exr_read_channels(void *handle)
diff --git a/source/blender/imbuf/intern/rotate.c b/source/blender/imbuf/intern/rotate.c
index c04987b3e71e404ff062d2f2f29c645f729d456f..732c06907df9594408fa9162a3d213603c53a73b 100644
--- a/source/blender/imbuf/intern/rotate.c
+++ b/source/blender/imbuf/intern/rotate.c
@@ -30,6 +30,7 @@
  */
 
 #include "BLI_blenlib.h"
+#include  "BKE_utildefines.h"
 
 #include "imbuf.h"
 #include "imbuf_patch.h"
@@ -94,7 +95,6 @@ void IMB_flipy(struct ImBuf * ibuf)
 void IMB_flipx(struct ImBuf * ibuf)
 {
 	short x, y, xr, xl, yi;
-	unsigned int px;
 	float px_f[4];
 	
 	if (ibuf == NULL) return;
@@ -105,9 +105,7 @@ void IMB_flipx(struct ImBuf * ibuf)
 	if (ibuf->rect) {
 		for(yi=y-1;yi>=0;yi--) {
 			for(xr=x-1, xl=0; xr>=xl; xr--, xl++) {
-				px = ibuf->rect[(x*yi)+xr];
-				ibuf->rect[(x*yi)+xr] =	ibuf->rect[(x*yi)+xl];
-				ibuf->rect[(x*yi)+xl] =	px;		
+				SWAP(unsigned int, ibuf->rect[(x*yi)+xr], ibuf->rect[(x*yi)+xl]);
 			}
 		}
 	}
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 8257eb4643ed70b070a4648fc7896b0f8b4d09dc..b308915cd62a93cdc4c413e34fb3b1a83bd01599 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -299,7 +299,6 @@ struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
 	if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (0);
 
 	do_rect= (ibuf1->rect != NULL);
-	do_float= (ibuf1->rect_float != NULL);
 
 	if (ibuf1->x <= 1) return(IMB_half_y(ibuf1));
 	if (ibuf1->y <= 1) return(IMB_half_x(ibuf1));
@@ -312,6 +311,8 @@ struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
 	p1 = (uchar *) ibuf1->rect;
 	dest=(uchar *) ibuf2->rect;
 
+	do_float= (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL);
+
 	for(y=ibuf2->y;y>0;y--){
 		if (do_rect) p2 = p1 + (ibuf1->x << 2);
 		if (do_float) p2f = p1f + (ibuf1->x << 2);
@@ -608,34 +609,35 @@ static void shrink_picture_byte(
 
 			w = (weight1y * weight1x) >> 16;
 
-			dst_line1[x].r += (line[0] * w) >> 16;
-			dst_line1[x].g += (line[1] * w) >> 16;
-			dst_line1[x].b += (line[2] * w) >> 16;
-			dst_line1[x].a += (line[3] * w) >> 16;
+			/* ensure correct rounding, without this you get ugly banding (ton) */
+			dst_line1[x].r += (line[0] * w + 32767) >> 16;
+			dst_line1[x].g += (line[1] * w + 32767) >> 16;
+			dst_line1[x].b += (line[2] * w + 32767) >> 16;
+			dst_line1[x].a += (line[3] * w + 32767) >> 16;
 			dst_line1[x].weight += w;
 
 			w = (weight2y * weight1x) >> 16;
 
-			dst_line2[x].r += (line[0] * w) >> 16;
-			dst_line2[x].g += (line[1] * w) >> 16;
-			dst_line2[x].b += (line[2] * w) >> 16;
-			dst_line2[x].a += (line[3] * w) >> 16;
+			dst_line2[x].r += (line[0] * w + 32767) >> 16;
+			dst_line2[x].g += (line[1] * w + 32767) >> 16;
+			dst_line2[x].b += (line[2] * w + 32767) >> 16;
+			dst_line2[x].a += (line[3] * w + 32767) >> 16;
 			dst_line2[x].weight += w;
 
 			w = (weight1y * weight2x) >> 16;
 
-			dst_line1[x+1].r += (line[0] * w) >> 16;
-			dst_line1[x+1].g += (line[1] * w) >> 16;
-			dst_line1[x+1].b += (line[2] * w) >> 16;
-			dst_line1[x+1].a += (line[3] * w) >> 16;
+			dst_line1[x+1].r += (line[0] * w + 32767) >> 16;
+			dst_line1[x+1].g += (line[1] * w + 32767) >> 16;
+			dst_line1[x+1].b += (line[2] * w + 32767) >> 16;
+			dst_line1[x+1].a += (line[3] * w + 32767) >> 16;
 			dst_line1[x+1].weight += w;
 
 			w = (weight2y * weight2x) >> 16;
 
-			dst_line2[x+1].r += (line[0] * w) >> 16;
-			dst_line2[x+1].g += (line[1] * w) >> 16;
-			dst_line2[x+1].b += (line[2] * w) >> 16;
-			dst_line2[x+1].a += (line[3] * w) >> 16;
+			dst_line2[x+1].r += (line[0] * w + 32767) >> 16;
+			dst_line2[x+1].g += (line[1] * w + 32767) >> 16;
+			dst_line2[x+1].b += (line[2] * w + 32767) >> 16;
+			dst_line2[x+1].a += (line[3] * w + 32767) >> 16;
 			dst_line2[x+1].weight += w;
 
 			x_dst += dx_dst;
diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h
index 6848be2a48194e8471d2c5ebd06843601abb4151..2835e414d1c31c0bd23c9309fa5800b990aaa895 100644
--- a/source/blender/include/BDR_gpencil.h
+++ b/source/blender/include/BDR_gpencil.h
@@ -65,7 +65,7 @@ struct bGPdata *gpencil_data_getactive(struct ScrArea *sa);
 short gpencil_data_setactive(struct ScrArea *sa, struct bGPdata *gpd);
 struct ScrArea *gpencil_data_findowner(struct bGPdata *gpd);
 
-void gpencil_frame_delete_laststroke(struct bGPDframe *gpf, bGPDlayer *gpl);
+void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf);
 
 struct bGPDframe *gpencil_layer_getframe(struct bGPDlayer *gpl, int cframe, short addnew);
 void gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf);
diff --git a/source/blender/include/BIF_butspace.h b/source/blender/include/BIF_butspace.h
index f0b37814947a084f0b7772ff002ded8cdddb35fb..94bf7d65832e116e8795bb785eb089d1411c5644 100644
--- a/source/blender/include/BIF_butspace.h
+++ b/source/blender/include/BIF_butspace.h
@@ -134,7 +134,89 @@ extern void validate_editbonebutton_cb(void *bonev, void *namev);
 #define X4CLM2		77
 #define X4CLM3		165
 #define X4CLM4		232
- 
 
-#endif
+#if 0
+/* start buttons grid doc/reclacement version
+   With this system rows can easily have 1 to 4 buttons
+   or create perfectly aligned 1 to 4 columns layouts
+
+     < - - -    PANEL_XMAX  - - - >|
+     < - - -      PANELX     - - - >
+
+      .--  XSPACE side padding  --.
+      |                           |
+      |.- All CLM1                |
+      ||     X2CLM2 -.  X3CLM3    |
+      ||             |    |       |
+     +v|-------------|----|-------v+
+     <-/             |    |        |
+     | [           But1          ] |     1 button of BUTW1 size
+     <-             -/    |        |
+     | [   But1    ]=[   But2    ] |     2 buttons of BUTW2 size
+     <-                  -/        |
+  v  | [ But1  ]=[ But2 ]#[ But3 ] |     3 buttons of BUTW3 size
+  |  |                             |  v
+  ^  | [But1]#[But2]=[But3]#[But4] |  |  4 buttons of BUTW3 size
+  |  <-      ^      ^      -\      |  ^
+  |  +-------|------|-------|------+  |
+  |          |      |       |         |
+  '- YSPACE  '---.--'       '- X4CLM4 '- BUTH
+ (row to row)    |
+              Padding based in XSPACE (= normal, # +1 pix to make all match)
+
+   Calls like uiBlockBeginAlign/uiBlockEndAlign will make the button
+   to button space disappear if needed, forming a compact group, in some themes
+
+   TODO: Figure relations, meaning and usage of
+         PANELY, PANEL_YMAX, PANELW, PANELH
+ */
+#define PANELX		320
+#define PANELY		0
+#define PANELW		318
+#define PANELH		204
+
+#define XSPACE		10
+#define YSPACE		6
+#define PANEL_XMAX	(PANELX - XSPACE)
+#define PANEL_YMAX	210
+
+/* The widths follow 300, 150, 100 and 75, which is nice (discarding spacing)
+   sadly spacers and integer rounding make 3 and 4 column complex cases
+   so they better be manually set and checked following the comments */
+#define BUTW1		(PANELX - (2 * XSPACE))
+#define BUTW2		((BUTW1 / 2) - XSPACE)
+/* Manual calc so BUTW3 + XSPACE + BUTW3 + (XSPACE+1) + BUTW3 = BUTW1
+   Could be something like ((BUTW1/3)-(1+(2*XSPACE)) if starting with 300 */
+#define BUTW3		93
+/* This time BUTW4 + (XSPACE+1) + BUTW4 + XSPACE + BUTW4 + (XSPACE+1) + BUTW4 = BUTW1
+   That would be ((BUTW1/4)-(2+(3*XSPACE)) if starting with 300 */
+#define BUTW4		67
+/* NOTE: Again, BUTW3 and BUTW4 values and formulas include manual tuning,
+   retune if base BUTW1 stops being 300 pixels. You have been warned */
+#define ICONBUTW	20
+#define BUTH		22
+
+/* X axis start positions of column presets
+   First number declares how many columns total
+   Second number declares the exact column it controls
+   So X3CLM2 means X start position of 2nd button for a row of 3 buttons */
+#define X1CLM1		XSPACE
+
+#define X2CLM1		X1CLM1
+#define X2CLM2		(X2CLM1 + BUTW2 + XSPACE)
+
+#define X3CLM1		X1CLM1
+#define X3CLM2		(X3CLM1 + BUTW3 + XSPACE)
+/* By substracting from end we already get the extra 1 pix */
+#define X3CLM3		(PANEL_XMAX - BUTW3)
 
+#define X4CLM1		X1CLM1
+/* Extra pix to reach the BUTW1 total size */
+#define X4CLM2		(X4CLM1 + BUTW4 + XSPACE + 1)
+#define X4CLM3		(X4CLM2 + BUTW4 + XSPACE)
+/* By substracting from end we already get the other extra 1 pix */
+#define X4CLM4		(PANEL_XMAX - BUTW4)
+/* end buttons grid doc/replacement version */
+#endif /* if 0 */
+
+#endif
diff --git a/source/blender/include/BIF_editfont.h b/source/blender/include/BIF_editfont.h
index d41f52f3c25c1a46f7672c9e6cea85483e2cabb9..f8bb708bccdbd8022278584664b148abd3211985 100644
--- a/source/blender/include/BIF_editfont.h
+++ b/source/blender/include/BIF_editfont.h
@@ -32,6 +32,8 @@
 #ifndef BIF_EDITFONT_H
 #define BIF_EDITFONT_H
 
+#include "BLO_sys_types.h"
+
 struct Text;
 
 extern char *BIF_lorem;
@@ -46,7 +48,7 @@ typedef struct unicodect
 	int   end;
 } unicodect;
 
-void do_textedit(unsigned short event, short val, unsigned long _ascii);
+void do_textedit(unsigned short event, short val, uintptr_t _ascii);
 void make_editText(void);
 void load_editText(void);
 void remake_editText(void);
diff --git a/source/blender/include/BIF_editseq.h b/source/blender/include/BIF_editseq.h
index be30a3eaaf354b61a73f4a89882468454963604c..54e99ca1828631238be2fa3629148bc696535ea7 100644
--- a/source/blender/include/BIF_editseq.h
+++ b/source/blender/include/BIF_editseq.h
@@ -41,7 +41,7 @@ void				reload_sequence(void);
 void				update_seq_ipo_rect(struct Sequence * seq);
 void				update_seq_icu_rects(struct Sequence * seq);
 struct Sequence*	get_last_seq();
-struct Sequence*	get_forground_frame_seq( int frame );
+struct Sequence*	get_foreground_frame_seq( int frame );
 void				set_last_seq(struct Sequence * seq);
 void				clear_last_seq();
 void				del_seq(void);
diff --git a/source/blender/include/BIF_poseobject.h b/source/blender/include/BIF_poseobject.h
index ab96f7ec03e44981e9fa280aea0489cbb703c4da..ba7ad8c4e77d3ff57e9df2c4ba149d3f4430310b 100644
--- a/source/blender/include/BIF_poseobject.h
+++ b/source/blender/include/BIF_poseobject.h
@@ -80,6 +80,7 @@ void pose_activate_flipped_bone(void);
 void pose_movetolayer(void);
 void pose_relax(void);
 void pose_flipquats(void);
+void pose_clear_user_transforms(void);
 
 #endif
 
diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h
index dc05acc173501a5b6a550824292b26bde35cce46..8bde3da85c7a4aeacbd3e40021bd1ada69a2ab4c 100644
--- a/source/blender/include/blendef.h
+++ b/source/blender/include/blendef.h
@@ -35,7 +35,7 @@
 #define MAXFRAMEF	300000.0f
 
 #define MINFRAME	1
-#define MINFRAMEF	1.0
+#define MINFRAMEF	1.0f
 
 /* max length material array, 16 because of bits in matfrom */
 #define MAXPICKBUF      10000
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index 868d0c3e6c0db4a6d29ef8995f8f91f6bda54576..8a9c1933c974a3bb60e89c9c8b03eae248d998fb 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -729,6 +729,7 @@ enum {
 	B_CONSTRAINT_ADD_PYTHON,
 	B_CONSTRAINT_ADD_CLAMPTO,
 	B_CONSTRAINT_ADD_TRANSFORM,
+	B_CONSTRAINT_ADD_SHRINKWRAP,
 	B_CONSTRAINT_INF
 };
 
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index 48432b8c6e226a8d14032dbd169a304eb48e1ee7..aeabae42adfd70dbabab169e71c08790cdc5deb5 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -195,7 +195,8 @@ typedef struct bGameActuator {
 
 typedef struct bVisibilityActuator {
 	/** bit 0: Is this object visible? 
-	 ** bit 1: Apply recursively  */
+	 ** bit 1: Apply recursively  
+	 ** bit 2: Is this object an occluder? */
 	int flag;
 } bVisibilityActuator;
 
@@ -357,6 +358,7 @@ typedef struct FreeCamera {
 #define ACT_PROP_ASSIGN		0
 #define ACT_PROP_ADD		1
 #define ACT_PROP_COPY		2
+#define ACT_PROP_TOGGLE		3
 
 /* constraint flag */
 #define ACT_CONST_LOCX		1
@@ -457,6 +459,7 @@ typedef struct FreeCamera {
 /* Set means the object will become invisible */
 #define ACT_VISIBILITY_INVISIBLE       (1 << 0)
 #define ACT_VISIBILITY_RECURSIVE       (1 << 1)
+#define ACT_VISIBILITY_OCCLUSION       (1 << 2)
 
 /* twodfilter->type */
 #define ACT_2DFILTER_ENABLED			-2
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index fe19cf60f12fe44a38882ef46cd7b3846b19645e..79f032d0d21040334c471bfb1198d514d138bc88 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -317,6 +317,15 @@ typedef struct bDistLimitConstraint {
 	int 		pad;
 } bDistLimitConstraint;
 
+typedef struct bShrinkwrapConstraint {
+	Object		*target;
+	float		dist;			/* distance to kept from target */
+	short		shrinkType;		/* shrink type (look on MOD shrinkwrap for values) */
+	char		projAxis;		/* axis to project over UP_X, UP_Y, UP_Z */
+	char 		pad[9];
+} bShrinkwrapConstraint;
+
+
 /* ------------------------------------------ */
 
 /* bConstraint->type 
@@ -344,10 +353,11 @@ typedef enum B_CONSTAINT_TYPES {
 	CONSTRAINT_TYPE_RIGIDBODYJOINT,		/* rigidbody constraint */
 	CONSTRAINT_TYPE_CLAMPTO, 			/* clampto constraint */	
 	CONSTRAINT_TYPE_TRANSFORM,			/* transformation (loc/rot/size -> loc/rot/size) constraint */	
+	CONSTRAINT_TYPE_SHRINKWRAP,			/* shrinkwrap (loc/rot) constraint */
 	
 	
 	/* NOTE: everytime a new constraint is added, update this */
-	NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_TRANSFORM
+	NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_SHRINKWRAP
 } B_CONSTRAINT_TYPES; 
 
 /* bConstraint->flag */
diff --git a/source/blender/makesdna/DNA_controller_types.h b/source/blender/makesdna/DNA_controller_types.h
index 376f95b0145147d9a8f59dc0419a4c2ef03fa544..b3c82e746c12b10fc7910b162d3b45b6acd83f60 100644
--- a/source/blender/makesdna/DNA_controller_types.h
+++ b/source/blender/makesdna/DNA_controller_types.h
@@ -43,6 +43,9 @@ typedef struct bExpressionCont {
 
 typedef struct bPythonCont {
 	struct Text *text;
+	char module[64];
+	int mode;
+	int flag; /* only used for debug now */
 } bPythonCont;
 
 typedef struct bController {
@@ -77,5 +80,8 @@ typedef struct bController {
 #define CONT_NEW		4
 #define CONT_MASK		8
 
+/* pyctrl->flag */
+#define CONT_PY_DEBUG	1
+
 #endif
 
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index ae07434a37ffe1a36c181a9fc0bbd1a3dc514b46..077481dfa6ede0f5467b52b6eb71e28ee5e6b53f 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -39,6 +39,7 @@ typedef enum ModifierType {
 	eModifierType_Fluidsim,
 	eModifierType_Mask,
 	eModifierType_SimpleDeform,
+	eModifierType_Surface,
 	NUM_MODIFIER_TYPES
 } ModifierType;
 
@@ -418,6 +419,14 @@ typedef struct CollisionModifierData {
 	struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
 } CollisionModifierData;
 
+typedef struct SurfaceModifierData {
+	ModifierData	modifier;
+
+	struct DerivedMesh *dm;
+
+	struct BVHTreeFromMesh *bvhtree; /* bounding volume hierarchy of the mesh faces */
+} SurfaceModifierData;
+
 typedef enum {
 	eBooleanModifierOp_Intersect,
 	eBooleanModifierOp_Union,
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 21c5242a703cafb9526aaafa2e80ca4df45fc468..e8e865a533cecf9daeb8724291f2acedf77e71eb 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -119,7 +119,7 @@ typedef struct BulletSoftBody {
 	float	kAHR;			/* Anchors hardness [0,1] */
 	int		collisionflags;	/* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */
 	int		numclusteriterations;	/* number of iterations to refine collision clusters*/
-
+	float	welding;		/* welding limit to remove duplicate/nearby vertices, 0.0..0.01 */
 } BulletSoftBody;
 
 /* BulletSoftBody.flag */
@@ -225,6 +225,7 @@ typedef struct SoftBody {
 #define PFIELD_USEMAXR			512
 #define PFIELD_USEMINR			1024
 #define PFIELD_TEX_ROOTCO		2048
+#define PFIELD_SURFACE			4096
 
 /* pd->falloff */
 #define PFIELD_FALL_SPHERE		0
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index b17896aec708deea6ce55d3c3d32c01387b4f2ac..82da883df4af7d5c6e35f1088a327698b635363f 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -157,7 +157,9 @@ typedef struct Object {
 	float formfactor;
 	float rdamping, sizefac;
 	float margin;
-	int   pad3;
+	float max_vel; /* clamp the maximum velocity 0.0 is disabled */
+	float min_vel; /* clamp the maximum velocity 0.0 is disabled */
+	float pad3; /* clamp the maximum velocity 0.0 is disabled */
 
 	char dt, dtx;
 	char totcol;	/* copy of mesh or curve or meta */
@@ -437,6 +439,7 @@ extern Object workob;
 
 #define OB_COLLISION	65536
 #define OB_SOFT_BODY	0x20000
+#define OB_OCCLUDER		0x40000
 
 /* ob->gameflag2 */
 #define OB_NEVER_DO_ACTIVITY_CULLING	1
@@ -455,6 +458,7 @@ extern Object workob;
 #define OB_BODY_TYPE_DYNAMIC		2
 #define OB_BODY_TYPE_RIGID			3
 #define OB_BODY_TYPE_SOFT			4
+#define OB_BODY_TYPE_OCCLUDER		5
 
 /* ob->scavisflag */
 #define OB_VIS_SENS		1
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index bf5b2ad3df54e048c1710c975f673727d665be4f..d26bdd469f6164a644e59aba231428d2602a00b5 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -412,6 +412,8 @@ typedef struct ToolSettings {
 	short unwrapper;
 	float uvcalc_radius;
 	float uvcalc_cubesize;
+	float uvcalc_margin;
+	float pad;
 	short uvcalc_mapdir;
 	short uvcalc_mapalign;
 	short uvcalc_flag;
diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h
index 2cae2cc8ccbd4112faa427954b1a0306391b35be..8b29ce1338dd3a1a83bbca906c9a2fd27673ee88 100644
--- a/source/blender/makesdna/DNA_sensor_types.h
+++ b/source/blender/makesdna/DNA_sensor_types.h
@@ -158,7 +158,8 @@ typedef struct bSensor {
 	/* just add here, to avoid align errors... */
 	short invert; /* Whether or not to invert the output. */
 	short level;  /* Whether the sensor is level base (edge by default) */
-	int pad;
+	short tap;
+	short pad;
 } bSensor;
 
 typedef struct bJoystickSensor {
@@ -166,7 +167,8 @@ typedef struct bJoystickSensor {
 	char type;
 	char joyindex;
 	short flag;
-	int axis;
+	short axis;
+	short axis_single;
 	int axisf;
 	int button;
 	int hat;
@@ -255,20 +257,22 @@ typedef struct bJoystickSensor {
 
 #define SENS_JOY_ANY_EVENT		1
 
-#define SENS_JOY_BUTTON		0
+#define SENS_JOY_BUTTON		0			/* axis type */
 #define SENS_JOY_BUTTON_PRESSED	0
 #define SENS_JOY_BUTTON_RELEASED	1
 
-#define SENS_JOY_AXIS			1
+#define SENS_JOY_AXIS			1		/* axis type */
 #define SENS_JOY_X_AXIS		0
 #define SENS_JOY_Y_AXIS		1
 #define SENS_JOY_NEG_X_AXIS     	2
 #define SENS_JOY_NEG_Y_AXIS     	3
 #define SENS_JOY_PRECISION		4
 
-#define SENS_JOY_HAT			2
+#define SENS_JOY_HAT			2		/* axis type */
 #define SENS_JOY_HAT_DIR		0
 
+#define SENS_JOY_AXIS_SINGLE	3		/* axis type */
+
 
 #define SENS_DELAY_REPEAT		1
 // should match JOYINDEX_MAX in SCA_JoystickDefines.h */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 735e1c4f195231055d77907f306e60d61867f0a3..d14acc12693aaf65c23080dccca51aae3ed6cd1a 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -356,7 +356,8 @@ typedef struct SpaceNode {
 	float xof, yof;	/* offset for drawing the backdrop */
 	
 	struct bNodeTree *nodetree, *edittree;
-	int treetype, pad;			/* treetype: as same nodetree->type */
+	int treetype;			/* treetype: as same nodetree->type */
+	short texfrom, pad;		/* texfrom object, world or brush */
 	
 	struct bGPdata *gpd;		/* grease-pencil data */
 } SpaceNode;
@@ -366,6 +367,11 @@ typedef struct SpaceNode {
 #define SNODE_BACKDRAW		2
 #define SNODE_DISPGP		4
 
+/* snode->texfrom */
+#define SNODE_TEX_OBJECT	0
+#define SNODE_TEX_WORLD		1
+#define SNODE_TEX_BRUSH		2
+
 typedef struct SpaceImaSel {
 	SpaceLink *next, *prev;
 	int spacetype;
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index ab7e25190adcd0c93de9a329a10a7b864289fde3..f599364ed66aa4b6593410ebc057bd5d2067e01b 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -84,9 +84,12 @@ typedef struct World {
 	 * bit 1: Do stars
 	 * bit 2: (reserved) depth of field
 	 * bit 3: (gameengine): Activity culling is enabled.
+	 * bit 4: ambient occlusion
+	 * bit 5: (gameengine) : enable Bullet DBVT tree for view frustrum culling 
 	 */
 	short mode;
-	int physicsEngine;	/* here it's aligned */
+	short occlusionRes;		/* resolution of occlusion Z buffer in pixel */
+	short physicsEngine;	/* here it's aligned */
 	
 	float misi, miststa, mistdist, misthi;
 	
@@ -133,6 +136,7 @@ typedef struct World {
 #define WO_DOF                 4
 #define WO_ACTIVITY_CULLING	   8
 #define WO_AMB_OCC	   		  16
+#define WO_DBVT_CULLING		  32
 
 /* aomix */
 #define WO_AOADD	0
diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript
index d38303d7d20dc0b078b67a01f27cca84b4d19c01..bf8df8a9156383be06f915be78be3864f0954a2b 100644
--- a/source/blender/nodes/SConscript
+++ b/source/blender/nodes/SConscript
@@ -17,29 +17,31 @@ incs += ' ../gpu #/extern/glew/include '
 incs += ' ' + env['BF_OPENGL_INC']
 incs += ' ' + env['BF_ZLIB_INC']
 
-defs = ''
+defs = [] 
 
 if env['WITH_BF_PYTHON']:
-    incs += ' ' + env['BF_PYTHON_INC']
-    incs += ' ../python'
+	incs += ' ' + env['BF_PYTHON_INC']
+	incs += ' ../python'
+	if env['BF_DEBUG']:
+		defs.append('_DEBUG')
 else:
-    defs += 'DISABLE_PYTHON'
+	defs.append('DISABLE_PYTHON')
 
 if env['WITH_BF_INTERNATIONAL']:
-    defs += ' WITH_FREETYPE2'
+	defs.append('WITH_FREETYPE2')
 
 if env['WITH_BF_OPENEXR']:
-    defs += ' WITH_OPENEXR'
+	defs.append('WITH_OPENEXR')
 
 if env['WITH_BF_FFMPEG']:
-    defs += ' WITH_FFMPEG'
-    incs += ' ' + env['BF_FFMPEG_INC']
+	defs.append('WITH_FFMPEG')
+	incs += ' ' + env['BF_FFMPEG_INC']
 
 if env['WITH_BF_QUICKTIME']:
-    defs += ' WITH_QUICKTIME'
-    incs += ' ' + env['BF_QUICKTIME_INC']
+	defs.append('WITH_QUICKTIME')
+	incs += ' ' + env['BF_QUICKTIME_INC']
 
-env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 200, 400] )
-env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] )
-env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] )
-env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] )
+env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = defs, libtype=['intern', 'core', 'player'], priority = [200, 200, 400] )
+env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = defs, libtype=['intern', 'core', 'player'], priority = [200, 175, 300] )
+env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = defs, libtype=['intern', 'core', 'player'], priority = [200, 175, 300] )
+env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = defs, libtype=['intern', 'core', 'player'], priority = [200, 175, 300] )
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c b/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c
index 846aec490c2c475a8b1d15009e033e863072f4ff..15f3148b54c62d7ca797b716b36bda404aef494f 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c
@@ -55,6 +55,7 @@ static void do_normalize(bNode *node, float *out, float *src, float *min, float
 	}
 }
 
+/* The code below assumes all data is inside range +- this, and that input buffer is single channel */
 #define BLENDER_ZMAX 10000.0f
 
 static void node_composit_exec_normalize(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
@@ -63,7 +64,7 @@ static void node_composit_exec_normalize(void *data, bNode *node, bNodeStack **i
 	/* stack order out: valbuf */
 	if(out[0]->hasoutput==0) return;
 
-	/* input no image? then only value operation */
+	/* Input has no image buffer? Then pass the value */
 	if(in[0]->data==NULL) {
 		QUATCOPY(out[0]->vec, in[0]->vec);
 	}
@@ -78,18 +79,20 @@ static void node_composit_exec_normalize(void *data, bNode *node, bNodeStack **i
 		CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */
 
 		for (val = cbuf->rect; tot; tot--, val++) {
-			if ((*val > max) && (*val < BLENDER_ZMAX)) {
+			if ((*val > max) && (*val <= BLENDER_ZMAX)) {
 				max = *val;
 			}
-			if (*val < min) {
+			if ((*val < min) && (*val >= -BLENDER_ZMAX)) {
 				min = *val;
 			}
 		}
-		mult = 1.0f/(max-min);
-
-		printf("min %f max %f\n", min, max);
-
-		composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, NULL, &min, NULL, &mult, do_normalize, CB_VAL, CB_VAL, CB_VAL);
+		/* In the rare case of flat buffer, which would cause a divide by 0, just pass the input to the output */
+		if ((max-min) != 0.0f) {
+			mult = 1.0f/(max-min);
+			composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, NULL, &min, NULL, &mult, do_normalize, CB_VAL, CB_VAL, CB_VAL);
+		} else {
+			memcpy(stackbuf->rect, cbuf->rect, sizeof(float) * cbuf->x * cbuf->y);
+		}
 
 		out[0]->data= stackbuf;
 	}
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_scale.c b/source/blender/nodes/intern/CMP_nodes/CMP_scale.c
index cc6f924949572b104227a384fc9a626dae8e7b87..ee3607c11f6afc88b65d1a26feeece135023273e 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_scale.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_scale.c
@@ -65,8 +65,8 @@ static void node_composit_exec_scale(void *data, bNode *node, bNodeStack **in, b
 			newx = cbuf->x * (rd->size / 100.0f);
 			newy = cbuf->y * (rd->size / 100.0f);
 		} else {	/* CMP_SCALE_ABSOLUTE */
-			newx= (int)in[1]->vec[0];
-			newy= (int)in[2]->vec[0];
+			newx= MAX2((int)in[1]->vec[0], 1);
+			newy= MAX2((int)in[2]->vec[0], 1);
 		}
 		newx= MIN2(newx, CMP_SCALE_MAX);
 		newy= MIN2(newy, CMP_SCALE_MAX);
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
index 2065ac2ed338a7730f29ac9ce1da25ad1d1bbeef..4b20ca9da21db09b0b16fd4c60a9edb5d3214f8d 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
@@ -33,6 +33,11 @@
 #include <eval.h>
 #endif
 
+/* TODO, support python3.x */
+#if PY_VERSION_HEX >= 0x03000000
+#define DISABLE_PYTHON 1
+#endif
+
 #include "DNA_text_types.h"
 #include "BKE_text.h"
 #include "BKE_utildefines.h"
@@ -51,13 +56,15 @@ static void node_dynamic_free_storage_cb(bNode *node);
 
 #ifndef DISABLE_PYTHON
 static PyObject *init_dynamicdict(void) {
-	PyObject *newscriptdict;
+	PyObject *newscriptdict, *item;
 	PyGILState_STATE gilstate = PyGILState_Ensure();
 
 	newscriptdict= PyDict_New();
 
 	PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins());
-	EXPP_dict_set_item_str(newscriptdict, "__name__", PyString_FromString("__main__"));
+	item= PyString_FromString("__main__");
+	PyDict_SetItemString(newscriptdict, "__name__", item);
+	Py_DECREF(item);
 
 	PyGILState_Release(gilstate);
 
@@ -340,7 +347,11 @@ static void node_dynamic_pyerror_print(bNode *node)
 	PyGILState_STATE gilstate = PyGILState_Ensure();
 
 	fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name);
-	if (PyErr_Occurred()) { PyErr_Print(); }
+	if (PyErr_Occurred()) {
+		PyErr_Print();
+		PyErr_Clear();
+		PySys_SetObject("last_traceback", NULL);
+	}
 	else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); }
 
 	PyGILState_Release(gilstate);
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_math.c b/source/blender/nodes/intern/SHD_nodes/SHD_math.c
index 050c2cdcc9596ff94921afb7b97922952914b6d1..645f95686d76e23ad65b45764970bb50858dc230 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_math.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_math.c
@@ -197,7 +197,7 @@ bNodeStack **out)
 static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
 {
 	static char *names[] = {"math_add", "math_subtract", "math_multiply",
-		"math_divide", "math_sine", "math_cosine", "math_tangnet", "math_asin",
+		"math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
 		"math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
 		"math_round", "math_less_than", "math_greater_than"};
 
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_distance.c b/source/blender/nodes/intern/TEX_nodes/TEX_distance.c
index ff9ec4db76bb67021d5129acb068edf6203444c5..d23eb6bc5896e86ffc629282421fd7ea510ff8bc 100644
--- a/source/blender/nodes/intern/TEX_nodes/TEX_distance.c
+++ b/source/blender/nodes/intern/TEX_nodes/TEX_distance.c
@@ -44,7 +44,6 @@ static bNodeSocketType outputs[]= {
 static void valuefn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
 {
 	float coord1[3], coord2[3];
-	float x, y, z;
 
 	tex_input_vec(coord1, in[0], coord, thread);
 	tex_input_vec(coord2, in[1], coord, thread);
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_texture.c b/source/blender/nodes/intern/TEX_nodes/TEX_texture.c
index 884d2cd0eb66cb6ed232722b8c18dfda2e803b29..30492b84764f88ff9370fe04bd0c9fdf7eee51fe 100644
--- a/source/blender/nodes/intern/TEX_nodes/TEX_texture.c
+++ b/source/blender/nodes/intern/TEX_nodes/TEX_texture.c
@@ -47,7 +47,7 @@ static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, shor
 	
 	Tex *nodetex = (Tex *)node->id;
 	
-	if(node->custom2) {
+	if(node->custom2 || node->need_exec==0) {
 		/* this node refers to its own texture tree! */
 		QUATCOPY(
 			out,
diff --git a/source/blender/nodes/intern/TEX_util.c b/source/blender/nodes/intern/TEX_util.c
index 562072328a86b02f43fae7078ab832968eb0ed8f..1aabb7ae5147f9445b273a807a806e37f100c817 100644
--- a/source/blender/nodes/intern/TEX_util.c
+++ b/source/blender/nodes/intern/TEX_util.c
@@ -34,6 +34,12 @@
 	obtain a colour value from this, a node further up the chain reads
 	the TexDelegate* from its input stack, and uses tex_call_delegate to
 	retrieve the colour from the delegate.
+ 
+    comments: (ton)
+    
+    This system needs recode, a node system should rely on the stack, and 
+	callbacks for nodes only should evaluate own node, not recursively go
+    over other previous ones.
 */
 
 #include <assert.h>
@@ -43,7 +49,8 @@
 
 void tex_call_delegate(TexDelegate *dg, float *out, float *coord, short thread)
 {
-	dg->fn(out, coord, dg->node, dg->in, thread);
+	if(dg->node->need_exec)
+		dg->fn(out, coord, dg->node, dg->in, thread);
 }
 
 void tex_input(float *out, int sz, bNodeStack *in, float *coord, short thread)
diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c
index ec81de1f5e89c695c6369a09f74473dcc403261b..1f35ebad9f7868c72cff6c3cd5071fbfd6a62e3a 100644
--- a/source/blender/python/BPY_interface.c
+++ b/source/blender/python/BPY_interface.c
@@ -70,7 +70,9 @@
 #include "api2_2x/Object.h"
 #include "api2_2x/Registry.h"
 #include "api2_2x/Pose.h"
+#include "api2_2x/Mathutils.h"
 #include "api2_2x/bpy.h" /* for the new "bpy" module */
+#include "api2_2x/bpy_internal_import.h"
 
 /*these next two are for pyconstraints*/
 #include "api2_2x/IDProp.h"
@@ -96,6 +98,17 @@ PyObject *bpy_pydriver_Dict = NULL;
 PyObject *bpy_orig_syspath_List = NULL;
 
 
+static void BPY_Err_Clear(void)
+{	
+	/* Added in 2.48a, the last_traceback can reference Objects for example, increasing
+	 * their user count. Not to mention holding references to wrapped data.
+	 * This is especially bad when the PyObject for the wrapped data is free'd, after blender 
+	 * has alredy dealocated the pointer */
+	PySys_SetObject( "last_traceback", NULL);
+	
+	PyErr_Clear();
+}
+
 /*
  * set up a weakref list for Armatures
  *    creates list in __main__ module dict 
@@ -105,30 +118,30 @@ static int setup_armature_weakrefs()
 {
 	PyObject *maindict;
 	PyObject *main_module;
-	char *list_name = ARM_WEAKREF_LIST_NAME;
+	PyObject *list;
+	PyObject *list_name = PyString_FromString(ARM_WEAKREF_LIST_NAME);
 
 	main_module = PyImport_AddModule( "__main__");
 	if(main_module){
-		PyObject *weakreflink;
 		maindict= PyModule_GetDict(main_module);
 
 		/* check if there is already a dict entry for the armature weakrefs,
 		 * and delete if so before making another one */
-
-		weakreflink= PyDict_GetItemString(maindict,list_name);
-		if( weakreflink != NULL ) {
-			PyDict_DelItemString(maindict,list_name);
-			Py_XDECREF( weakreflink );
-		}
-
-		if (PyDict_SetItemString(maindict, 
-								 list_name, 
-								 PyList_New(0)) == -1){
-			printf("Oops - setup_armature_weakrefs()\n");
-			
+		
+		if (PyDict_DelItem(maindict, list_name)==-1)
+			PyErr_Clear();
+		
+		list= PyList_New(0);
+		if (PyDict_SetItem(maindict, list_name, list) == -1){
+			PyErr_Print();
+			BPY_Err_Clear();
+			Py_DECREF(list);
+			Py_DECREF(list_name);
 			return 0;
 		}
+		Py_DECREF(list); /* the dict owns it now */
 	}
+	Py_DECREF(list_name);
 	return 1;
 }
 
@@ -164,10 +177,8 @@ static PyObject *RunPython( Text * text, PyObject * globaldict );
 static PyObject *CreateGlobalDictionary( void );
 static void ReleaseGlobalDictionary( PyObject * dict );
 static void DoAllScriptsFromList( ListBase * list, short event );
-static PyObject *importText( char *name );
 static void init_ourImport( void );
 static void init_ourReload( void );
-static PyObject *blender_import( PyObject * self, PyObject * args,  PyObject * kw);
 
 
 static void BPY_Err_Handle( char *script_name );
@@ -274,7 +285,7 @@ void BPY_end_python( void )
 		next_script = script->id.next;
 		free_libblock( &G.main->script, script );
 	}
-
+	
 	Py_Finalize(  );
 
 	BPyMenu_RemoveAllEntries(  );	/* freeing bpymenu mem */
@@ -532,16 +543,6 @@ static PyObject *traceback_getFilename( PyObject * tb )
 	else return PyString_FromString("unknown");
 }
 
-static void BPY_Err_Clear(void)
-{	
-	/* Added in 2.48a, the last_traceback can reference Objects for example, increasing
-	 * their user count. Not to mention holding references to wrapped data.
-	 * This is especially bad when the PyObject for the wrapped data is free'd, after blender 
-	 * has alredy dealocated the pointer */
-	PySys_SetObject( "last_traceback", Py_None);
-	
-	PyErr_Clear();
-}
 /****************************************************************************
 * Description: Blender Python error handler. This catches the error and	
 * stores filename and line number in a global  
@@ -1137,6 +1138,7 @@ void BPY_free_finished_script( Script * script )
 
 	if( PyErr_Occurred(  ) ) {	/* if script ended after filesel */
 		PyErr_Print(  );	/* eventual errors are handled now */
+		BPY_Err_Clear(  );
 		error_pyscript(  );
 	}
 
@@ -1239,15 +1241,15 @@ static int bpy_pydriver_create_dict(void)
 
 	/* import some modules: builtins, Blender, math, Blender.noise */
 
-	PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
+	PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins()); /* borrow ref, ok */
 
 	mod = PyImport_ImportModule("Blender");
 	if (mod) {
 		PyDict_SetItemString(d, "Blender", mod);
 		PyDict_SetItemString(d, "b", mod);
-		Py_DECREF(mod);
+		Py_DECREF(mod); /* 2 refs above are cleared with the dict, only decref the ref from PyImport_ImportModule */
 	} else {
-		PyErr_Clear();
+		BPY_Err_Clear();
 	}
 
 	mod = PyImport_ImportModule("math");
@@ -1257,28 +1259,31 @@ static int bpy_pydriver_create_dict(void)
 		/* Only keep for backwards compat! - just import all math into root, they are standard */
 		PyDict_SetItemString(d, "math", mod);
 		PyDict_SetItemString(d, "m", mod);
-		Py_DECREF(mod);
-	} 
+		Py_DECREF(mod); /* 2 refs above are cleared with the dict, only decref the ref from PyImport_ImportModule */
+	} else {
+		BPY_Err_Clear();
+	}
 
 	mod = PyImport_ImportModule("Blender.Noise");
 	if (mod) {
 		PyDict_SetItemString(d, "noise", mod);
 		PyDict_SetItemString(d, "n", mod);
-		Py_DECREF(mod);
+		Py_DECREF(mod); /* 2 refs above are cleared with the dict, only decref the ref from PyImport_ImportModule */
 	} else {
-		PyErr_Clear();
+		BPY_Err_Clear();
 	}
 
 	/* If there's a Blender text called pydrivers.py, import it.
 	 * Users can add their own functions to this module. */
 	if (G.f&G_DOSCRIPTLINKS) {
-		mod = importText("pydrivers"); /* can also use PyImport_Import() */
+		int found; /* not used but needed as an arg */
+		mod = bpy_text_import("pydrivers", &found); /* can also use PyImport_Import() */
 		if (mod) {
 			PyDict_SetItemString(d, "pydrivers", mod);
 			PyDict_SetItemString(d, "p", mod);
-			Py_DECREF(mod);
+			Py_DECREF(mod); /* 2 refs above are cleared with the dict, only decref the ref from PyImport_ImportModule */
 		} else {
-			PyErr_Clear();
+			BPY_Err_Clear();
 		}
 	}
 	/* short aliases for some Get() functions: */
@@ -1293,7 +1298,7 @@ static int bpy_pydriver_create_dict(void)
 			Py_DECREF(fcn);
 		}
 	} else {
-		PyErr_Clear();
+		BPY_Err_Clear();
 	}
 	
 	/* TODO - change these */
@@ -1307,7 +1312,7 @@ static int bpy_pydriver_create_dict(void)
 			Py_DECREF(fcn);
 		}
 	} else {
-		PyErr_Clear();
+		BPY_Err_Clear();
 	}
 
 	/* ma(matname) == Blender.Material.Get(matname) */
@@ -1320,7 +1325,7 @@ static int bpy_pydriver_create_dict(void)
 			Py_DECREF(fcn);
 		}
 	} else {
-		PyErr_Clear();
+		BPY_Err_Clear();
 	}
 
 	return 0;
@@ -1346,6 +1351,7 @@ static float pydriver_error(IpoDriver *driver) {
 		fprintf(stderr, "\nError in Ipo Driver: No Object\nThis is the failed Python expression:\n'%s'\n\n", driver->name);
 	
 	PyErr_Print();
+	BPY_Err_Clear();
 
 	return 0.0f;
 }
@@ -1441,7 +1447,7 @@ void BPY_pyconstraint_update(Object *owner, bConstraint *con)
 			return;
 		}
 		
-		Py_XDECREF(retval);
+		Py_DECREF(retval);
 		retval = NULL;
 		
 		/* try to find NUM_TARGETS */
@@ -1574,9 +1580,9 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase
 		con->flag |= PYCON_SCRIPTERROR;
 		
 		/* free temp objects */
-		Py_XDECREF(idprop);
-		Py_XDECREF(srcmat);
-		Py_XDECREF(tarmats);
+		Py_DECREF(idprop);
+		Py_DECREF(srcmat);
+		Py_DECREF(tarmats);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1585,7 +1591,7 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase
 		return;
 	}
 
-	if (retval) {Py_XDECREF( retval );}
+	Py_DECREF( retval );
 	retval = NULL;
 	
 	gval = PyDict_GetItemString(globals, "doConstraint");
@@ -1593,9 +1599,9 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase
 		printf("ERROR: no doConstraint function in constraint!\n");
 		
 		/* free temp objects */
-		Py_XDECREF(idprop);
-		Py_XDECREF(srcmat);
-		Py_XDECREF(tarmats);
+		Py_DECREF(idprop);
+		Py_DECREF(srcmat);
+		Py_DECREF(tarmats);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1608,15 +1614,15 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase
 	if (PyFunction_Check(gval)) {
 		pyargs = Py_BuildValue("OOO", srcmat, tarmats, idprop);
 		retval = PyObject_CallObject(gval, pyargs);
-		Py_XDECREF(pyargs);
+		Py_DECREF(pyargs);
 	} 
 	else {
 		printf("ERROR: doConstraint is supposed to be a function!\n");
 		con->flag |= PYCON_SCRIPTERROR;
 		
-		Py_XDECREF(idprop);
-		Py_XDECREF(srcmat);
-		Py_XDECREF(tarmats);
+		Py_DECREF(idprop);
+		Py_DECREF(srcmat);
+		Py_DECREF(tarmats);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1630,9 +1636,9 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase
 		con->flag |= PYCON_SCRIPTERROR;
 		
 		/* free temp objects */
-		Py_XDECREF(idprop);
-		Py_XDECREF(srcmat);
-		Py_XDECREF(tarmats);
+		Py_DECREF(idprop);
+		Py_DECREF(srcmat);
+		Py_DECREF(tarmats);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1646,10 +1652,10 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase
 		printf("Error in PyConstraint - doConstraint: Function not returning a matrix!\n");
 		con->flag |= PYCON_SCRIPTERROR;
 		
-		Py_XDECREF(idprop);
-		Py_XDECREF(srcmat);
-		Py_XDECREF(tarmats);
-		Py_XDECREF(retval);
+		Py_DECREF(idprop);
+		Py_DECREF(srcmat);
+		Py_DECREF(tarmats);
+		Py_DECREF(retval);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1663,10 +1669,10 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase
 		printf("Error in PyConstraint - doConstraint: Matrix returned is the wrong size!\n");
 		con->flag |= PYCON_SCRIPTERROR;
 		
-		Py_XDECREF(idprop);
-		Py_XDECREF(srcmat);
-		Py_XDECREF(tarmats);
-		Py_XDECREF(retval);
+		Py_DECREF(idprop);
+		Py_DECREF(srcmat);
+		Py_DECREF(tarmats);
+		Py_DECREF(retval);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1683,10 +1689,10 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase
 	}
 	
 	/* free temp objects */
-	Py_XDECREF(idprop);
-	Py_XDECREF(srcmat);
-	Py_XDECREF(tarmats);
-	Py_XDECREF(retval);
+	Py_DECREF(idprop);
+	Py_DECREF(srcmat);
+	Py_DECREF(tarmats);
+	Py_DECREF(retval);
 	
 	/* clear globals */
 	ReleaseGlobalDictionary(globals);
@@ -1741,10 +1747,10 @@ void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
 		con->flag |= PYCON_SCRIPTERROR;
 		
 		/* free temp objects */
-		Py_XDECREF(tar);
-		Py_XDECREF(subtar);
-		Py_XDECREF(idprop);
-		Py_XDECREF(tarmat);
+		Py_DECREF(tar);
+		Py_DECREF(subtar);
+		Py_DECREF(idprop);
+		Py_DECREF(tarmat);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1753,17 +1759,17 @@ void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
 		return;
 	}
 
-	Py_XDECREF(retval);
+	Py_DECREF(retval);
 	retval = NULL;
 	
 	/* try to find doTarget function to set the target matrix */
 	gval = PyDict_GetItemString(globals, "doTarget");
 	if (!gval) {
 		/* free temp objects */
-		Py_XDECREF(tar);
-		Py_XDECREF(subtar);
-		Py_XDECREF(idprop);
-		Py_XDECREF(tarmat);
+		Py_DECREF(tar);
+		Py_DECREF(subtar);
+		Py_DECREF(idprop);
+		Py_DECREF(tarmat);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1776,16 +1782,16 @@ void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
 	if (PyFunction_Check(gval)) {
 		pyargs = Py_BuildValue("OOOO", tar, subtar, tarmat, idprop);
 		retval = PyObject_CallObject(gval, pyargs);
-		Py_XDECREF(pyargs);
+		Py_DECREF(pyargs);
 	} 
 	else {
 		printf("ERROR: doTarget is supposed to be a function!\n");
 		con->flag |= PYCON_SCRIPTERROR;
 		
-		Py_XDECREF(tar);
-		Py_XDECREF(subtar);
-		Py_XDECREF(idprop);
-		Py_XDECREF(tarmat);
+		Py_DECREF(tar);
+		Py_DECREF(subtar);
+		Py_DECREF(idprop);
+		Py_DECREF(tarmat);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1800,10 +1806,10 @@ void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
 		
 		
 		/* free temp objects */
-		Py_XDECREF(tar);
-		Py_XDECREF(subtar);
-		Py_XDECREF(idprop);
-		Py_XDECREF(tarmat);
+		Py_DECREF(tar);
+		Py_DECREF(subtar);
+		Py_DECREF(idprop);
+		Py_DECREF(tarmat);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1815,11 +1821,11 @@ void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
 	if (!PyObject_TypeCheck(retval, &matrix_Type)) {
 		con->flag |= PYCON_SCRIPTERROR;
 		
-		Py_XDECREF(tar);
-		Py_XDECREF(subtar);
-		Py_XDECREF(idprop);
-		Py_XDECREF(tarmat);
-		Py_XDECREF(retval);
+		Py_DECREF(tar);
+		Py_DECREF(subtar);
+		Py_DECREF(idprop);
+		Py_DECREF(tarmat);
+		Py_DECREF(retval);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1833,11 +1839,11 @@ void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
 		printf("Error in PyConstraint - doTarget: Matrix returned is the wrong size!\n");
 		con->flag |= PYCON_SCRIPTERROR;
 		
-		Py_XDECREF(tar);
-		Py_XDECREF(subtar);
-		Py_XDECREF(idprop);
-		Py_XDECREF(tarmat);
-		Py_XDECREF(retval);
+		Py_DECREF(tar);
+		Py_DECREF(subtar);
+		Py_DECREF(idprop);
+		Py_DECREF(tarmat);
+		Py_DECREF(retval);
 		
 		ReleaseGlobalDictionary(globals);
 
@@ -1854,11 +1860,11 @@ void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
 	}
 	
 	/* free temp objects */
-	Py_XDECREF(tar);
-	Py_XDECREF(subtar);
-	Py_XDECREF(idprop);
-	Py_XDECREF(tarmat);
-	Py_XDECREF(retval);
+	Py_DECREF(tar);
+	Py_DECREF(subtar);
+	Py_DECREF(idprop);
+	Py_DECREF(tarmat);
+	Py_DECREF(retval);
 	
 	/* clear globals */
 	ReleaseGlobalDictionary(globals);
@@ -1893,7 +1899,7 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
 		con->flag |= PYCON_SCRIPTERROR;
 		
 		/* free temp objects */
-		Py_XDECREF(idprop);
+		Py_DECREF(idprop);
 		
 		PyGILState_Release(gilstate);
 		
@@ -1909,7 +1915,7 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
 		
 		/* free temp objects */
 		ReleaseGlobalDictionary( globals );
-		Py_XDECREF(idprop);
+		Py_DECREF(idprop);
 
 		PyGILState_Release(gilstate);
 
@@ -1924,7 +1930,7 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
 		printf("ERROR: getSettings is supposed to be a function!\n");
 		ReleaseGlobalDictionary( globals );
 		
-		Py_XDECREF(idprop);
+		Py_DECREF(idprop);
 		
 		PyGILState_Release(gilstate);
 		
@@ -1937,7 +1943,7 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
 		
 		/* free temp objects */
 		ReleaseGlobalDictionary(globals);
-		Py_XDECREF(idprop);
+		Py_DECREF(idprop);
 		
 		PyGILState_Release(gilstate);
 		
@@ -1948,7 +1954,7 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
 		ReleaseGlobalDictionary(globals);
 		
 		/* free temp objects */
-		Py_XDECREF(idprop);
+		Py_DECREF(idprop);
 		Py_DECREF(retval);
 		
 		PyGILState_Release(gilstate);
@@ -2103,6 +2109,7 @@ static int bpy_button_eval_error(char *expr) {
 	fprintf(stderr, "\nError in button evaluation:\nThis is the failed Python expression:\n'%s'\n\n", expr);
 
 	PyErr_Print();
+	BPY_Err_Clear();
 
 	return -1;
 }
@@ -2821,91 +2828,11 @@ static void DoAllScriptsFromList( ListBase * list, short event )
 	return;
 }
 
-static PyObject *importText( char *name )
-{
-	Text *text;
-	char txtname[22]; /* 21+NULL */
-	char *buf = NULL;
-	int namelen = strlen( name );
-	
-	if (namelen>21-3) return NULL; /* we know this cant be importable, the name is too long for blender! */
-	
-	memcpy( txtname, name, namelen );
-	memcpy( &txtname[namelen], ".py", 4 );
-
-	for(text = G.main->text.first; text; text = text->id.next) {
-		if( !strcmp( txtname, text->id.name+2 ) )
-			break;
-	}
-
-	if( !text )
-		return NULL;
-
-	if( !text->compiled ) {
-		buf = txt_to_buf( text );
-		text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
-		MEM_freeN( buf );
-
-		if( PyErr_Occurred(  ) ) {
-			PyErr_Print(  );
-			BPY_free_compiled_text( text );
-			return NULL;
-		}
-	}
-
-	return PyImport_ExecCodeModule( name, text->compiled );
-}
-
-static PyMethodDef bimport[] = {
-	{"blimport", blender_import, METH_KEYWORDS, "our own import"}
-};
-
-static PyObject *blender_import( PyObject * self, PyObject * args,  PyObject * kw)
-{
-	PyObject *exception, *err, *tb;
-	char *name;
-	PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
-	PyObject *m;
-	
-	//PyObject_Print(args, stderr, 0);
-#if (PY_VERSION_HEX >= 0x02060000)
-	int dummy_val; /* what does this do?*/
-	static char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", 0};
-	
-	if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOOi:bimport", kwlist,
-			       &name, &globals, &locals, &fromlist, &dummy_val) )
-		return NULL;
-#else
-	static char *kwlist[] = {"name", "globals", "locals", "fromlist", 0};
-	
-	if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOO:bimport", kwlist,
-			       &name, &globals, &locals, &fromlist ) )
-		return NULL;
-#endif
-	m = PyImport_ImportModuleEx( name, globals, locals, fromlist );
-
-	if( m )
-		return m;
-	else
-		PyErr_Fetch( &exception, &err, &tb );	/*restore for probable later use */
-
-	m = importText( name );
-	if( m ) {		/* found module, ignore above exception */
-		PyErr_Clear(  );
-		Py_XDECREF( exception );
-		Py_XDECREF( err );
-		Py_XDECREF( tb );
-		printf( "imported from text buffer...\n" );
-	} else {
-		PyErr_Restore( exception, err, tb );
-	}
-	return m;
-}
 
 static void init_ourImport( void )
 {
 	PyObject *m, *d;
-	PyObject *import = PyCFunction_New( bimport, NULL );
+	PyObject *import = PyCFunction_New( bpy_import_meth, NULL );
 
 	m = PyImport_AddModule( "__builtin__" );
 	d = PyModule_GetDict( m );
@@ -2913,100 +2840,10 @@ static void init_ourImport( void )
 	EXPP_dict_set_item_str( d, "__import__", import );
 }
 
-/*
- * find in-memory module and recompile
- */
-
-static PyObject *reimportText( PyObject *module )
-{
-	Text *text;
-	char *txtname;
-	char *name;
-	char *buf = NULL;
-
-	/* get name, filename from the module itself */
-
-	txtname = PyModule_GetFilename( module );
-	name = PyModule_GetName( module );
-	if( !txtname || !name)
-		return NULL;
-
-	/* look up the text object */
-	text = ( Text * ) & ( G.main->text.first );
-	while( text ) {
-		if( !strcmp( txtname, text->id.name+2 ) )
-			break;
-		text = text->id.next;
-	}
-
-	/* uh-oh.... didn't find it */
-	if( !text )
-		return NULL;
-
-	/* if previously compiled, free the object */
-	/* (can't see how could be NULL, but check just in case) */ 
-	if( text->compiled ){
-		Py_DECREF( (PyObject *)text->compiled );
-	}
-
-	/* compile the buffer */
-	buf = txt_to_buf( text );
-	text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
-	MEM_freeN( buf );
-
-	/* if compile failed.... return this error */
-	if( PyErr_Occurred(  ) ) {
-		PyErr_Print(  );
-		BPY_free_compiled_text( text );
-		return NULL;
-	}
-
-	/* make into a module */
-	return PyImport_ExecCodeModule( name, text->compiled );
-}
-
-/*
- * our reload() module, to handle reloading in-memory scripts
- */
-
-static PyObject *blender_reload( PyObject * self, PyObject * args )
-{
-	PyObject *exception, *err, *tb;
-	PyObject *module = NULL;
-	PyObject *newmodule = NULL;
-
-	/* check for a module arg */
-	if( !PyArg_ParseTuple( args, "O:breload", &module ) )
-		return NULL;
-
-	/* try reimporting from file */
-	newmodule = PyImport_ReloadModule( module );
-	if( newmodule )
-		return newmodule;
-
-	/* no file, try importing from memory */
-	PyErr_Fetch( &exception, &err, &tb );	/*restore for probable later use */
-
-	newmodule = reimportText( module );
-	if( newmodule ) {		/* found module, ignore above exception */
-		PyErr_Clear(  );
-		Py_XDECREF( exception );
-		Py_XDECREF( err );
-		Py_XDECREF( tb );
-	} else
-		PyErr_Restore( exception, err, tb );
-
-	return newmodule;
-}
-
-static PyMethodDef breload[] = {
-	{"blreload", blender_reload, METH_VARARGS, "our own reload"}
-};
-
 static void init_ourReload( void )
 {
 	PyObject *m, *d;
-	PyObject *reload = PyCFunction_New( breload, NULL );
+	PyObject *reload = PyCFunction_New( bpy_reload_meth, NULL );
 
 	m = PyImport_AddModule( "__builtin__" );
 	d = PyModule_GetDict( m );
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index 670041a6504b4eb9a214b10a1b4c8b35755927ce..e06cf1840c55bf9c40ea0d7dc8717df320546ea0 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -14,17 +14,22 @@ defs = []
 if env['OURPLATFORM'] in ('win32-mingw') and env['BF_DEBUG']:
 	defs.append('Py_TRACE_REFS')
 
+if env['BF_DEBUG']:
+	defs.append('_DEBUG')
+
 if env['WITH_BF_QUICKTIME']:
 	incs += ' ' + env['BF_QUICKTIME_INC']
 	defs.append('WITH_QUICKTIME')
 	
 if env['WITH_BF_OPENEXR']:
-    defs.append('WITH_OPENEXR')
+	defs.append('WITH_OPENEXR')
 
 if env['WITH_BF_FFMPEG']:
-    defs.append('WITH_FFMPEG')
+	defs.append('WITH_FFMPEG')
 
 if env['BF_BUILDINFO']:
-    defs.append('NAN_BUILDINFO')
+	defs.append('NAN_BUILDINFO')
 
-env.BlenderLib ( libname='blender_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype=['core','game2'], priority = [60,115] )
+# A bit dodgy but disable building with python3
+if not env['BF_PYTHON_VERSION'].startswith('3'):
+	env.BlenderLib ( libname='blender_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype=['core','game2'], priority = [60,115] )
diff --git a/source/blender/python/api2_2x/BGL.c b/source/blender/python/api2_2x/BGL.c
index 2503a66250bf9a055c4c69cacf095ef818cf174e..7735f2b444f6a6ccf2254d2738985bafbf2dc25b 100644
--- a/source/blender/python/api2_2x/BGL.c
+++ b/source/blender/python/api2_2x/BGL.c
@@ -35,7 +35,6 @@
 #include "BGL.h" /*This must come first */
 
 #include "MEM_guardedalloc.h"
-#include "gen_utils.h"
 
 static int type_size( int type );
 static Buffer *make_buffer( int type, int ndimensions, int *dimensions );
@@ -121,8 +120,6 @@ static PyObject *Method_##funcname (PyObject *self, PyObject *args) {\
 
 /* #endif */
 
-PyObject *BGL_Init( void );
-
 /********/
 static int type_size(int type)
 {
@@ -185,12 +182,12 @@ static PyObject *Method_Buffer (PyObject *self, PyObject *args)
 	int i, type;
 	int *dimensions = 0, ndimensions = 0;
 	
-	if (!PyArg_ParseTuple(args, "iO|O", &type, &length_ob, &template))
-	        return EXPP_ReturnPyObjError(PyExc_AttributeError,
-	                        "expected an int and one or two PyObjects");
-
+	if (!PyArg_ParseTuple(args, "iO|O", &type, &length_ob, &template)) {
+		PyErr_SetString(PyExc_AttributeError, "expected an int and one or two PyObjects");
+		return NULL;
+	}
 	if (type!=GL_BYTE && type!=GL_SHORT && type!=GL_INT && type!=GL_FLOAT && type!=GL_DOUBLE) {
-		PyErr_SetString(PyExc_AttributeError, "type");
+		PyErr_SetString(PyExc_AttributeError, "invalid first argument type, should be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE");
 		return NULL;
 	}
 
@@ -1088,19 +1085,38 @@ static struct PyMethodDef BGL_methods[] = {
 	{NULL, NULL, 0, NULL}
 };
 
-PyObject *BGL_Init(void) 
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef BGL_module_def = {
+	{}, /* m_base */
+	"BGL",  /* m_name */
+	0,  /* m_doc */
+	0,  /* m_size */
+	BGL_methods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
+
+PyObject *BGL_Init(const char *from) 
 {
-	PyObject *mod= Py_InitModule("Blender.BGL", BGL_methods);
-	PyObject *dict= PyModule_GetDict(mod);
+	PyObject *mod, *dict, *item;
+#if (PY_VERSION_HEX >= 0x03000000)
+	mod = PyModule_Create(&BGL_module_def);
+#else
+	mod= Py_InitModule(from, BGL_methods);
+#endif
+	dict= PyModule_GetDict(mod);
 	
 	if( PyType_Ready( &buffer_Type) < 0)
-		Py_RETURN_NONE;
+		return NULL; /* should never happen */
 
-#define EXPP_ADDCONST(x) EXPP_dict_set_item_str(dict, #x, PyInt_FromLong((int)x))
+#define EXPP_ADDCONST(x) PyDict_SetItemString(dict, #x, item=PyInt_FromLong((int)x)); Py_DECREF(item)
 
 /* So, for example:
  * EXPP_ADDCONST(GL_CURRENT_BIT) becomes
- * EXPP_dict_set_item_str(dict, "GL_CURRENT_BIT", PyInt_FromLong(GL_CURRENT_BIT)) */
+ * PyDict_SetItemString(dict, "GL_CURRENT_BIT", item=PyInt_FromLong(GL_CURRENT_BIT)); Py_DECREF(item) */
 
 	EXPP_ADDCONST(GL_CURRENT_BIT);
 	EXPP_ADDCONST(GL_POINT_BIT);
diff --git a/source/blender/python/api2_2x/BGL.h b/source/blender/python/api2_2x/BGL.h
index 461f5bc93724cad00be25b0d5f286bc7e45f1740..bad6330dd8d2e11a42d27ac19ca6bedd643873f0 100644
--- a/source/blender/python/api2_2x/BGL.h
+++ b/source/blender/python/api2_2x/BGL.h
@@ -43,6 +43,7 @@
 #include <Python.h>
 #include "BIF_gl.h"
 
+PyObject *BGL_Init( const char *from );
 
 /*@ Buffer Object */
 /*@ For Python access to OpenGL functions requiring a pointer. */
@@ -303,7 +304,8 @@ typedef struct _Buffer {
 
 #define ret_def_void
 #define ret_set_void
-#define ret_ret_void    return EXPP_incr_ret(Py_None)
+/* would use Py_RETURN_NONE - except for py 2.3 doesnt have it */
+#define ret_ret_void    { Py_INCREF(Py_None); return Py_None; }
 
 #define ret_def_GLint   int ret_int
 #define ret_set_GLint   ret_int=
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index d09506f731b751329d3f4296cb863a346fc3e665..fd316eb484f357bd47eb8d9388892fd70f4cc10e 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -1074,7 +1074,7 @@ void M_Blender_Init(void)
 
 	PyDict_SetItemString(dict, "Armature", Armature_Init());
 	PyDict_SetItemString(dict, "BezTriple", BezTriple_Init());
-	PyDict_SetItemString(dict, "BGL", BGL_Init());
+	PyDict_SetItemString(dict, "BGL", BGL_Init("Blender.BGL"));
 	PyDict_SetItemString(dict, "CurNurb", CurNurb_Init());
 	PyDict_SetItemString(dict, "Constraint", Constraint_Init());
 	PyDict_SetItemString(dict, "Curve", Curve_Init());
@@ -1092,7 +1092,7 @@ void M_Blender_Init(void)
 	PyDict_SetItemString(dict, "Mesh", Mesh_Init()); 
 	PyDict_SetItemString(dict, "Metaball", Metaball_Init());
 	PyDict_SetItemString(dict, "Mathutils", Mathutils_Init("Blender.Mathutils"));
-	PyDict_SetItemString(dict, "Geometry", Geometry_Init());
+	PyDict_SetItemString(dict, "Geometry", Geometry_Init("Blender.Geometry"));
 	PyDict_SetItemString(dict, "Modifier", Modifier_Init());
 	PyDict_SetItemString(dict, "NMesh", NMesh_Init());
 	PyDict_SetItemString(dict, "Node", Node_Init());
diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c
index 2af2261808b34409177a56368e8e3def32261e80..7e3f57da60dd42ff3fac6b6b938392ac54e3a839 100644
--- a/source/blender/python/api2_2x/Draw.c
+++ b/source/blender/python/api2_2x/Draw.c
@@ -614,6 +614,9 @@ static void exit_pydraw( SpaceScript * sc, short err )
 
 	if( err ) {
 		PyErr_Print(  );
+		PyErr_Clear(  );
+		PySys_SetObject("last_traceback", NULL);
+		
 		script->flags = 0;	/* mark script struct for deletion */
 		SCRIPT_SET_NULL(script);
 		script->scriptname[0] = '\0';
@@ -838,6 +841,8 @@ static void exec_but_callback(void *pyobj, void *data)
 	if (!result) {
 		Py_DECREF(pyvalue);
 		PyErr_Print(  );
+		PyErr_Clear(  );
+		PySys_SetObject("last_traceback", NULL);
 		error_pyscript(  );
 	}
 	Py_XDECREF( result );
@@ -910,12 +915,12 @@ static PyObject *Method_Exit( PyObject * self )
 	exit_pydraw( sc, 0 );
 
 	script = sc->script;
-
-	/* remove our lock to the current namespace */
-	script->flags &= ~SCRIPT_GUI;
-	script->scriptname[0] = '\0';
-	script->scriptarg[0] = '\0';
-
+	if(script) { /* in very rare cases this can be NULL, (when saving and loading see bug #18654)*/
+		/* remove our lock to the current namespace */
+		script->flags &= ~SCRIPT_GUI;
+		script->scriptname[0] = '\0';
+		script->scriptarg[0] = '\0';
+	}
 	Py_RETURN_NONE;
 }
 
@@ -1129,6 +1134,8 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args )
 	
 	if (!result) {
 		PyErr_Print(  );
+		PyErr_Clear(  );
+		PySys_SetObject("last_traceback", NULL);
 		error_pyscript(  );
 	} else {
 		/* copied from do_clever_numbuts in toolbox.c */
diff --git a/source/blender/python/api2_2x/Geometry.c b/source/blender/python/api2_2x/Geometry.c
index 89c63870d5987a1b2be6f4520c7a412b5c0cfe38..2ac6b8a714a19cf661fd77271398d0b24c5e587f 100644
--- a/source/blender/python/api2_2x/Geometry.c
+++ b/source/blender/python/api2_2x/Geometry.c
@@ -38,11 +38,9 @@
 #include "BKE_displist.h"
 #include "MEM_guardedalloc.h"
 #include "BLI_blenlib.h"
-
-/* needed for EXPP_ReturnPyObjError and EXPP_check_sequence_consistency */
-#include "gen_utils.h"
  
 #include "BKE_utildefines.h"
+#include "BKE_curve.h"
 #include "BLI_boxpack2d.h"
 #include "BLI_arithb.h"
 
@@ -56,16 +54,18 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args
 static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args );
 static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args );
 static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * args );
+static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args );
 
 
 /*-------------------------DOC STRINGS ---------------------------*/
 static char M_Geometry_doc[] = "The Blender Geometry module\n\n";
 static char M_Geometry_PolyFill_doc[] = "(veclist_list) - takes a list of polylines (each point a vector) and returns the point indicies for a polyline filled with triangles";
 static char M_Geometry_LineIntersect2D_doc[] = "(lineA_p1, lineA_p2, lineB_p1, lineB_p2) - takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None";
-static char M_Geometry_ClosestPointOnLine_doc[] = "(pt, line_p1, line_p2) - takes a point and a line and returns a (Vector, Bool) for the point on the line, and the bool so you can know if the point was between the 2 points";
+static char M_Geometry_ClosestPointOnLine_doc[] = "(pt, line_p1, line_p2) - takes a point and a line and returns a (Vector, float) for the point on the line, and the bool so you can know if the point was between the 2 points";
 static char M_Geometry_PointInTriangle2D_doc[] = "(pt, tri_p1, tri_p2, tri_p3) - takes 4 vectors, one is the point and the next 3 define the triangle, only the x and y are used from the vectors";
 static char M_Geometry_PointInQuad2D_doc[] = "(pt, quad_p1, quad_p2, quad_p3, quad_p4) - takes 5 vectors, one is the point and the next 4 define the quad, only the x and y are used from the vectors";
 static char M_Geometry_BoxPack2D_doc[] = "";
+static char M_Geometry_BezierInterp_doc[] = "";
 /*-----------------------METHOD DEFINITIONS ----------------------*/
 struct PyMethodDef M_Geometry_methods[] = {
 	{"PolyFill", ( PyCFunction ) M_Geometry_PolyFill, METH_O, M_Geometry_PolyFill_doc},
@@ -74,15 +74,35 @@ struct PyMethodDef M_Geometry_methods[] = {
 	{"PointInTriangle2D", ( PyCFunction ) M_Geometry_PointInTriangle2D, METH_VARARGS, M_Geometry_PointInTriangle2D_doc},
 	{"PointInQuad2D", ( PyCFunction ) M_Geometry_PointInQuad2D, METH_VARARGS, M_Geometry_PointInQuad2D_doc},
 	{"BoxPack2D", ( PyCFunction ) M_Geometry_BoxPack2D, METH_O, M_Geometry_BoxPack2D_doc},
+	{"BezierInterp", ( PyCFunction ) M_Geometry_BezierInterp, METH_VARARGS, M_Geometry_BezierInterp_doc},
 	{NULL, NULL, 0, NULL}
 };
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef M_Geometry_module_def = {
+	{}, /* m_base */
+	"Geometry",  /* m_name */
+	M_Geometry_doc,  /* m_doc */
+	0,  /* m_size */
+	M_Geometry_methods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
+
 /*----------------------------MODULE INIT-------------------------*/
-PyObject *Geometry_Init(void)
+PyObject *Geometry_Init(const char *from)
 {
 	PyObject *submodule;
-
-	submodule = Py_InitModule3("Blender.Geometry",
-				    M_Geometry_methods, M_Geometry_doc);
+	
+#if (PY_VERSION_HEX >= 0x03000000)
+	submodule = PyModule_Create(&M_Geometry_module_def);
+#else
+	submodule = Py_InitModule3(from, M_Geometry_methods, M_Geometry_doc);
+#endif
+	
 	return (submodule);
 }
 
@@ -92,7 +112,7 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
 {
 	PyObject *tri_list; /*return this list of tri's */
 	PyObject *polyLine, *polyVec;
-	int i, len_polylines, len_polypoints;
+	int i, len_polylines, len_polypoints, ls_error = 0;
 	
 	/* display listbase */
 	ListBase dispbase={NULL, NULL};
@@ -105,8 +125,8 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
 	
 	
 	if(!PySequence_Check(polyLineSeq)) {
-		return EXPP_ReturnPyObjError( PyExc_TypeError,
-					      "expected a sequence of poly lines" );
+		PyErr_SetString( PyExc_TypeError, "expected a sequence of poly lines" );
+		return NULL;
 	}
 	
 	len_polylines = PySequence_Size( polyLineSeq );
@@ -116,19 +136,20 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
 		if (!PySequence_Check(polyLine)) {
 			freedisplist(&dispbase);
 			Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/
-			return EXPP_ReturnPyObjError( PyExc_TypeError,
-				  "One or more of the polylines is not a sequence of Mathutils.Vector's" );
+			PyErr_SetString( PyExc_TypeError, "One or more of the polylines is not a sequence of Mathutils.Vector's" );
+			return NULL;
 		}
 		
 		len_polypoints= PySequence_Size( polyLine );
 		if (len_polypoints>0) { /* dont bother adding edges as polylines */
+#if 0
 			if (EXPP_check_sequence_consistency( polyLine, &vector_Type ) != 1) {
 				freedisplist(&dispbase);
 				Py_DECREF(polyLine);
-				return EXPP_ReturnPyObjError( PyExc_TypeError,
-					  "A point in one of the polylines is not a Mathutils.Vector type" );
+				PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" );
+				return NULL;
 			}
-			
+#endif
 			dl= MEM_callocN(sizeof(DispList), "poly disp");
 			BLI_addtail(&dispbase, dl);
 			dl->type= DL_INDEX3;
@@ -141,13 +162,17 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
 			
 			for( index = 0; index<len_polypoints; ++index, fp+=3) {
 				polyVec= PySequence_GetItem( polyLine, index );
-				
-				fp[0] = ((VectorObject *)polyVec)->vec[0];
-				fp[1] = ((VectorObject *)polyVec)->vec[1];
-				if( ((VectorObject *)polyVec)->size > 2 )
-					fp[2] = ((VectorObject *)polyVec)->vec[2];
-				else
-					fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */
+				if(VectorObject_Check(polyVec)) {
+					fp[0] = ((VectorObject *)polyVec)->vec[0];
+					fp[1] = ((VectorObject *)polyVec)->vec[1];
+					if( ((VectorObject *)polyVec)->size > 2 )
+						fp[2] = ((VectorObject *)polyVec)->vec[2];
+					else
+						fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */
+				}
+				else {
+					ls_error= 1;
+				}
 				
 				totpoints++;
 				Py_DECREF(polyVec);
@@ -156,7 +181,12 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
 		Py_DECREF(polyLine);
 	}
 	
-	if (totpoints) {
+	if(ls_error) {
+		freedisplist(&dispbase); /* possible some dl was allocated */
+		PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" );
+		return NULL;
+	}
+	else if (totpoints) {
 		/* now make the list to return */
 		filldisplist(&dispbase, &dispbase);
 		
@@ -167,8 +197,8 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
 		tri_list= PyList_New(dl->parts);
 		if( !tri_list ) {
 			freedisplist(&dispbase);
-			return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"Geometry.PolyFill failed to make a new list" );
+			PyErr_SetString( PyExc_RuntimeError, "Geometry.PolyFill failed to make a new list" );
+			return NULL;
 		}
 		
 		index= 0;
@@ -181,6 +211,7 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
 		freedisplist(&dispbase);
 	} else {
 		/* no points, do this so scripts dont barf */
+		freedisplist(&dispbase); /* possible some dl was allocated */
 		tri_list= PyList_New(0);
 	}
 	
@@ -197,9 +228,10 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
 	  &vector_Type, &line_a2,
 	  &vector_Type, &line_b1,
 	  &vector_Type, &line_b2)
-	)
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError, "expected 4 vector types\n" ) );
+	) {
+		PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+		return NULL;
+	}
 	
 	a1x= line_a1->vec[0];
 	a1y= line_a1->vec[1];
@@ -293,10 +325,10 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args
 	&vector_Type, &pt,
 	&vector_Type, &line_1,
 	&vector_Type, &line_2)
-	  )
-		return ( EXPP_ReturnPyObjError
-				( PyExc_TypeError, "expected 3 vector types\n" ) );
-	
+	  ) {
+		PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
+		return NULL;
+	}
 	/* accept 2d verts */
 	if (pt->size==3) { VECCOPY(pt_in, pt->vec);}
 	else { pt_in[2]=0.0;	VECCOPY2D(pt_in, pt->vec) }
@@ -325,9 +357,10 @@ static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args
 	  &vector_Type, &tri_p1,
 	  &vector_Type, &tri_p2,
 	  &vector_Type, &tri_p3)
-	)
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError, "expected 4 vector types\n" ) );
+	) {
+		PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+		return NULL;
+	}
 	
 	return PyInt_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
 }
@@ -342,9 +375,10 @@ static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args )
 	  &vector_Type, &quad_p2,
 	  &vector_Type, &quad_p3,
 	  &vector_Type, &quad_p4)
-	)
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError, "expected 5 vector types\n" ) );
+	) {
+		PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
+		return NULL;
+	}
 	
 	return PyInt_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
 }
@@ -357,9 +391,10 @@ static int boxPack_FromPyObject(PyObject * value, boxPack **boxarray )
 	
 	
 	/* Error checking must alredy be done */
-	if( !PyList_Check( value ) )
-		return EXPP_ReturnIntError( PyExc_TypeError,
-				"can only back a list of [x,y,x,w]" );
+	if( !PyList_Check( value ) ) {
+		PyErr_SetString( PyExc_TypeError, "can only back a list of [x,y,x,w]" );
+		return -1;
+	}
 	
 	len = PyList_Size( value );
 	
@@ -370,8 +405,8 @@ static int boxPack_FromPyObject(PyObject * value, boxPack **boxarray )
 		list_item = PyList_GET_ITEM( value, i );
 		if( !PyList_Check( list_item ) || PyList_Size( list_item ) < 4 ) {
 			MEM_freeN(*boxarray);
-			return EXPP_ReturnIntError( PyExc_TypeError,
-					"can only back a list of [x,y,x,w]" );
+			PyErr_SetString( PyExc_TypeError, "can only back a list of [x,y,x,w]" );
+			return -1;
 		}
 		
 		box = (*boxarray)+i;
@@ -381,8 +416,8 @@ static int boxPack_FromPyObject(PyObject * value, boxPack **boxarray )
 		
 		if (!PyNumber_Check(item_1) || !PyNumber_Check(item_2)) {
 			MEM_freeN(*boxarray);
-			return EXPP_ReturnIntError( PyExc_TypeError,
-					"can only back a list of 2d boxes [x,y,x,w]" );
+			PyErr_SetString( PyExc_TypeError, "can only back a list of 2d boxes [x,y,x,w]" );
+			return -1;
 		}
 		
 		box->w =  (float)PyFloat_AsDouble( item_1 );
@@ -418,9 +453,10 @@ static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * boxlist )
 	int len;
 	int error;
 	
-	if(!PyList_Check(boxlist))
-		return EXPP_ReturnPyObjError( PyExc_TypeError,
-					      "expected a sequence of boxes [[x,y,w,h], ... ]" );
+	if(!PyList_Check(boxlist)) {
+		PyErr_SetString( PyExc_TypeError, "expected a sequence of boxes [[x,y,w,h], ... ]" );
+		return NULL;
+	}
 	
 	len = PyList_Size( boxlist );
 	
@@ -437,3 +473,49 @@ static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * boxlist )
 	
 	return Py_BuildValue( "ff", tot_width, tot_height);
 }
+
+static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args )
+{
+	VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
+	int resolu;
+	int dims;
+	int i;
+	float *coord_array, *fp;
+	PyObject *list;
+	
+	float k1[4] = {0.0, 0.0, 0.0, 0.0};
+	float h1[4] = {0.0, 0.0, 0.0, 0.0};
+	float k2[4] = {0.0, 0.0, 0.0, 0.0};
+	float h2[4] = {0.0, 0.0, 0.0, 0.0};
+	
+	float a1x, a1y, a2x, a2y,  b1x, b1y, b2x, b2y, xi, yi, a1,a2,b1,b2, newvec[2];
+	if( !PyArg_ParseTuple ( args, "O!O!O!O!i",
+	  &vector_Type, &vec_k1,
+	  &vector_Type, &vec_h1,
+	  &vector_Type, &vec_h2,
+	  &vector_Type, &vec_k2, &resolu) || (resolu<=1)
+	) {
+		PyErr_SetString( PyExc_TypeError, "expected 4 vector types and an int greater then 1\n" );
+		return NULL;
+	}
+	
+	dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
+	
+	for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i];
+	for(i=0; i < vec_h1->size; i++) h1[i]= vec_h1->vec[i];
+	for(i=0; i < vec_k2->size; i++) k2[i]= vec_k2->vec[i];
+	for(i=0; i < vec_h2->size; i++) h2[i]= vec_h2->vec[i];
+	
+	coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "BezierInterp");
+	for(i=0; i<dims; i++) {
+		forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array+i, resolu-1, dims);
+	}
+	
+	list= PyList_New(resolu);
+	fp= coord_array;
+	for(i=0; i<resolu; i++, fp= fp+dims) {
+		PyList_SET_ITEM(list, i, newVectorObject(fp, dims, Py_NEW));
+	}
+	MEM_freeN(coord_array);
+	return list;
+}
diff --git a/source/blender/python/api2_2x/Geometry.h b/source/blender/python/api2_2x/Geometry.h
index d7de95610787277a24a56301bf2b184f596e1074..ebfb054c54aa367e574c555d314b46e7b8bcf1d7 100644
--- a/source/blender/python/api2_2x/Geometry.h
+++ b/source/blender/python/api2_2x/Geometry.h
@@ -32,8 +32,8 @@
 #define EXPP_Geometry_H
 
 #include <Python.h>
-#include "vector.h"
+#include "Mathutils.h"
 
-PyObject *Geometry_Init( void );
+PyObject *Geometry_Init( const char *from );
 
 #endif				/* EXPP_Geometry_H */
diff --git a/source/blender/python/api2_2x/Group.c b/source/blender/python/api2_2x/Group.c
index 0998053e7e13bbbccafa31013ae25c1eb356be4c..eefa6fe58d6ba6ef9727e0d144989b2ff5fe4a1c 100644
--- a/source/blender/python/api2_2x/Group.c
+++ b/source/blender/python/api2_2x/Group.c
@@ -46,7 +46,7 @@
 #include "gen_utils.h"
 #include "gen_library.h"
 
-#include "vector.h"
+#include "Mathutils.h"
 
 /* checks for the group being removed */
 #define GROUP_DEL_CHECK_PY(bpy_group) if (!(bpy_group->group)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Group has been removed" ) )
diff --git a/source/blender/python/api2_2x/Key.c b/source/blender/python/api2_2x/Key.c
index 856dabdde745e90bd61d6c8e5a60efcaa5e2a3d1..45a68bfa0e6f1ae890f25b6a72244458d390727a 100644
--- a/source/blender/python/api2_2x/Key.c
+++ b/source/blender/python/api2_2x/Key.c
@@ -29,7 +29,7 @@
  */
 
 #include "Key.h" /*This must come first*/
-#include "vector.h"
+#include "Mathutils.h"
 
 #include "DNA_scene_types.h"
 
diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c
index 799833d4ee01cd649cefc95eea70c9b6a5be60ff..3b7a785f32e1deffd715a58c1bdcecf7212f54b2 100644
--- a/source/blender/python/api2_2x/Lamp.c
+++ b/source/blender/python/api2_2x/Lamp.c
@@ -191,6 +191,7 @@ static PyObject *Lamp_getTypesConst( void );
 static PyObject *Lamp_getMode( BPy_Lamp * self );
 static PyObject *Lamp_getModesConst( void );
 static PyObject *Lamp_getSamples( BPy_Lamp * self );
+static PyObject *Lamp_getSampleBuffers( BPy_Lamp * self );
 static PyObject *Lamp_getRaySamplesX( BPy_Lamp * self );
 static PyObject *Lamp_getRaySamplesY( BPy_Lamp * self );
 static PyObject *Lamp_getAreaSizeX( BPy_Lamp * self );
@@ -241,6 +242,7 @@ static int Lamp_setIpo( BPy_Lamp * self, PyObject * args );
 static int Lamp_setType( BPy_Lamp * self, PyObject * args );
 static int Lamp_setMode( BPy_Lamp * self, PyObject * args );
 static int Lamp_setSamples( BPy_Lamp * self, PyObject * args );
+static int Lamp_setSampleBuffers( BPy_Lamp * self, PyObject * args );
 static int Lamp_setRaySamplesX( BPy_Lamp * self, PyObject * args );
 static int Lamp_setRaySamplesY( BPy_Lamp * self, PyObject * args );
 static int Lamp_setAreaSizeX( BPy_Lamp * self, PyObject * args );
@@ -447,6 +449,10 @@ static PyGetSetDef BPy_Lamp_getseters[] = {
 	 (getter)Lamp_getSamples, (setter)Lamp_setSamples,
 	 "Lamp shadow map samples",
 	 NULL},
+	{"sampleBuffers",
+	 (getter)Lamp_getSampleBuffers, (setter)Lamp_setSampleBuffers,
+	 "Lamp shadow samples buffers",
+	 NULL},
 	{"raySamplesX",
 	 (getter)Lamp_getRaySamplesX, (setter)Lamp_setRaySamplesX,
 	 "Lamp raytracing samples on the X axis",
@@ -923,6 +929,11 @@ static PyObject *Lamp_getSamples( BPy_Lamp * self )
 	return PyInt_FromLong( self->lamp->samp );
 }
 
+static PyObject *Lamp_getSampleBuffers( BPy_Lamp * self )
+{
+	return PyInt_FromLong( self->lamp->buffers );
+}
+
 static PyObject *Lamp_getRaySamplesX( BPy_Lamp * self )
 {
 	return PyInt_FromLong( self->lamp->ray_samp );
@@ -1063,6 +1074,23 @@ static int Lamp_setSamples( BPy_Lamp * self, PyObject * value )
 								EXPP_LAMP_SAMPLES_MAX, 'h' );
 }
 
+static int Lamp_setSampleBuffers( BPy_Lamp * self, PyObject * value )
+{
+	int buffers= 1;
+	if( !PyInt_Check ( value ) ) {
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
+	}
+	buffers= PyInt_AS_LONG(value);
+
+	if(buffers!=1 && buffers!=4 && buffers!=9) {
+		return EXPP_ReturnIntError( PyExc_TypeError,
+						"expected int argument of value 1, 4 or 9" );
+	}
+
+	self->lamp->buffers= buffers;
+
+	return 0;
+}
 
 static int Lamp_setRaySamplesX( BPy_Lamp * self, PyObject * value )
 {
diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c
index b370aa0e1e830b64f2b060eb3ab263b9ab3efdab..8f99723e12d3b10c381503f0ffffcf5eda8d6e79 100644
--- a/source/blender/python/api2_2x/Mathutils.c
+++ b/source/blender/python/api2_2x/Mathutils.c
@@ -69,7 +69,6 @@ static char M_Mathutils_TriangleArea_doc[] = "(v1, v2, v3) - returns the area si
 static char M_Mathutils_TriangleNormal_doc[] = "(v1, v2, v3) - returns the normal of the 3D triangle defined";
 static char M_Mathutils_QuadNormal_doc[] = "(v1, v2, v3, v4) - returns the normal of the 3D quad defined";
 static char M_Mathutils_LineIntersect_doc[] = "(v1, v2, v3, v4) - returns a tuple with the points on each line respectively closest to the other";
-static char M_Mathutils_Point_doc[] = "Creates a 2d or 3d point object";
 //-----------------------METHOD DEFINITIONS ----------------------
 struct PyMethodDef M_Mathutils_methods[] = {
 	{"Rand", (PyCFunction) M_Mathutils_Rand, METH_VARARGS, M_Mathutils_Rand_doc},
@@ -103,20 +102,32 @@ struct PyMethodDef M_Mathutils_methods[] = {
 	{"TriangleNormal", ( PyCFunction ) M_Mathutils_TriangleNormal, METH_VARARGS, M_Mathutils_TriangleNormal_doc},
 	{"QuadNormal", ( PyCFunction ) M_Mathutils_QuadNormal, METH_VARARGS, M_Mathutils_QuadNormal_doc},
 	{"LineIntersect", ( PyCFunction ) M_Mathutils_LineIntersect, METH_VARARGS, M_Mathutils_LineIntersect_doc},
-	{"Point", (PyCFunction) M_Mathutils_Point, METH_VARARGS, M_Mathutils_Point_doc},
 	{NULL, NULL, 0, NULL}
 };
 /*----------------------------MODULE INIT-------------------------*/
 /* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef M_Mathutils_module_def = {
+	{}, /* m_base */
+	"Mathutils",  /* m_name */
+	M_Mathutils_doc,  /* m_doc */
+	0,  /* m_size */
+	M_Mathutils_methods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
+
 PyObject *Mathutils_Init(const char *from)
 {
 	PyObject *submodule;
 
 	//seed the generator for the rand function
-	BLI_srand((unsigned int) (PIL_check_seconds_timer() *
-				      0x7FFFFFFF));
+	BLI_srand((unsigned int) (PIL_check_seconds_timer() * 0x7FFFFFFF));
 	
-	/* needed for getseters */
 	if( PyType_Ready( &vector_Type ) < 0 )
 		return NULL;
 	if( PyType_Ready( &matrix_Type ) < 0 )
@@ -126,9 +137,15 @@ PyObject *Mathutils_Init(const char *from)
 	if( PyType_Ready( &quaternion_Type ) < 0 )
 		return NULL;
 	
+#if (PY_VERSION_HEX >= 0x03000000)
+	submodule = PyModule_Create(&M_Mathutils_module_def);
+#else
 	submodule = Py_InitModule3(from, M_Mathutils_methods, M_Mathutils_doc);
+#endif
+	
 	return (submodule);
 }
+
 //-----------------------------METHODS----------------------------
 //----------------column_vector_multiplication (internal)---------
 //COLUMN VECTOR Multiplication (Matrix X Vector)
@@ -144,8 +161,8 @@ PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
 
 	if(mat->rowSize != vec->size){
 		if(mat->rowSize == 4 && vec->size != 3){
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"matrix * vector: matrix row size and vector size must be the same");
+			PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
+			return NULL;
 		}else{
 			vecCopy[3] = 1.0f;
 		}
@@ -164,36 +181,7 @@ PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
 	}
 	return newVectorObject(vecNew, vec->size, Py_NEW);
 }
-//This is a helper for point/matrix translation 
-
-PyObject *column_point_multiplication(MatrixObject * mat, PointObject* pt)
-{
-	float ptNew[4], ptCopy[4];
-	double dot = 0.0f;
-	int x, y, z = 0;
-
-	if(mat->rowSize != pt->size){
-		if(mat->rowSize == 4 && pt->size != 3){
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"matrix * point: matrix row size and point size must be the same\n");
-		}else{
-			ptCopy[3] = 0.0f;
-		}
-	}
 
-	for(x = 0; x < pt->size; x++){
-		ptCopy[x] = pt->coord[x];
-		}
-
-	for(x = 0; x < mat->rowSize; x++) {
-		for(y = 0; y < mat->colSize; y++) {
-			dot += mat->matrix[x][y] * ptCopy[y];
-		}
-		ptNew[z++] = (float)dot;
-		dot = 0.0f;
-	}
-	return newPointObject(ptNew, pt->size, Py_NEW);
-}
 //-----------------row_vector_multiplication (internal)-----------
 //ROW VECTOR Multiplication - Vector X Matrix
 //[x][y][z] *  [1][2][3]
@@ -208,8 +196,8 @@ PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
 
 	if(mat->colSize != vec_size){
 		if(mat->rowSize == 4 && vec_size != 3){
-			return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-				"vector * matrix: matrix column size and the vector size must be the same");
+			PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
+			return NULL;
 		}else{
 			vecCopy[3] = 1.0f;
 		}
@@ -229,36 +217,7 @@ PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
 	}
 	return newVectorObject(vecNew, vec_size, Py_NEW);
 }
-//This is a helper for the point class
-PyObject *row_point_multiplication(PointObject* pt, MatrixObject * mat)
-{
-	float ptNew[4], ptCopy[4];
-	double dot = 0.0f;
-	int x, y, z = 0, size;
 
-	if(mat->colSize != pt->size){
-		if(mat->rowSize == 4 && pt->size != 3){
-			return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-				"point * matrix: matrix column size and the point size must be the same\n");
-		}else{
-			ptCopy[3] = 0.0f;
-		}
-	}
-	size = pt->size;
-	for(x = 0; x < pt->size; x++){
-		ptCopy[x] = pt->coord[x];
-	}
-
-	//muliplication
-	for(x = 0; x < mat->colSize; x++) {
-		for(y = 0; y < mat->rowSize; y++) {
-			dot += mat->matrix[y][x] * ptCopy[y];
-		}
-		ptNew[z++] = (float)dot;
-		dot = 0.0f;
-	}
-	return newPointObject(ptNew, size, Py_NEW);
-}
 //-----------------quat_rotation (internal)-----------
 //This function multiplies a vector/point * quat or vice versa
 //to rotate the point/vector by the quaternion
@@ -268,7 +227,6 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
 	float rot[3];
 	QuaternionObject *quat = NULL;
 	VectorObject *vec = NULL;
-	PointObject *pt = NULL;
 
 	if(QuaternionObject_Check(arg1)){
 		quat = (QuaternionObject*)arg1;
@@ -287,21 +245,6 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
 				quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] - 
 				quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
 			return newVectorObject(rot, 3, Py_NEW);
-		}else if(PointObject_Check(arg2)){
-			pt = (PointObject*)arg2;
-			rot[0] = quat->quat[0]*quat->quat[0]*pt->coord[0] + 2*quat->quat[2]*quat->quat[0]*pt->coord[2] - 
-				2*quat->quat[3]*quat->quat[0]*pt->coord[1] + quat->quat[1]*quat->quat[1]*pt->coord[0] + 
-				2*quat->quat[2]*quat->quat[1]*pt->coord[1] + 2*quat->quat[3]*quat->quat[1]*pt->coord[2] - 
-				quat->quat[3]*quat->quat[3]*pt->coord[0] - quat->quat[2]*quat->quat[2]*pt->coord[0];
-			rot[1] = 2*quat->quat[1]*quat->quat[2]*pt->coord[0] + quat->quat[2]*quat->quat[2]*pt->coord[1] + 
-				2*quat->quat[3]*quat->quat[2]*pt->coord[2] + 2*quat->quat[0]*quat->quat[3]*pt->coord[0] - 
-				quat->quat[3]*quat->quat[3]*pt->coord[1] + quat->quat[0]*quat->quat[0]*pt->coord[1] - 
-				2*quat->quat[1]*quat->quat[0]*pt->coord[2] - quat->quat[1]*quat->quat[1]*pt->coord[1];
-			rot[2] = 2*quat->quat[1]*quat->quat[3]*pt->coord[0] + 2*quat->quat[2]*quat->quat[3]*pt->coord[1] + 
-				quat->quat[3]*quat->quat[3]*pt->coord[2] - 2*quat->quat[0]*quat->quat[2]*pt->coord[0] - 
-				quat->quat[2]*quat->quat[2]*pt->coord[2] + 2*quat->quat[0]*quat->quat[1]*pt->coord[1] - 
-				quat->quat[1]*quat->quat[1]*pt->coord[2] + quat->quat[0]*quat->quat[0]*pt->coord[2];
-			return newPointObject(rot, 3, Py_NEW);
 		}
 	}else if(VectorObject_Check(arg1)){
 		vec = (VectorObject*)arg1;
@@ -321,28 +264,11 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
 				quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
 			return newVectorObject(rot, 3, Py_NEW);
 		}
-	}else if(PointObject_Check(arg1)){
-		pt = (PointObject*)arg1;
-		if(QuaternionObject_Check(arg2)){
-			quat = (QuaternionObject*)arg2;
-			rot[0] = quat->quat[0]*quat->quat[0]*pt->coord[0] + 2*quat->quat[2]*quat->quat[0]*pt->coord[2] - 
-				2*quat->quat[3]*quat->quat[0]*pt->coord[1] + quat->quat[1]*quat->quat[1]*pt->coord[0] + 
-				2*quat->quat[2]*quat->quat[1]*pt->coord[1] + 2*quat->quat[3]*quat->quat[1]*pt->coord[2] - 
-				quat->quat[3]*quat->quat[3]*pt->coord[0] - quat->quat[2]*quat->quat[2]*pt->coord[0];
-			rot[1] = 2*quat->quat[1]*quat->quat[2]*pt->coord[0] + quat->quat[2]*quat->quat[2]*pt->coord[1] + 
-				2*quat->quat[3]*quat->quat[2]*pt->coord[2] + 2*quat->quat[0]*quat->quat[3]*pt->coord[0] - 
-				quat->quat[3]*quat->quat[3]*pt->coord[1] + quat->quat[0]*quat->quat[0]*pt->coord[1] - 
-				2*quat->quat[1]*quat->quat[0]*pt->coord[2] - quat->quat[1]*quat->quat[1]*pt->coord[1];
-			rot[2] = 2*quat->quat[1]*quat->quat[3]*pt->coord[0] + 2*quat->quat[2]*quat->quat[3]*pt->coord[1] + 
-				quat->quat[3]*quat->quat[3]*pt->coord[2] - 2*quat->quat[0]*quat->quat[2]*pt->coord[0] - 
-				quat->quat[2]*quat->quat[2]*pt->coord[2] + 2*quat->quat[0]*quat->quat[1]*pt->coord[1] - 
-				quat->quat[1]*quat->quat[1]*pt->coord[2] + quat->quat[0]*quat->quat[0]*pt->coord[2];
-			return newPointObject(rot, 3, Py_NEW);
-		}
 	}
 
-	return (EXPP_ReturnPyObjError(PyExc_RuntimeError,
-		"quat_rotation(internal): internal problem rotating vector/point\n"));
+	PyErr_SetString(PyExc_RuntimeError, "quat_rotation(internal): internal problem rotating vector/point\n");
+	return NULL;
+	
 }
 
 //----------------------------------Mathutils.Rand() --------------------
@@ -355,14 +281,15 @@ PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args)
 	high = 1.0;
 	low = 0.0;
 
-	if(!PyArg_ParseTuple(args, "|ff", &low, &high))
-		return (EXPP_ReturnPyObjError(PyExc_TypeError,
-			"Mathutils.Rand(): expected nothing or optional (float, float)\n"));
-
-	if((high < low) || (high < 0 && low > 0))
-		return (EXPP_ReturnPyObjError(PyExc_ValueError,
-			"Mathutils.Rand(): high value should be larger than low value\n"));
+	if(!PyArg_ParseTuple(args, "|ff", &low, &high)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.Rand(): expected nothing or optional (float, float)\n");
+		return NULL;
+	}
 
+	if((high < low) || (high < 0 && low > 0)) {
+		PyErr_SetString(PyExc_ValueError, "Mathutils.Rand(): high value should be larger than low value\n");
+		return NULL;
+	}
 	//get the random number 0 - 1
 	drand = BLI_drand();
 
@@ -381,8 +308,8 @@ PyObject *M_Mathutils_Vector(PyObject * self, PyObject * args)
 {
 	PyObject *listObject = NULL;
 	int size, i;
-	float vec[4];
-	PyObject *v, *f;
+	float vec[4], f;
+	PyObject *v;
 
 	size = PySequence_Length(args);
 	if (size == 1) {
@@ -391,40 +318,41 @@ PyObject *M_Mathutils_Vector(PyObject * self, PyObject * args)
 			size = PySequence_Length(listObject);
 		} else { // Single argument was not a sequence
 			Py_XDECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_TypeError, 
-				"Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+			PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+			return NULL;
 		}
 	} else if (size == 0) {
 		//returns a new empty 3d vector
 		return newVectorObject(NULL, 3, Py_NEW); 
 	} else {
-		listObject = EXPP_incr_ret(args);
+		Py_INCREF(args);
+		listObject = args;
 	}
 
 	if (size<2 || size>4) { // Invalid vector size
 		Py_XDECREF(listObject);
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-			"Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+		return NULL;
 	}
 
 	for (i=0; i<size; i++) {
 		v=PySequence_GetItem(listObject, i);
 		if (v==NULL) { // Failed to read sequence
 			Py_XDECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_RuntimeError, 
-				"Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+			PyErr_SetString(PyExc_RuntimeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+			return NULL;
 		}
 
-		f=PyNumber_Float(v);
-		if(f==NULL) { // parsed item not a number
+		f= PyFloat_AsDouble(v);
+		if(f==-1 && PyErr_Occurred()) { // parsed item not a number
 			Py_DECREF(v);
 			Py_XDECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_TypeError, 
-				"Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+			PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+			return NULL;
 		}
 
-		vec[i]=(float)PyFloat_AS_DOUBLE(f);
-		EXPP_decr2(f,v);
+		vec[i]= f;
+		Py_DECREF(v);
 	}
 	Py_DECREF(listObject);
 	return newVectorObject(vec, size, Py_NEW);
@@ -436,13 +364,15 @@ PyObject *M_Mathutils_CrossVecs(PyObject * self, PyObject * args)
 	PyObject *vecCross = NULL;
 	VectorObject *vec1 = NULL, *vec2 = NULL;
 
-	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Mathutils.CrossVecs(): expects (2) 3D vector objects\n");
-	if(vec1->size != 3 || vec2->size != 3)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-			"Mathutils.CrossVecs(): expects (2) 3D vector objects\n");
-
+	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.CrossVecs(): expects (2) 3D vector objects\n");
+		return NULL;
+	}
+	
+	if(vec1->size != 3 || vec2->size != 3) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.CrossVecs(): expects (2) 3D vector objects\n");
+		return NULL;
+	}
 	vecCross = newVectorObject(NULL, 3, Py_NEW);
 	Crossf(((VectorObject*)vecCross)->vec, vec1->vec, vec2->vec);
 	return vecCross;
@@ -455,12 +385,15 @@ PyObject *M_Mathutils_DotVecs(PyObject * self, PyObject * args)
 	double dot = 0.0f;
 	int x;
 
-	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Mathutils.DotVecs(): expects (2) vector objects of the same size\n");
-	if(vec1->size != vec2->size)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-			"Mathutils.DotVecs(): expects (2) vector objects of the same size\n");
+	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.DotVecs(): expects (2) vector objects of the same size\n");
+		return NULL;
+	}
+	
+	if(vec1->size != vec2->size) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.DotVecs(): expects (2) vector objects of the same size\n");
+		return NULL;
+	}
 
 	for(x = 0; x < vec1->size; x++) {
 		dot += vec1->vec[x] * vec2->vec[x];
@@ -502,12 +435,12 @@ PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
 	return PyFloat_FromDouble(angleRads * (180/ Py_PI));
 
 AttributeError1:
-	return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-		"Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n");
+	PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n");
+	return NULL;
 
 AttributeError2:
-	return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-		"Mathutils.AngleBetweenVecs(): zero length vectors are not acceptable arguments\n");
+	PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): zero length vectors are not acceptable arguments\n");
+	return NULL;
 }
 //----------------------------------Mathutils.MidpointVecs() -------------
 //calculates the midpoint between 2 vectors
@@ -517,12 +450,14 @@ PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
 	float vec[4];
 	int x;
 	
-	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
-	if(vec1->size != vec2->size)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-			"Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
+	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
+		return NULL;
+	}
+	if(vec1->size != vec2->size) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
+		return NULL;
+	}
 
 	for(x = 0; x < vec1->size; x++) {
 		vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]);
@@ -538,12 +473,14 @@ PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
 	double dot = 0.0f, dot2 = 0.0f;
 	int x, size;
 
-	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
-	if(vec1->size != vec2->size)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-			"Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
+	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
+		return NULL;
+	}
+	if(vec1->size != vec2->size) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
+		return NULL;
+	}
 
 	//since they are the same size...
 	size = vec1->size;
@@ -575,8 +512,8 @@ PyObject *M_Mathutils_Matrix(PyObject * self, PyObject * args)
 
 	argSize = PySequence_Length(args);
 	if(argSize > 4){	//bad arg nums
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-			"Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+		return NULL;
 	} else if (argSize == 0) { //return empty 4D matrix
 		return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW);
 	}else if (argSize == 1){
@@ -599,15 +536,15 @@ PyObject *M_Mathutils_Matrix(PyObject * self, PyObject * args)
 				if(seqSize){ //0 at first
 					if(PySequence_Length(argObject) != seqSize){ //seq size not same
 						Py_DECREF(argObject);
-						return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-						"Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+						PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+						return NULL;
 					}
 				}
 				seqSize = PySequence_Length(argObject);
 			}else{ //arg not a sequence
 				Py_XDECREF(argObject);
-				return EXPP_ReturnPyObjError(PyExc_TypeError, 
-					"Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+				PyErr_SetString(PyExc_TypeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+				return NULL;
 			}
 			Py_DECREF(argObject);
 		}
@@ -616,27 +553,29 @@ PyObject *M_Mathutils_Matrix(PyObject * self, PyObject * args)
 		for (i = 0; i < argSize; i++){
 			m = PySequence_GetItem(listObject, i);
 			if (m == NULL) { // Failed to read sequence
-				return EXPP_ReturnPyObjError(PyExc_RuntimeError, 
-					"Mathutils.Matrix(): failed to parse arguments...\n");
+				PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
+				return NULL;
 			}
 
 			for (j = 0; j < seqSize; j++) {
 				s = PySequence_GetItem(m, j);
-					if (s == NULL) { // Failed to read sequence
+				if (s == NULL) { // Failed to read sequence
 					Py_DECREF(m);
-					return EXPP_ReturnPyObjError(PyExc_RuntimeError, 
-						"Mathutils.Matrix(): failed to parse arguments...\n");
+					PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
+					return NULL;
 				}
 
 				f = PyNumber_Float(s);
 				if(f == NULL) { // parsed item is not a number
-					EXPP_decr2(m,s);
-					return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-						"Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+					Py_DECREF(m);
+					Py_DECREF(s);
+					PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+					return NULL;
 				}
 
 				matrix[(seqSize*i)+j]=(float)PyFloat_AS_DOUBLE(f);
-				EXPP_decr2(f,s);
+				Py_DECREF(f);
+				Py_DECREF(s);
 			}
 			Py_DECREF(m);
 		}
@@ -655,10 +594,9 @@ PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
 	float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
 		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
 
-	if(!PyArg_ParseTuple
-	    (args, "fi|sO!", &angle, &matSize, &axis, &vector_Type, &vec)) {
-		return EXPP_ReturnPyObjError (PyExc_TypeError, 
-			"Mathutils.RotationMatrix(): expected float int and optional string and vector\n");
+	if(!PyArg_ParseTuple(args, "fi|sO!", &angle, &matSize, &axis, &vector_Type, &vec)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): expected float int and optional string and vector\n");
+		return NULL;
 	}
 	
 	/* Clamp to -360:360 */
@@ -667,25 +605,29 @@ PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
 	while (angle>360.0f)
 		angle-=360.0;
 	
-	if(matSize != 2 && matSize != 3 && matSize != 4)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
-	if(matSize == 2 && (axis != NULL || vec != NULL))
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n");
-	if((matSize == 3 || matSize == 4) && axis == NULL)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n");
+	if(matSize != 2 && matSize != 3 && matSize != 4) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+		return NULL;
+	}
+	if(matSize == 2 && (axis != NULL || vec != NULL)) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n");
+		return NULL;
+	}
+	if((matSize == 3 || matSize == 4) && axis == NULL) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n");
+		return NULL;
+	}
 	if(axis) {
-		if(((strcmp(axis, "r") == 0) ||
-		      (strcmp(axis, "R") == 0)) && vec == NULL)
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"Mathutils.RotationMatrix(): please define the arbitrary axis of rotation\n");
+		if(((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) && vec == NULL) {
+			PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please define the arbitrary axis of rotation\n");
+			return NULL;
+		}
 	}
 	if(vec) {
-		if(vec->size != 3)
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-						      "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
+		if(vec->size != 3) {
+			PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
+			return NULL;
+		}
 	}
 	//convert to radians
 	angle = angle * (float) (Py_PI / 180);
@@ -753,8 +695,8 @@ PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
 				cosAngle;
 		}
 	} else {
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Mathutils.RotationMatrix(): unrecognizable axis of rotation type - expected x,y,z or r\n");
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): unrecognizable axis of rotation type - expected x,y,z or r\n");
+		return NULL;
 	}
 	if(matSize == 4) {
 		//resize matrix
@@ -778,12 +720,12 @@ PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec)
 		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
 	
 	if(!VectorObject_Check(vec)) {
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-						"Mathutils.TranslationMatrix(): expected vector\n");
+		PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): expected vector\n");
+		return NULL;
 	}
 	if(vec->size != 3 && vec->size != 4) {
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-					      "Mathutils.TranslationMatrix(): vector must be 3D or 4D\n");
+		PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): vector must be 3D or 4D\n");
+		return NULL;
 	}
 	//create a identity matrix and add translation
 	Mat4One((float(*)[4]) mat);
@@ -804,18 +746,19 @@ PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
 	float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
 		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
 
-	if(!PyArg_ParseTuple
-	    (args, "fi|O!", &factor, &matSize, &vector_Type, &vec)) {
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"Mathutils.ScaleMatrix(): expected float int and optional vector\n");
+	if(!PyArg_ParseTuple(args, "fi|O!", &factor, &matSize, &vector_Type, &vec)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.ScaleMatrix(): expected float int and optional vector\n");
+		return NULL;
+	}
+	if(matSize != 2 && matSize != 3 && matSize != 4) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+		return NULL;
 	}
-	if(matSize != 2 && matSize != 3 && matSize != 4)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Mathutils.ScaleMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
 	if(vec) {
-		if(vec->size > 2 && matSize == 2)
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"Mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n");
+		if(vec->size > 2 && matSize == 2) {
+			PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n");
+			return NULL;
+		}
 	}
 	if(vec == NULL) {	//scaling along axis
 		if(matSize == 2) {
@@ -878,18 +821,19 @@ PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
 	float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
 		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
 	
-	if(!PyArg_ParseTuple
-	    (args, "si|O!", &plane, &matSize, &vector_Type, &vec)) {
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"Mathutils.OrthoProjectionMatrix(): expected string and int and optional vector\n");
-	}
-	if(matSize != 2 && matSize != 3 && matSize != 4)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Mathutils.OrthoProjectionMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+	if(!PyArg_ParseTuple(args, "si|O!", &plane, &matSize, &vector_Type, &vec)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.OrthoProjectionMatrix(): expected string and int and optional vector\n");
+		return NULL;
+	}
+	if(matSize != 2 && matSize != 3 && matSize != 4) {
+		PyErr_SetString(PyExc_AttributeError,"Mathutils.OrthoProjectionMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+		return NULL;
+	}
 	if(vec) {
-		if(vec->size > 2 && matSize == 2)
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"Mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n");
+		if(vec->size > 2 && matSize == 2) {
+			PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n");
+			return NULL;
+		}
 	}
 	if(vec == NULL) {	//ortho projection onto cardinal plane
 		if(((strcmp(plane, "x") == 0)
@@ -915,8 +859,8 @@ PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
 			mat[4] = 1.0f;
 			mat[8] = 1.0f;
 		} else {
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"Mathutils.OrthoProjectionMatrix(): unknown plane - expected: x, y, xy, xz, yz\n");
+			PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: x, y, xy, xz, yz\n");
+			return NULL;
 		}
 	} else { //arbitrary plane
 		//normalize arbitrary axis
@@ -946,8 +890,8 @@ PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
 			mat[7] = -(vec->vec[1] * vec->vec[2]);
 			mat[8] = 1 - (vec->vec[2] * vec->vec[2]);
 		} else {
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"Mathutils.OrthoProjectionMatrix(): unknown plane - expected: 'r' expected for axis designation\n");
+			PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: 'r' expected for axis designation\n");
+			return NULL;
 		}
 	}
 	if(matSize == 4) {
@@ -975,12 +919,13 @@ PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
 		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
 
 	if(!PyArg_ParseTuple(args, "sfi", &plane, &factor, &matSize)) {
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"Mathutils.ShearMatrix(): expected string float and int\n");
+		PyErr_SetString(PyExc_TypeError,"Mathutils.ShearMatrix(): expected string float and int\n");
+		return NULL;
+	}
+	if(matSize != 2 && matSize != 3 && matSize != 4) {
+		PyErr_SetString(PyExc_AttributeError,"Mathutils.ShearMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+		return NULL;
 	}
-	if(matSize != 2 && matSize != 3 && matSize != 4)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Mathutils.ShearMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
 
 	if(((strcmp(plane, "x") == 0) || (strcmp(plane, "X") == 0))
 	    && matSize == 2) {
@@ -1013,8 +958,8 @@ PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
 		mat[4] = 1.0f;
 		mat[8] = 1.0f;
 	} else {
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Mathutils.ShearMatrix(): expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n");
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.ShearMatrix(): expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n");
+		return NULL;
 	}
 	if(matSize == 4) {
 		//resize matrix
@@ -1048,60 +993,75 @@ PyObject *M_Mathutils_Quaternion(PyObject * self, PyObject * args)
 				(size == 3 && PySequence_Length(args) !=2) || (size >4 || size < 3)) { 
 				// invalid args/size
 				Py_DECREF(listObject);
-				return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-					"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+				PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+				return NULL;
 			}
 	   		if(size == 3){ //get angle in axis/angle
-				n = PyNumber_Float(PySequence_GetItem(args, 1));
+				n = PySequence_GetItem(args, 1);
 				if(n == NULL) { // parsed item not a number or getItem fail
 					Py_DECREF(listObject);
-					return EXPP_ReturnPyObjError(PyExc_TypeError, 
-						"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+					PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+					return NULL;
 				}
-				angle = PyFloat_AS_DOUBLE(n);
+				
+				angle = PyFloat_AsDouble(n);
 				Py_DECREF(n);
+				
+				if (angle==-1 && PyErr_Occurred()) {
+					Py_DECREF(listObject);
+					PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+					return NULL;
+				}
 			}
 		}else{
+			Py_DECREF(listObject); /* assume the list is teh second arg */
 			listObject = PySequence_GetItem(args, 1);
 			if (size>1 && PySequence_Check(listObject)) {
 				size = PySequence_Length(listObject);
 				if (size != 3) { 
 					// invalid args/size
 					Py_DECREF(listObject);
-					return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-						"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+					PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+					return NULL;
 				}
-				n = PyNumber_Float(PySequence_GetItem(args, 0));
+				n = PySequence_GetItem(args, 0);
 				if(n == NULL) { // parsed item not a number or getItem fail
 					Py_DECREF(listObject);
-					return EXPP_ReturnPyObjError(PyExc_TypeError, 
-						"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+					PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+					return NULL;
 				}
-				angle = PyFloat_AS_DOUBLE(n);
+				angle = PyFloat_AsDouble(n);
 				Py_DECREF(n);
+				
+				if (angle==-1 && PyErr_Occurred()) {
+					Py_DECREF(listObject);
+					PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+					return NULL;
+				}
 			} else { // argument was not a sequence
 				Py_XDECREF(listObject);
-				return EXPP_ReturnPyObjError(PyExc_TypeError, 
-					"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+				PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+				return NULL;
 			}
 		}
 	} else if (size == 0) { //returns a new empty quat
 		return newQuaternionObject(NULL, Py_NEW); 
 	} else {
-		listObject = EXPP_incr_ret(args);
+		Py_INCREF(args);
+		listObject = args;
 	}
 
 	if (size == 3) { // invalid quat size
 		if(PySequence_Length(args) != 2){
 			Py_DECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-				"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+			PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+			return NULL;
 		}
 	}else{
 		if(size != 4){
 			Py_DECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-				"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+			PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+			return NULL;
 		}
 	}
 
@@ -1109,19 +1069,21 @@ PyObject *M_Mathutils_Quaternion(PyObject * self, PyObject * args)
 		q = PySequence_GetItem(listObject, i);
 		if (q == NULL) { // Failed to read sequence
 			Py_DECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_RuntimeError, 
-				"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+			PyErr_SetString(PyExc_RuntimeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+			return NULL;
 		}
 
 		f = PyNumber_Float(q);
 		if(f == NULL) { // parsed item not a number
-			EXPP_decr2(q, listObject);
-			return EXPP_ReturnPyObjError(PyExc_TypeError, 
-				"Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+			Py_DECREF(q);
+			Py_DECREF(listObject);
+			PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+			return NULL;
 		}
 
 		quat[i] = (float)PyFloat_AS_DOUBLE(f);
-		EXPP_decr2(f, q);
+		Py_DECREF(f);
+		Py_DECREF(q);
 	}
 	if(size == 3){ //calculate the quat based on axis/angle
 		norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2]);
@@ -1146,9 +1108,10 @@ PyObject *M_Mathutils_CrossQuats(PyObject * self, PyObject * args)
 	QuaternionObject *quatU = NULL, *quatV = NULL;
 	float quat[4];
 
-	if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, 
-		&quaternion_Type, &quatV))
-		return EXPP_ReturnPyObjError(PyExc_TypeError,"Mathutils.CrossQuats(): expected Quaternion types");
+	if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
+		PyErr_SetString(PyExc_TypeError,"Mathutils.CrossQuats(): expected Quaternion types");
+		return NULL;
+	}
 	QuatMul(quat, quatU->quat, quatV->quat);
 
 	return newQuaternionObject(quat, Py_NEW);
@@ -1161,9 +1124,10 @@ PyObject *M_Mathutils_DotQuats(PyObject * self, PyObject * args)
 	double dot = 0.0f;
 	int x;
 
-	if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, 
-		&quaternion_Type, &quatV))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, "Mathutils.DotQuats(): expected Quaternion types");
+	if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.DotQuats(): expected Quaternion types");
+		return NULL;
+	}
 
 	for(x = 0; x < 4; x++) {
 		dot += quatU->quat[x] * quatV->quat[x];
@@ -1179,10 +1143,10 @@ PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
 	double dot = 0.0f;
 	int x;
 
-	if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, 
-		&quatU, &quaternion_Type, &quatV))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
-
+	if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
+		return NULL;
+	}
 	tempQuat[0] = quatU->quat[0];
 	tempQuat[1] = -quatU->quat[1];
 	tempQuat[2] = -quatU->quat[2];
@@ -1206,14 +1170,14 @@ PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
 	double x, y, dot, sinT, angle, IsinT;
 	int z;
 
-	if(!PyArg_ParseTuple(args, "O!O!f", &quaternion_Type, 
-		&quatU, &quaternion_Type, &quatV, &param))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Mathutils.Slerp(): expected Quaternion types and float");
-
-	if(param > 1.0f || param < 0.0f)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-					"Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
+	if(!PyArg_ParseTuple(args, "O!O!f", &quaternion_Type, &quatU, &quaternion_Type, &quatV, &param)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
+		return NULL;
+	}
+	if(param > 1.0f || param < 0.0f) {
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
+		return NULL;
+	}
 
 	//copy quats
 	for(z = 0; z < 4; z++){
@@ -1272,97 +1236,47 @@ PyObject *M_Mathutils_Euler(PyObject * self, PyObject * args)
 			size = PySequence_Length(listObject);
 		} else { // Single argument was not a sequence
 			Py_DECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_TypeError, 
-				"Mathutils.Euler(): 3d numeric sequence expected\n");
+			PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
+			return NULL;
 		}
 	} else if (size == 0) {
 		//returns a new empty 3d euler
 		return newEulerObject(NULL, Py_NEW); 
 	} else {
-		listObject = EXPP_incr_ret(args);
+		Py_INCREF(args);
+		listObject = args;
 	}
 
 	if (size != 3) { // Invalid euler size
 		Py_DECREF(listObject);
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-			"Mathutils.Euler(): 3d numeric sequence expected\n");
+		PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
+		return NULL;
 	}
 
 	for (i=0; i<size; i++) {
 		e = PySequence_GetItem(listObject, i);
 		if (e == NULL) { // Failed to read sequence
 			Py_DECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_RuntimeError, 
-				"Mathutils.Euler(): 3d numeric sequence expected\n");
+			PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
+			return NULL;
 		}
 
 		f = PyNumber_Float(e);
 		if(f == NULL) { // parsed item not a number
-			EXPP_decr2(e, listObject);
-			return EXPP_ReturnPyObjError(PyExc_TypeError, 
-				"Mathutils.Euler(): 3d numeric sequence expected\n");
+			Py_DECREF(e);
+			Py_DECREF(listObject);
+			PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
+			return NULL;
 		}
 
 		eul[i]=(float)PyFloat_AS_DOUBLE(f);
-		EXPP_decr2(f,e);
+		Py_DECREF(f);
+		Py_DECREF(e);
 	}
 	Py_DECREF(listObject);
 	return newEulerObject(eul, Py_NEW);
 }
-//----------------------------------POINT FUNCTIONS---------------------
-//----------------------------------Mathutils.Point() ------------------
-PyObject *M_Mathutils_Point(PyObject * self, PyObject * args)
-{
-	PyObject *listObject = NULL;
-	int size, i;
-	float point[3];
-	PyObject *v, *f;
 
-	size = PySequence_Length(args);
-	if (size == 1) {
-		listObject = PySequence_GetItem(args, 0);
-		if (PySequence_Check(listObject)) {
-			size = PySequence_Length(listObject);
-		} else { // Single argument was not a sequence
-			Py_XDECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_TypeError, 
-				"Mathutils.Point(): 2-3 floats or ints expected (optionally in a sequence)\n");
-		}
-	} else if (size == 0) {
-		//returns a new empty 3d point
-		return newPointObject(NULL, 3, Py_NEW); 
-	} else {
-		listObject = EXPP_incr_ret(args);
-	}
-
-	if (size<2 || size>3) { // Invalid vector size
-		Py_XDECREF(listObject);
-		return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-			"Mathutils.Point(): 2-3 floats or ints expected (optionally in a sequence)\n");
-	}
-
-	for (i=0; i<size; i++) {
-		v=PySequence_GetItem(listObject, i);
-		if (v==NULL) { // Failed to read sequence
-			Py_XDECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_RuntimeError, 
-				"Mathutils.Point(): 2-3 floats or ints expected (optionally in a sequence)\n");
-		}
-
-		f=PyNumber_Float(v);
-		if(f==NULL) { // parsed item not a number
-			Py_DECREF(v);
-			Py_XDECREF(listObject);
-			return EXPP_ReturnPyObjError(PyExc_TypeError, 
-				"Mathutils.Point(): 2-3 floats or ints expected (optionally in a sequence)\n");
-		}
-
-		point[i]=(float)PyFloat_AS_DOUBLE(f);
-		EXPP_decr2(f,v);
-	}
-	Py_DECREF(listObject);
-	return newPointObject(point, size, Py_NEW);
-}
 //---------------------------------INTERSECTION FUNCTIONS--------------------
 //----------------------------------Mathutils.Intersect() -------------------
 PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
@@ -1372,15 +1286,14 @@ PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
 	float det, inv_det, u, v, t;
 	int clip = 1;
 
-	if( !PyArg_ParseTuple
-	    ( args, "O!O!O!O!O!|i", &vector_Type, &vec1, &vector_Type, &vec2
-		, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off , &clip) )
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError, "expected 5 vector types\n" ) );
-	if( vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || 
-		ray->size != 3 || ray_off->size != 3)
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"only 3D vectors for all parameters\n" ) );
+	if(!PyArg_ParseTuple(args, "O!O!O!O!O!|i", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off , &clip)) {
+		PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
+		return NULL;
+	}
+	if(vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
+		PyErr_SetString( PyExc_TypeError, "only 3D vectors for all parameters\n");
+		return NULL;
+	}
 
 	VECCOPY(v1, vec1->vec);
 	VECCOPY(v2, vec2->vec);
@@ -1402,7 +1315,7 @@ PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
 	det = Inpf(e1, pvec);
 
 	if (det > -0.000001 && det < 0.000001) {
-		return EXPP_incr_ret( Py_None );
+		Py_RETURN_NONE;
 	}
 
 	inv_det = 1.0f / det;
@@ -1413,7 +1326,7 @@ PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
 	/* calculate U parameter and test bounds */
 	u = Inpf(tvec, pvec) * inv_det;
 	if (clip && (u < 0.0f || u > 1.0f)) {
-		return EXPP_incr_ret( Py_None );
+		Py_RETURN_NONE;
 	}
 
 	/* prepare to test the V parameter */
@@ -1423,7 +1336,7 @@ PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
 	v = Inpf(dir, qvec) * inv_det;
 
 	if (clip && (v < 0.0f || u + v > 1.0f)) {
-		return EXPP_incr_ret( Py_None );
+		Py_RETURN_NONE;
 	}
 
 	/* calculate t, ray intersects triangle */
@@ -1442,15 +1355,14 @@ PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
 	VectorObject *vec1, *vec2, *vec3, *vec4;
 	float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3];
 
-	if( !PyArg_ParseTuple
-	    ( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
-		, &vector_Type, &vec3, &vector_Type, &vec4 ) )
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError, "expected 4 vector types\n" ) );
-	if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec2->size)
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"vectors must be of the same size\n" ) );
-
+	if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
+		PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+		return NULL;
+	}
+	if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec2->size) {
+		PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
+		return NULL;
+	}
 	if( vec1->size == 3 || vec1->size == 2) {
 		int result;
 		
@@ -1482,7 +1394,7 @@ PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
 
 		if (result == 0) {
 			/* colinear */
-			return EXPP_incr_ret( Py_None );
+			Py_RETURN_NONE;
 		}
 		else {
 			tuple = PyTuple_New( 2 );
@@ -1492,8 +1404,8 @@ PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
 		}
 	}
 	else {
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"2D/3D vectors only\n" ) );
+		PyErr_SetString( PyExc_TypeError, "2D/3D vectors only\n" );
+		return NULL;
 	}
 }
 
@@ -1509,18 +1421,18 @@ PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
 	VectorObject *vec4;
 	float v1[3], v2[3], v3[3], v4[3], e1[3], e2[3], n1[3], n2[3];
 
-	if( !PyArg_ParseTuple
-	    ( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
-		, &vector_Type, &vec3, &vector_Type, &vec4 ) )
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError, "expected 4 vector types\n" ) );
-	if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size)
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"vectors must be of the same size\n" ) );
-	if( vec1->size != 3 )
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"only 3D vectors\n" ) );
-
+	if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
+		PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+		return NULL;
+	}
+	if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
+		PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
+		return NULL;
+	}
+	if( vec1->size != 3 ) {
+		PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
+		return NULL;
+	}
 	VECCOPY(v1, vec1->vec);
 	VECCOPY(v2, vec2->vec);
 	VECCOPY(v3, vec3->vec);
@@ -1553,17 +1465,18 @@ PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
 	VectorObject *vec1, *vec2, *vec3;
 	float v1[3], v2[3], v3[3], e1[3], e2[3], n[3];
 
-	if( !PyArg_ParseTuple
-	    ( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
-		, &vector_Type, &vec3 ) )
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError, "expected 3 vector types\n" ) );
-	if( vec1->size != vec2->size || vec1->size != vec3->size )
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"vectors must be of the same size\n" ) );
-	if( vec1->size != 3 )
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"only 3D vectors\n" ) );
+	if( !PyArg_ParseTuple( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3 ) ) {
+		PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
+		return NULL;
+	}
+	if( vec1->size != vec2->size || vec1->size != vec3->size ) {
+		PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
+		return NULL;
+	}
+	if( vec1->size != 3 ) {
+		PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
+		return NULL;
+	}
 
 	VECCOPY(v1, vec1->vec);
 	VECCOPY(v2, vec2->vec);
@@ -1588,12 +1501,14 @@ PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
 
 	if( !PyArg_ParseTuple
 	    ( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
-		, &vector_Type, &vec3 ) )
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError, "expected 3 vector types\n" ) );
-	if( vec1->size != vec2->size || vec1->size != vec3->size )
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"vectors must be of the same size\n" ) );
+		, &vector_Type, &vec3 ) ) {
+		PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n");
+		return NULL;
+	}
+	if( vec1->size != vec2->size || vec1->size != vec3->size ) {
+		PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
+		return NULL;
+	}
 
 	if (vec1->size == 3) {
 		VECCOPY(v1, vec1->vec);
@@ -1615,8 +1530,8 @@ PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
 		return PyFloat_FromDouble( AreaF2Dfl(v1, v2, v3) );
 	}
 	else {
-		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-						"only 2D,3D vectors are supported\n" ) );
+		PyErr_SetString( PyExc_TypeError, "only 2D,3D vectors are supported\n" );
+		return NULL;
 	}
 }
 //#############################DEPRECATED################################
@@ -1708,9 +1623,10 @@ PyObject *M_Mathutils_RotateEuler(PyObject * self, PyObject * args)
 		--warning;
 	}
 
-	if(!PyArg_ParseTuple(args, "O!fs", &euler_Type, &Eul, &angle, &axis))
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			   "Mathutils.RotateEuler(): expected euler type & float & string");
+	if(!PyArg_ParseTuple(args, "O!fs", &euler_Type, &Eul, &angle, &axis)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.RotateEuler(): expected euler type & float & string");
+		return NULL;
+	}
 
 	Euler_Rotate(Eul, Py_BuildValue("fs", angle, axis));
 	Py_RETURN_NONE;
@@ -1729,9 +1645,10 @@ PyObject *M_Mathutils_MatMultVec(PyObject * self, PyObject * args)
 	}
 
 	//get pyObjects
-	if(!PyArg_ParseTuple(args, "O!O!", &matrix_Type, &mat, &vector_Type, &vec))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Mathutils.MatMultVec(): MatMultVec() expects a matrix and a vector object - in that order\n");
+	if(!PyArg_ParseTuple(args, "O!O!", &matrix_Type, &mat, &vector_Type, &vec)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.MatMultVec(): MatMultVec() expects a matrix and a vector object - in that order\n");
+		return NULL;
+	}
 
 	return column_vector_multiplication(mat, vec);
 }
@@ -1749,11 +1666,48 @@ PyObject *M_Mathutils_VecMultMat(PyObject * self, PyObject * args)
 	}
 
 	//get pyObjects
-	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec, &matrix_Type, &mat))
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Mathutils.VecMultMat(): VecMultMat() expects a vector and matrix object - in that order\n");
+	if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec, &matrix_Type, &mat)) {
+		PyErr_SetString(PyExc_TypeError, "Mathutils.VecMultMat(): VecMultMat() expects a vector and matrix object - in that order\n");
+		return NULL;
+	}
 
 	return row_vector_multiplication(vec, mat);
 }
+
+/* Utility functions */
+
+/*---------------------- EXPP_FloatsAreEqual -------------------------
+  Floating point comparisons 
+  floatStep = number of representable floats allowable in between
+   float A and float B to be considered equal. */
+int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
+{
+	int a, b, delta;
+    assert(floatSteps > 0 && floatSteps < (4 * 1024 * 1024));
+    a = *(int*)&A;
+    if (a < 0)	
+		a = 0x80000000 - a;
+    b = *(int*)&B;
+    if (b < 0)	
+		b = 0x80000000 - b;
+    delta = abs(a - b);
+    if (delta <= floatSteps)	
+		return 1;
+    return 0;
+}
+/*---------------------- EXPP_VectorsAreEqual -------------------------
+  Builds on EXPP_FloatsAreEqual to test vectors */
+int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
+
+	int x;
+	for (x=0; x< size; x++){
+		if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
+			return 0;
+	}
+	return 1;
+}
+
+
+
 //#######################################################################
 //#############################DEPRECATED################################
diff --git a/source/blender/python/api2_2x/Mathutils.h b/source/blender/python/api2_2x/Mathutils.h
index 0db83216178933956e5202ae0be430edf5595afd..b511f2046a6cd8c67e286c71f81d8041813109db 100644
--- a/source/blender/python/api2_2x/Mathutils.h
+++ b/source/blender/python/api2_2x/Mathutils.h
@@ -36,13 +36,11 @@
 #include "matrix.h"
 #include "quat.h"
 #include "euler.h"
-#include "point.h"
 
 PyObject *Mathutils_Init( const char * from );
+
 PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat);
 PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec);
-PyObject *row_point_multiplication(PointObject* pt, MatrixObject * mat);
-PyObject *column_point_multiplication(MatrixObject * mat, PointObject* pt);
 PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
 
 PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args);
@@ -69,7 +67,6 @@ PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args );
 PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args );
 PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args );
 PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args );
-PyObject *M_Mathutils_Point(PyObject * self, PyObject * args);
 //DEPRECATED	
 PyObject *M_Mathutils_CopyMat(PyObject * self, PyObject * args);
 PyObject *M_Mathutils_CopyVec(PyObject * self, PyObject * args);
@@ -79,4 +76,25 @@ PyObject *M_Mathutils_RotateEuler(PyObject * self, PyObject * args);
 PyObject *M_Mathutils_MatMultVec(PyObject * self, PyObject * args);
 PyObject *M_Mathutils_VecMultMat(PyObject * self, PyObject * args);
 
+int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
+int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
+
+
+#define Py_PI  3.14159265358979323846
+#define Py_WRAP 1024
+#define Py_NEW  2048
+
+
+/* Mathutils is used by the BGE and Blender so have to define 
+ * some things here for luddite mac users of py2.3 */
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE  return Py_INCREF(Py_None), Py_None
+#endif
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE  return Py_INCREF(Py_False), Py_False
+#endif
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE  return Py_INCREF(Py_True), Py_True
+#endif
+
 #endif				/* EXPP_Mathutils_H */
diff --git a/source/blender/python/api2_2x/Node.c b/source/blender/python/api2_2x/Node.c
index 792b23315084c5ea648733f84782d1c9b8bbf943..813f599967869c4914a4bcfcc2facee5d58e6fb6 100644
--- a/source/blender/python/api2_2x/Node.c
+++ b/source/blender/python/api2_2x/Node.c
@@ -40,7 +40,7 @@
 
 #include "BLI_blenlib.h"
 #include "gen_utils.h"
-#include "vector.h"
+#include "Mathutils.h"
 
 static PyObject *Node_repr( BPy_Node * self );
 static int Node_compare(BPy_Node *a, BPy_Node *b);
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index fd2301bfae4a9e6be52b0dddf4c7f05be1c5c6c7..2de2906335fa387179cab0af91516210c85d7f49 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -3561,7 +3561,7 @@ static int Object_setRBMass( BPy_Object * self, PyObject * args )
 
 /* this is too low level, possible to add helper methods */
 
-#define GAMEFLAG_MASK ( OB_COLLISION | OB_DYNAMIC | OB_CHILD | OB_ACTOR | OB_DO_FH | \
+#define GAMEFLAG_MASK ( OB_OCCLUDER | OB_COLLISION | OB_DYNAMIC | OB_CHILD | OB_ACTOR | OB_DO_FH | \
 		OB_ROT_FH | OB_ANISOTROPIC_FRICTION | OB_GHOST | OB_RIGID_BODY | OB_SOFT_BODY | \
 		OB_BOUNDS | OB_COLLISION_RESPONSE | OB_SECTOR | OB_PROP | \
 		OB_MAINACTOR )
@@ -5542,6 +5542,7 @@ static PyObject *M_Object_RBFlagsDict( void )
 
 	if( M ) {
 		BPy_constant *d = ( BPy_constant * ) M;
+		PyConstant_Insert( d, "OCCLUDER", PyInt_FromLong( OB_OCCLUDER ) );
 		PyConstant_Insert( d, "COLLISION", PyInt_FromLong( OB_COLLISION ) );
 		PyConstant_Insert( d, "DYNAMIC", PyInt_FromLong( OB_DYNAMIC ) );
 		PyConstant_Insert( d, "CHILD", PyInt_FromLong( OB_CHILD ) );
diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c
index c3f2e0f89c055209e452a5a6f0e0acbc2cde3a15..a7db8290c6272bc7844b85602c0249c6e75ece1d 100644
--- a/source/blender/python/api2_2x/Particle.c
+++ b/source/blender/python/api2_2x/Particle.c
@@ -152,6 +152,38 @@ static int Part_setChildSize( BPy_PartSys * self, PyObject * args );
 static PyObject *Part_getChildSize( BPy_PartSys * self );
 static int Part_setChildRandom( BPy_PartSys * self, PyObject * args );
 static PyObject *Part_getChildRandom( BPy_PartSys * self );
+static int Part_setChildRough1( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildRough1( BPy_PartSys * self );
+static int Part_setChildRough1Size( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildRough1Size( BPy_PartSys * self );
+static int Part_setChildRough2( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildRough2( BPy_PartSys * self );
+static int Part_setChildRough2Size( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildRough2Size( BPy_PartSys * self );
+static int Part_setChildRough2Thres( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildRough2Thres( BPy_PartSys * self );
+static int Part_setChildRoughE( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildRoughE( BPy_PartSys * self );
+static int Part_setChildRoughEShape( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildRoughEShape( BPy_PartSys * self );
+static int Part_setChildKink( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildKink( BPy_PartSys * self );
+static int Part_setChildKinkAxis( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildKinkAxis( BPy_PartSys * self );
+static int Part_setChildKinkFreq( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildKinkFreq( BPy_PartSys * self );
+static int Part_setChildKinkShape( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildKinkShape( BPy_PartSys * self );
+static int Part_setChildKinkAmp( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildKinkAmp( BPy_PartSys * self );
+static int Part_setChildBranch( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildBranch( BPy_PartSys * self );
+static int Part_setChildBranchAnim( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildBranchAnim( BPy_PartSys * self );
+static int Part_setChildBranchSymm( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildBranchSymm( BPy_PartSys * self );
+static int Part_setChildBranchThre( BPy_PartSys * self, PyObject * args );
+static PyObject *Part_getChildBranchThre( BPy_PartSys * self );
 
 /*****************************************************************************/
 /* Python Effect_Type callback function prototypes:                           */
@@ -371,6 +403,70 @@ static PyGetSetDef BPy_ParticleSys_getseters[] = {
 	 (getter)Part_getChildRandom, (setter)Part_setChildRandom,
 	 "Random variation to the size of the child particles",
 	 NULL},
+	 {"childRough1",
+	 (getter)Part_getChildRough1, (setter)Part_setChildRough1,
+	 "Amount of location dependant rough",
+	 NULL},
+	 {"childRough1Size",
+	 (getter)Part_getChildRough1Size, (setter)Part_setChildRough1Size,
+	 "Size of location dependant rough",
+	 NULL},
+	 {"childRough2",
+	 (getter)Part_getChildRough2, (setter)Part_setChildRough2,
+	 "Amount of random rough",
+	 NULL},
+	 {"childRough2Size",
+	 (getter)Part_getChildRough2Size, (setter)Part_setChildRough2Size,
+	 "Size of random rough",
+	 NULL},
+	 {"childRough2Thresh",
+	 (getter)Part_getChildRough2Thres, (setter)Part_setChildRough2Thres,
+	 "Amount of particles left untouched by random rough",
+	 NULL},
+	 {"childRoughE",
+	 (getter)Part_getChildRoughE, (setter)Part_setChildRoughE,
+	 "Amount of end point rough",
+	 NULL},
+	 {"childRoughEShape",
+	 (getter)Part_getChildRoughEShape, (setter)Part_setChildRoughEShape,
+	 "Shape of end point rough",
+	 NULL},
+	 {"childKink",
+	 (getter)Part_getChildKink, (setter)Part_setChildKink,
+	 "Type of periodic offset on the path (Particle.CHILDKINK[ 'BRAID' | 'WAVE' | 'RADIAL' | 'CURL' | 'NOTHING' ])",
+	 NULL},
+	 {"childKinkAxis",
+	 (getter)Part_getChildKinkAxis, (setter)Part_setChildKinkAxis,
+	 "Which axis to use for offset (Particle.CHILDKINKAXIS[ 'Z' | 'Y' | 'X' ])",
+	 NULL},
+	 {"childKinkFreq",
+	 (getter)Part_getChildKinkFreq, (setter)Part_setChildKinkFreq,
+	 "The frequency of the offset (1/total length)",
+	 NULL},
+	 {"childKinkShape",
+	 (getter)Part_getChildKinkShape, (setter)Part_setChildKinkShape,
+	 "Adjust the offset to the beginning/end",
+	 NULL},
+	 {"childKinkAmp",
+	 (getter)Part_getChildKinkAmp, (setter)Part_setChildKinkAmp,
+	 "The amplitude of the offset",
+	 NULL},
+	 {"childBranch",
+	 (getter)Part_getChildBranch, (setter)Part_setChildBranch,
+	 "Branch child paths from eachother",
+	 NULL},
+	 {"childBranchAnim",
+	 (getter)Part_getChildBranchAnim, (setter)Part_setChildBranchAnim,
+	 "Animate branching",
+	 NULL},
+	 {"childBranchSymm",
+	 (getter)Part_getChildBranchSymm, (setter)Part_setChildBranchSymm,
+	 "Start and end points are the same",
+	 NULL},
+	 {"childBranchThre",
+	 (getter)Part_getChildBranchThre, (setter)Part_setChildBranchThre,
+	 "Threshold of branching",
+	 NULL},
 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
 };
 
@@ -614,10 +710,8 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args )
 		}
 
 		if( !wanted_obj){  /* requested object not found */
-			char error_msg[64];
-			PyOS_snprintf( error_msg, sizeof( error_msg ),
-						   "Particle System '%s' not found", name);
-			return EXPP_ReturnPyObjError( PyExc_NameError, error_msg );
+			PyErr_Format(PyExc_NameError, "Particle System '%s' not found", name);
+			return NULL;
 		}
 
 		return wanted_obj;
@@ -785,6 +879,48 @@ static PyObject *Particle_ChildTypeDict( void )
 	return ChildTypes;
 }
 
+/* create the Blender.Particle.ChildKink constant dict */
+
+static PyObject *Particle_ChildKinkDict( void )
+{
+	PyObject *ChildKinks = PyConstant_New(  );
+
+	if( ChildKinks ) {
+		BPy_constant *c = ( BPy_constant * ) ChildKinks;
+
+		PyConstant_Insert( c, "BRAID",
+				 PyInt_FromLong( 4 ) );
+		PyConstant_Insert( c, "WAVE",
+				 PyInt_FromLong( 3 ) );
+		PyConstant_Insert( c, "RADIAL",
+				 PyInt_FromLong( 2 ) );
+		PyConstant_Insert( c, "CURL",
+				 PyInt_FromLong( 1 ) );
+		PyConstant_Insert( c, "NOTHING",
+				 PyInt_FromLong( 0 ) );
+	}
+	return ChildKinks;
+}
+
+/* create the Blender.Particle.ChildKinkAxis constant dict */
+
+static PyObject *Particle_ChildKinkAxisDict( void )
+{
+	PyObject *ChildKinkAxes = PyConstant_New(  );
+
+	if( ChildKinkAxes ) {
+		BPy_constant *c = ( BPy_constant * ) ChildKinkAxes;
+
+		PyConstant_Insert( c, "Z",
+				 PyInt_FromLong( 2 ) );
+		PyConstant_Insert( c, "Y",
+				 PyInt_FromLong( 1 ) );
+		PyConstant_Insert( c, "X",
+				 PyInt_FromLong( 0 ) );
+	}
+	return ChildKinkAxes;
+}
+
 static PyObject *Particle_DrawAs( void )
 {
 	PyObject *DrawAs = PyConstant_New(  );
@@ -832,6 +968,8 @@ PyObject *ParticleSys_Init( void ){
 	PyObject *Dist;
 	PyObject *DrawAs;
 	PyObject *ChildTypes;
+	PyObject *ChildKinks;
+	PyObject *ChildKinkAxes;
 
 
 	if( PyType_Ready( &ParticleSys_Type ) < 0)
@@ -843,6 +981,8 @@ PyObject *ParticleSys_Init( void ){
 	DrawAs = Particle_DrawAs();
 	Dist = Particle_DistrDict();
 	ChildTypes = Particle_ChildTypeDict();
+	ChildKinks = Particle_ChildKinkDict();
+	ChildKinkAxes = Particle_ChildKinkAxisDict();
 
 	submodule = Py_InitModule3( "Blender.Particle", 
 								M_ParticleSys_methods, M_ParticleSys_doc );
@@ -859,6 +999,10 @@ PyObject *ParticleSys_Init( void ){
 		PyModule_AddObject( submodule, "DRAWAS", DrawAs );
 	if( ChildTypes )
 		PyModule_AddObject( submodule, "CHILDTYPE", ChildTypes );
+	if( ChildKinks )
+		PyModule_AddObject( submodule, "CHILDKINK", ChildKinks );
+	if( ChildKinkAxes )
+		PyModule_AddObject( submodule, "CHILDKINKAXIS", ChildKinkAxes );
 
 	return ( submodule );
 }
@@ -1488,11 +1632,8 @@ static int Part_setEditable( BPy_PartSys * self, PyObject * args )
 {
 	int number;
 
-	if( !PyInt_Check( args ) ) {
-		char errstr[128];
-		sprintf ( errstr, "expected int argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
 	number = PyInt_AS_LONG( args );
 
@@ -1539,11 +1680,8 @@ static int Part_setMultiReact( BPy_PartSys * self, PyObject * args )
 {
 	int number;
 
-	if( !PyInt_Check( args ) ) {
-		char errstr[128];
-		sprintf ( errstr, "expected int argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
 	number = PyInt_AS_LONG( args );
 
@@ -1727,11 +1865,8 @@ static PyObject *Part_getGroundZ( BPy_PartSys * self )
 static int Part_setOb( BPy_PartSys * self, PyObject * args )
 {
 	Object *obj;
-	if( !BPy_Object_Check( args ) ) {
-		char errstr[128];
-		sprintf ( errstr, "expected object argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !BPy_Object_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected object argument" );
 
 	obj = Object_FromPyObject(args);
 
@@ -1754,11 +1889,8 @@ static int Part_setRandEmission( BPy_PartSys * self, PyObject * args )
 {
 	int number;
 
-	if( !PyInt_Check( args ) ) {
-		char errstr[128];
-		sprintf ( errstr, "expected int argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
 	number = PyInt_AS_LONG( args );
 
@@ -1781,19 +1913,14 @@ static PyObject *Part_getRandEmission( BPy_PartSys * self )
 static int Part_setParticleDist( BPy_PartSys * self, PyObject * args )
 {
 	int number;
-	char errstr[128];
 
-	if( !PyInt_Check( args ) ) {
-		sprintf ( errstr, "expected int argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
 	number = PyInt_AS_LONG( args );
 
-	if (number < 0 || number > 3){
-		sprintf ( errstr, "expected int argument between 0 - 3" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if (number < 0 || number > 3)
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument between 0 - 3" );
 
 	self->psys->part->from = (short)number;
 
@@ -1811,11 +1938,8 @@ static int Part_setEvenDist( BPy_PartSys * self, PyObject * args )
 {
 	int number;
 
-	if( !PyInt_Check( args ) ) {
-		char errstr[128];
-		sprintf ( errstr, "expected int argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
 	number = PyInt_AS_LONG( args );
 
@@ -1838,19 +1962,14 @@ static PyObject *Part_getEvenDist( BPy_PartSys * self )
 static int Part_setDist( BPy_PartSys * self, PyObject * args )
 {
 	int number;
-	char errstr[128];
 
-	if( !PyInt_Check( args ) ) {
-		sprintf ( errstr, "expected int argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
 	number = PyInt_AS_LONG( args );
 
-	if (number < 0 || number > 2){
-		sprintf ( errstr, "expected int argument between 0 - 2" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if (number < 0 || number > 2)
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument between 0 - 2" );
 
 	self->psys->part->distr = (short)number;
 
@@ -1900,11 +2019,8 @@ static int Part_setInvert( BPy_PartSys * self, PyObject * args )
 {
 	int number;
 
-	if( !PyInt_Check( args ) ) {
-		char errstr[128];
-		sprintf ( errstr, "expected int argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
 	number = PyInt_AS_LONG( args );
 
@@ -1927,11 +2043,9 @@ static PyObject *Part_getInvert( BPy_PartSys * self )
 static int Part_setTargetOb( BPy_PartSys * self, PyObject * args )
 {
 	Object *obj;
-	if( !BPy_Object_Check( args ) ) {
-		char errstr[128];
-		sprintf ( errstr, "expected object argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	
+	if( !BPy_Object_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected object argument" );
 
 	obj = Object_FromPyObject(args);
 
@@ -2005,11 +2119,8 @@ static int Part_setRenderObject( BPy_PartSys * self, PyObject * args )
 	int number,nr;
 	ParticleSystem *psys = 0L;
 
-	if( !PyInt_Check( args ) ) {
-		char errstr[128];
-		sprintf ( errstr, "expected int argument" );
-		return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-	}
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
 	number = PyInt_AS_LONG( args );
 
@@ -2225,3 +2336,273 @@ static PyObject *Part_getChildRandom( BPy_PartSys * self )
 {
 	return PyFloat_FromDouble( ((float)( self->psys->part->childrandsize )) );
 }
+
+static int Part_setChildRough1( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->rough1,
+			0.0, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildRough1( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->rough1 )) );
+}
+
+static int Part_setChildRough1Size( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->rough1_size,
+			0.01, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildRough1Size( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->rough1_size )) );
+}
+
+static int Part_setChildRough2( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->rough2,
+			0.0, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildRough2( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->rough2 )) );
+}
+
+static int Part_setChildRough2Size( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->rough2_size,
+			0.01, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildRough2Size( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->rough2_size )) );
+}
+
+static int Part_setChildRough2Thres( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->rough2_thres,
+			0.0, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildRough2Thres( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->rough2_thres )) );
+}
+
+static int Part_setChildRoughE( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->rough_end,
+			0.0, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildRoughE( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->rough_end )) );
+}
+
+static int Part_setChildRoughEShape( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->rough_end_shape,
+			0.0, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildRoughEShape( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->rough_end_shape )) );
+}
+
+static int Part_setChildKink( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setIValueRange( args, &self->psys->part->kink,
+			0, 4, 'h' );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildKink( BPy_PartSys * self )
+{
+	return PyInt_FromLong( (short)( self->psys->part->kink ) );
+}
+
+static int Part_setChildKinkAxis( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setIValueRange( args, &self->psys->part->kink_axis,
+			0, 2, 'h' );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildKinkAxis( BPy_PartSys * self )
+{
+	return PyInt_FromLong( (short)( self->psys->part->kink_axis ) );
+}
+
+static int Part_setChildKinkFreq( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->kink_freq,
+			0.0, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildKinkFreq( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->kink_freq )) );
+}
+
+static int Part_setChildKinkShape( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->kink_shape,
+			-0.999, 0.999 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildKinkShape( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->kink_shape )) );
+}
+
+static int Part_setChildKinkAmp( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->kink_amp,
+			0.0, 10.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildKinkAmp( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->kink_amp )) );
+}
+
+static int Part_setChildBranch( BPy_PartSys * self, PyObject * args )
+{
+	int number;
+
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
+
+	number = PyInt_AS_LONG( args );
+
+	if (number){
+		self->psys->part->flag |= PART_BRANCHING;
+	}else{
+		self->psys->part->flag &= ~PART_BRANCHING;
+	}
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return 0;
+}
+
+static PyObject *Part_getChildBranch( BPy_PartSys * self )
+{
+	return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BRANCHING )) > 0 );
+}
+
+static int Part_setChildBranchAnim( BPy_PartSys * self, PyObject * args )
+{
+	int number;
+
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
+
+	number = PyInt_AS_LONG( args );
+
+	if (number){
+		self->psys->part->flag |= PART_ANIM_BRANCHING;
+	}else{
+		self->psys->part->flag &= ~PART_ANIM_BRANCHING;
+	}
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return 0;
+}
+
+static PyObject *Part_getChildBranchAnim( BPy_PartSys * self )
+{
+	return PyInt_FromLong( ((long)( self->psys->part->flag & PART_ANIM_BRANCHING )) > 0 );
+}
+
+static int Part_setChildBranchSymm( BPy_PartSys * self, PyObject * args )
+{
+	int number;
+
+	if( !PyInt_Check( args ) )
+		return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
+
+	number = PyInt_AS_LONG( args );
+
+	if (number){
+		self->psys->part->flag |= PART_SYMM_BRANCHING;
+	}else{
+		self->psys->part->flag &= ~PART_SYMM_BRANCHING;
+	}
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return 0;
+}
+
+static PyObject *Part_getChildBranchSymm( BPy_PartSys * self )
+{
+	return PyInt_FromLong( ((long)( self->psys->part->flag & PART_SYMM_BRANCHING )) > 0 );
+}
+
+static int Part_setChildBranchThre( BPy_PartSys * self, PyObject * args )
+{
+	int res = EXPP_setFloatRange( args, &self->psys->part->branch_thres,
+			0.0, 1.0 );
+
+	psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
+
+	return res;
+}
+
+static PyObject *Part_getChildBranchThre( BPy_PartSys * self )
+{
+	return PyFloat_FromDouble( ((float)( self->psys->part->branch_thres )) );
+}
diff --git a/source/blender/python/api2_2x/Scene.c b/source/blender/python/api2_2x/Scene.c
index 8a2be2391a41eb32d7db7a9fe18dde5fda422afb..cfdfa5d3456fe89ee55bdf1b3e7987d3a8dda707 100644
--- a/source/blender/python/api2_2x/Scene.c
+++ b/source/blender/python/api2_2x/Scene.c
@@ -85,7 +85,7 @@ struct View3D;
 
 
 #include "BKE_utildefines.h" /* vec copy */
-#include "vector.h"
+#include "Mathutils.h"
 
 PyObject *M_Object_Get( PyObject * self, PyObject * args ); /* from Object.c */
 
@@ -844,12 +844,15 @@ static PyObject *Scene_link( BPy_Scene * self, PyObject * args )
 	Scene *scene = self->scene;
 	BPy_Object *bpy_obj;
 	Object *object = NULL;
+
+#if 0
 	static char warning = 1;
 
 	if( warning ) {
 		printf("scene.link(ob) deprecated!\n\tuse scene.objects.link(ob) instead\n");
 		--warning;
 	}
+#endif
 
 	SCENE_DEL_CHECK_PY(self);
 	
diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c
index 51e1c389528d5faf9532d5037a9de191aefdd085..455badef4adbf2831023be8ba42a14dbdb7e8ee4 100644
--- a/source/blender/python/api2_2x/Texture.c
+++ b/source/blender/python/api2_2x/Texture.c
@@ -53,7 +53,7 @@
 #include "gen_utils.h"
 #include "gen_library.h"
 
-#include "vector.h" /* for Texture_evaluate(vec) */
+#include "Mathutils.h" /* for Texture_evaluate(vec) */
 #include "Material.h" /* for EXPP_Colorband_fromPyList and EXPP_PyList_fromColorband */
 #include "RE_shader_ext.h"
 
diff --git a/source/blender/python/api2_2x/Types.c b/source/blender/python/api2_2x/Types.c
index 10b968cacbaef98f4e818d847d0e7471f8fcf849..65d816ac7b007bcd15422ac1f8e476160367c172 100644
--- a/source/blender/python/api2_2x/Types.c
+++ b/source/blender/python/api2_2x/Types.c
@@ -60,7 +60,6 @@ extern PyTypeObject World_Type;
 extern PyTypeObject property_Type;
 extern PyTypeObject buffer_Type, constant_Type, euler_Type;
 extern PyTypeObject matrix_Type, quaternion_Type, rgbTuple_Type, vector_Type;
-extern PyTypeObject point_Type;
 extern PyTypeObject Modifier_Type, ModSeq_Type;
 extern PyTypeObject EditBone_Type;
 extern PyTypeObject ThemeSpace_Type;
@@ -246,7 +245,6 @@ void types_InitAll( void )
 	PyType_Ready( &rgbTuple_Type );
 	vector_Type.ob_type = &PyType_Type;
 	property_Type.ob_type = &PyType_Type;
-	point_Type.ob_type = &PyType_Type;
 	PyType_Ready( &Modifier_Type );
 	PyType_Ready( &ModSeq_Type );
 	PyType_Ready( &EditBone_Type );
@@ -358,8 +356,6 @@ PyObject *Types_Init( void )
 			      ( PyObject * ) &Pose_Type );
 	PyDict_SetItemString( dict, "propertyType",
 			      ( PyObject * ) &property_Type );
-	PyDict_SetItemString( dict, "pointType",
-			      ( PyObject * ) &point_Type );
 	PyDict_SetItemString( dict, "ModifierType",
 			      ( PyObject * ) &Modifier_Type );
 	PyDict_SetItemString( dict, "ModSeqType",
diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c
index 40f6d52d8daa4b54140542a50560d4ac4ab1805b..fe7cee5b0e1a577d9c0b4a5f510f49e556bf96ca 100644
--- a/source/blender/python/api2_2x/Window.c
+++ b/source/blender/python/api2_2x/Window.c
@@ -954,9 +954,11 @@ static PyObject *M_Window_EditMode( PyObject * self, PyObject * args )
 				enter_editmode(0);
 			}
 		} else if( G.obedit ) {
-			if( undo_str_len > 63 )
-				undo_str[63] = '\0';	/* 64 is max */
-			BIF_undo_push( undo_str ); /* This checks user undo settings */
+			if( do_undo ) {
+				if( undo_str_len > 63 )
+					undo_str[63] = '\0';	/* 64 is max */
+				BIF_undo_push( undo_str ); /* This checks user undo settings */
+			}
 			exit_editmode( EM_FREEDATA );
 
 			//update armatures
diff --git a/source/blender/python/api2_2x/bpy_internal_import.c b/source/blender/python/api2_2x/bpy_internal_import.c
new file mode 100644
index 0000000000000000000000000000000000000000..125993cc42580cedf12eaf08335cba82672fadbe
--- /dev/null
+++ b/source/blender/python/api2_2x/bpy_internal_import.c
@@ -0,0 +1,339 @@
+/* 
+ * $Id$
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+#include "bpy_internal_import.h"
+#include "DNA_text_types.h"
+#include "DNA_ID.h"
+
+#include "BKE_global.h"
+#include "MEM_guardedalloc.h"
+#include "BKE_text.h" /* txt_to_buf */	
+#include "BKE_main.h"
+
+static Main *bpy_import_main= NULL;
+
+static void free_compiled_text(Text *text)
+{
+	if(text->compiled) {
+		Py_DECREF(( PyObject * )text->compiled);
+	}
+	text->compiled= NULL;
+}
+
+struct Main *bpy_import_main_get(void)
+{
+	return bpy_import_main;
+}
+
+void bpy_import_main_set(struct Main *maggie)
+{
+	bpy_import_main= maggie;
+}
+
+
+PyObject *bpy_text_import( char *name, int *found )
+{
+	Text *text;
+	char txtname[22]; /* 21+NULL */
+	char *buf = NULL;
+	int namelen = strlen( name );
+	Main *maggie= bpy_import_main ? bpy_import_main:G.main;
+	
+	*found= 0;
+	
+	if (namelen>21-3) return NULL; /* we know this cant be importable, the name is too long for blender! */
+	
+	memcpy( txtname, name, namelen );
+	memcpy( &txtname[namelen], ".py", 4 );
+
+	for(text = maggie->text.first; text; text = text->id.next) {
+		if( !strcmp( txtname, text->id.name+2 ) )
+			break;
+	}
+
+	if( !text )
+		return NULL;
+	else
+		*found = 1;
+	
+	if( !text->compiled ) {
+		buf = txt_to_buf( text );
+		text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
+		MEM_freeN( buf );
+
+		if( PyErr_Occurred(  ) ) {
+			PyErr_Print(  );
+			PyErr_Clear(  );
+			PySys_SetObject("last_traceback", NULL);
+			free_compiled_text( text );
+			return NULL;
+		}
+	}
+
+	return PyImport_ExecCodeModule( name, text->compiled );
+}
+
+
+/*
+ * find in-memory module and recompile
+ */
+
+PyObject *bpy_text_reimport( PyObject *module, int *found )
+{
+	Text *text;
+	char *txtname;
+	char *name;
+	char *buf = NULL;
+	Main *maggie= bpy_import_main ? bpy_import_main:G.main;
+	
+	*found= 0;
+	
+	/* get name, filename from the module itself */
+
+	txtname = PyModule_GetFilename( module );
+	name = PyModule_GetName( module );
+	if( !txtname || !name)
+		return NULL;
+
+	/* look up the text object */
+	text = ( Text * ) & ( maggie->text.first );
+	while( text ) {
+		if( !strcmp( txtname, text->id.name+2 ) )
+			break;
+		text = text->id.next;
+	}
+
+	/* uh-oh.... didn't find it */
+	if( !text )
+		return NULL;
+	else
+		*found = 1;
+
+	/* if previously compiled, free the object */
+	/* (can't see how could be NULL, but check just in case) */ 
+	if( text->compiled ){
+		Py_DECREF( (PyObject *)text->compiled );
+	}
+
+	/* compile the buffer */
+	buf = txt_to_buf( text );
+	text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
+	MEM_freeN( buf );
+
+	/* if compile failed.... return this error */
+	if( PyErr_Occurred(  ) ) {
+		PyErr_Print(  );
+		PyErr_Clear(  );
+		PySys_SetObject("last_traceback", NULL);
+		free_compiled_text( text );
+		return NULL;
+	}
+
+	/* make into a module */
+	return PyImport_ExecCodeModule( name, text->compiled );
+}
+
+
+static PyObject *blender_import( PyObject * self, PyObject * args,  PyObject * kw)
+{
+	PyObject *exception, *err, *tb;
+	char *name;
+	int found= 0;
+	PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
+	PyObject *newmodule;
+	
+	//PyObject_Print(args, stderr, 0);
+#if (PY_VERSION_HEX >= 0x02060000)
+	int dummy_val; /* what does this do?*/
+	static char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", 0};
+	
+	if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOOi:bpy_import_meth", kwlist,
+			       &name, &globals, &locals, &fromlist, &dummy_val) )
+		return NULL;
+#else
+	static char *kwlist[] = {"name", "globals", "locals", "fromlist", 0};
+	
+	if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOO:bpy_import_meth", kwlist,
+			       &name, &globals, &locals, &fromlist ) )
+		return NULL;
+#endif
+
+	/* import existing builtin modules or modules that have been imported alredy */
+	newmodule = PyImport_ImportModuleEx( name, globals, locals, fromlist );
+	
+	if(newmodule)
+		return newmodule;
+	
+	PyErr_Fetch( &exception, &err, &tb );	/* get the python error incase we cant import as blender text either */
+	
+	/* importing from existing modules failed, see if we have this module as blender text */
+	newmodule = bpy_text_import( name, &found );
+	
+	if( newmodule ) {/* found module as blender text, ignore above exception */
+		PyErr_Clear(  );
+		Py_XDECREF( exception );
+		Py_XDECREF( err );
+		Py_XDECREF( tb );
+		/* printf( "imported from text buffer...\n" ); */
+	}
+	else if (found==1) { /* blender text module failed to execute but was found, use its error message */
+		Py_XDECREF( exception );
+		Py_XDECREF( err );
+		Py_XDECREF( tb );
+		return NULL;
+	}
+	else {
+		/* no blender text was found that could import the module
+		 * rause the original error from PyImport_ImportModuleEx */
+		PyErr_Restore( exception, err, tb );
+	}
+	return newmodule;
+}
+
+
+/*
+ * our reload() module, to handle reloading in-memory scripts
+ */
+
+static PyObject *blender_reload( PyObject * self, PyObject * args )
+{
+	PyObject *exception, *err, *tb;
+	PyObject *module = NULL;
+	PyObject *newmodule = NULL;
+	int found= 0;
+	
+	/* check for a module arg */
+	if( !PyArg_ParseTuple( args, "O:bpy_reload_meth", &module ) )
+		return NULL;
+
+	/* try reimporting from file */
+	newmodule = PyImport_ReloadModule( module );
+	if( newmodule )
+		return newmodule;
+
+	/* no file, try importing from memory */
+	PyErr_Fetch( &exception, &err, &tb );	/*restore for probable later use */
+
+	newmodule = bpy_text_reimport( module, &found );
+	if( newmodule ) {/* found module as blender text, ignore above exception */
+		PyErr_Clear(  );
+		Py_XDECREF( exception );
+		Py_XDECREF( err );
+		Py_XDECREF( tb );
+		/* printf( "imported from text buffer...\n" ); */
+	}
+	else if (found==1) { /* blender text module failed to execute but was found, use its error message */
+		Py_XDECREF( exception );
+		Py_XDECREF( err );
+		Py_XDECREF( tb );
+		return NULL;
+	}
+	else {
+		/* no blender text was found that could import the module
+		 * rause the original error from PyImport_ImportModuleEx */
+		PyErr_Restore( exception, err, tb );
+	}
+
+	return newmodule;
+}
+
+PyMethodDef bpy_import_meth[] = { {"bpy_import_meth", blender_import, METH_KEYWORDS, "blenders import"} };
+PyMethodDef bpy_reload_meth[] = { {"bpy_reload_meth", blender_reload, METH_VARARGS, "blenders reload"} };
+
+
+/* Clear user modules.
+ * This is to clear any modules that could be defined from running scripts in blender.
+ * 
+ * Its also needed for the BGE Python api so imported scripts are not used between levels
+ * 
+ * This clears every modules that has a __file__ attribute (is not a builtin)
+ *
+ * Note that clearing external python modules is important for the BGE otherwise
+ * it wont reload scripts between loading different blend files or while making the game.
+ * - use 'clear_all' arg in this case.
+ *
+ * Since pythons bultins include a full path even for win32.
+ * even if we remove a python module a reimport will bring it back again.
+ */
+
+
+#if defined(WIN32) || defined(WIN64)
+#define SEPSTR "\\"
+#else
+#define SEPSTR "/"
+#endif
+
+
+void bpy_text_clear_modules(int clear_all)
+{
+	PyObject *modules= PySys_GetObject("modules");
+	
+	char *fname;
+	char *file_extension;
+	
+	/* looping over the dict */
+	PyObject *key, *value;
+	int pos = 0;
+	
+	/* new list */
+	PyObject *list;
+
+	if (modules==NULL)
+		return; /* should never happen but just incase */
+
+	list= PyList_New(0);
+
+	/* go over sys.modules and remove anything with a 
+	 * sys.modukes[x].__file__ thats ends with a .py and has no path
+	 */
+	while (PyDict_Next(modules, &pos, &key, &value)) {
+		fname= PyModule_GetFilename(value);
+		if(fname) {
+			if (clear_all || ((strstr(fname, SEPSTR))==0)) { /* no path ? */
+				file_extension = strstr(fname, ".py");
+				if(file_extension && *(file_extension + 3) == '\0') { /* .py extension ? */
+					/* now we can be fairly sure its a python import from the blendfile */
+					PyList_Append(list, key); /* free'd with the list */
+				}
+			}
+		}
+		else {
+			PyErr_Clear();
+		}
+	}
+	
+	/* remove all our modules */
+	for(pos=0; pos < PyList_Size(list); pos++) {
+		/* PyObject_Print(key, stderr, 0); */
+		key= PyList_GET_ITEM(list, pos);
+		PyDict_DelItem(modules, key);
+	}
+	
+	Py_DECREF(list); /* removes all references from append */
+}
+
diff --git a/source/blender/python/api2_2x/bpy_internal_import.h b/source/blender/python/api2_2x/bpy_internal_import.h
new file mode 100644
index 0000000000000000000000000000000000000000..7220212f13e798bd3fa64dd98ac82f93f8e85835
--- /dev/null
+++ b/source/blender/python/api2_2x/bpy_internal_import.h
@@ -0,0 +1,49 @@
+/* 
+ * $Id$
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+/* Note, the BGE needs to use this too, keep it minimal */
+
+#ifndef EXPP_bpy_import_h
+#define EXPP_bpy_import_h
+
+#include <Python.h>
+#include "compile.h"		/* for the PyCodeObject */
+#include "eval.h"		/* for PyEval_EvalCode */
+
+PyObject*	bpy_text_import( char *name, int *found );
+PyObject*	bpy_text_reimport( PyObject *module, int *found );
+void		bpy_text_clear_modules( int clear_all ); /* Clear user modules */
+extern PyMethodDef bpy_import_meth[];
+extern PyMethodDef bpy_reload_meth[];
+
+/* The game engine has its own Main struct, if this is set search this rather then G.main */
+struct Main *bpy_import_main_get(void);
+void bpy_import_main_set(struct Main *maggie);
+
+
+#endif				/* EXPP_bpy_import_h */
diff --git a/source/blender/python/api2_2x/doc/Geometry.py b/source/blender/python/api2_2x/doc/Geometry.py
index 5d507956cdbe675485f16801d0af775874e7a188..97f97e8833e9f17ddd321ac89c483a0d9e8d15ea 100644
--- a/source/blender/python/api2_2x/doc/Geometry.py
+++ b/source/blender/python/api2_2x/doc/Geometry.py
@@ -102,4 +102,10 @@ def BoxPack2D(boxlist):
 	@rtype: tuple
 	@return: a tuple pair - (width, height) of all the packed boxes.
 	"""
-	
\ No newline at end of file
+def BezierInterp(vec_knot_1, vec_handle_1, vec_handle_2, vec_knot_2, resolution):
+	"""
+	Takes 4 vectors representing a bezier curve and returns a list of vector points.
+	@note: any vector size is supported, the largest dimension from the input will be used for all returned vectors/
+	@rtype: list
+	@return: a list of vectors the size of resolution including the start and end points (vec_knot_1 and vec_knot_2)
+	"""
\ No newline at end of file
diff --git a/source/blender/python/api2_2x/doc/Image.py b/source/blender/python/api2_2x/doc/Image.py
index e376b11c4fa60d3b94f3b0aef27e85d47babda2d..12231ee8bcc2c61ddfa06d37adb225302550bbec 100644
--- a/source/blender/python/api2_2x/doc/Image.py
+++ b/source/blender/python/api2_2x/doc/Image.py
@@ -373,6 +373,7 @@ class Image:
 	def save():
 		"""
 		Saves the current image to L{filename}
+		@note: New images created in Blender will always save as Targa regardless of filename.
 		@note: Saving to a directory that doent exist will raise an error.
 		@note: Saving a packed image will make a unique (numbered) name if the file alredy exists. Remove the file first to be sure it will not be renamed.
 		@returns: None
diff --git a/source/blender/python/api2_2x/doc/Lamp.py b/source/blender/python/api2_2x/doc/Lamp.py
index 162d94ccff318b82349c1ff2b8ee03967394f81a..878ca53bb1566e42f2619a010d92d47032fc4a4b 100644
--- a/source/blender/python/api2_2x/doc/Lamp.py
+++ b/source/blender/python/api2_2x/doc/Lamp.py
@@ -136,6 +136,9 @@ class Lamp:
 	@ivar samples:  Lamp shadow map samples.
 	Value is clamped to the range [1,16].
 	@type samples:  int
+	@ivar sampleBuffers:  Lamp amount of shadow map sample buffers.
+	Number of sample buffers for shadow buffer: 1, 4 or 9.
+	@type sampleBuffers:  int
 	@ivar raySamplesX:  Lamp raytracing X samples (X is used for the Y axis with square area lamps).
 	Value is clamped to the range [1,16].
 	@type raySamplesX:  int
diff --git a/source/blender/python/api2_2x/doc/Library.py b/source/blender/python/api2_2x/doc/Library.py
index c99739d939b6e26cbcf7843187643dad65ba7639..68b5f2858fba1e69e09b0d822c0eb6281a74e6b9 100644
--- a/source/blender/python/api2_2x/doc/Library.py
+++ b/source/blender/python/api2_2x/doc/Library.py
@@ -58,7 +58,7 @@ def Close ():
   Close the currently open library file, if any.
   """
 
-def getName ():
+def GetName ():
   """
   Get the filename of the currently open library file.
   @rtype: string
@@ -111,4 +111,9 @@ def Update ():
      down your script and make you look like a lousy programmer.
      Enough warnings :)?
   """
-
+def LinkedLibs():
+  """
+  Return a list of all libs used in the the open .blend file (direct and indirect).
+  @rtype: list of strings
+  @return: a list of blendfile names.
+  """
diff --git a/source/blender/python/api2_2x/doc/Mathutils.py b/source/blender/python/api2_2x/doc/Mathutils.py
index 524d1fb6d4c790fe1068bd2115944bbcbb695841..7ca10c53d029ac4883d0bfab65cc0022e1311794 100644
--- a/source/blender/python/api2_2x/doc/Mathutils.py
+++ b/source/blender/python/api2_2x/doc/Mathutils.py
@@ -400,6 +400,7 @@ class Vector:
   The Vector object
   =================
     This object gives access to Vectors in Blender.
+  @group Axises: x, y, z, w
   @ivar x: The x value.
   @ivar y: The y value.
   @ivar z: The z value (if any).
@@ -420,6 +421,16 @@ class Vector:
       - -vec
   @note: You can access a vector object like a sequence
       - x = vector[0]
+      - vec_a[:] vec_b
+      - vec2d[:] vec3d[:2]
+  @note: Vectors support 'swizzle' operations
+      - vec.xyz = vec.zyx
+      - vec.xy = vec.zw
+      - vec.xxy = vec.wzz
+      - vec.yzyz = vec.yxyx
+
+      See U{http://en.wikipedia.org/wiki/Swizzling_(computer_graphics)}
+  
   @attention: Vector data can be wrapped or non-wrapped. When a object is wrapped it
   means that the object will give you direct access to the data inside of blender. Modification
   of this object will directly change the data inside of blender. To copy a wrapped object
@@ -429,7 +440,7 @@ class Vector:
   Example::
       wrappedObject = Object.getAttribute() #this is wrapped data
       print wrappedObject.wrapped #prints 'True'
-      copyOfObject = Object(wrappedObject) #creates a copy of the object
+      copyOfObject = wrappedObject.copy() #creates a copy of the object
       secondPointer = wrappedObject #creates a second pointer to the same data
       print wrappedObject.attribute #prints '5'
       secondPointer.attribute = 10
@@ -535,6 +546,7 @@ class Euler:
   The Euler object
   ================
     This object gives access to Eulers in Blender.
+  @group Axises: x, y, z, w
   @ivar x: The heading value in degrees.
   @ivar y: The pitch value in degrees.
   @ivar z: The roll value in degrees.
@@ -552,7 +564,7 @@ class Euler:
   Example::
       wrappedObject = Object.getAttribute() #this is wrapped data
       print wrappedObject.wrapped #prints 'True'
-      copyOfObject = Object(wrappedObject) #creates a copy of the object
+      copyOfObject = wrappedObject.copy() #creates a copy of the object
       secondPointer = wrappedObject #creates a second pointer to the same data
       print wrappedObject.attribute #prints '5'
       secondPointer.attribute = 10
@@ -596,7 +608,7 @@ class Euler:
     """
     Return a matrix representation of the euler.
     @rtype: Matrix object
-    @return: A roation matrix representation of the euler.
+    @return: A 3x3 roation matrix representation of the euler.
     """
 
   def toQuat():
@@ -611,6 +623,7 @@ class Quaternion:
   The Quaternion object
   =====================
     This object gives access to Quaternions in Blender.
+  @group Axises: x, y, z, w
   @ivar w: The w value.
   @ivar x: The x value.
   @ivar y: The y value.
@@ -639,7 +652,7 @@ class Quaternion:
   Example::
       wrappedObject = Object.getAttribute() #this is wrapped data
       print wrappedObject.wrapped #prints 'True'
-      copyOfObject = Object(wrappedObject) #creates a copy of the object
+      copyOfObject = wrappedObject.copy() #creates a copy of the object
       secondPointer = wrappedObject #creates a second pointer to the same data
       print wrappedObject.attribute #prints '5'
       secondPointer.attribute = 10
@@ -716,7 +729,7 @@ class Quaternion:
     """
     Return a matrix representation of the quaternion.
     @rtype: Matrix object
-    @return: A rotation matrix representation of the quaternion.
+    @return: A 3x3 rotation matrix representation of the quaternion.
     """
 
 class Matrix:
@@ -747,7 +760,7 @@ class Matrix:
   Example::
       wrappedObject = Object.getAttribute() #this is wrapped data
       print wrappedObject.wrapped #prints 'True'
-      copyOfObject = Object(wrappedObject) #creates a copy of the object
+      copyOfObject = wrappedObject.copy() #creates a copy of the object
       secondPointer = wrappedObject #creates a second pointer to the same data
       print wrappedObject.attribute #prints '5'
       secondPointer.attribute = 10
diff --git a/source/blender/python/api2_2x/doc/Particle.py b/source/blender/python/api2_2x/doc/Particle.py
index 47bcc7c88a3f35e15ca5286f9c4145b40ec4d1a5..6107f0bda2f3ea783be07f1bff6c59a916056fa7 100644
--- a/source/blender/python/api2_2x/doc/Particle.py
+++ b/source/blender/python/api2_2x/doc/Particle.py
@@ -40,13 +40,25 @@ This module provides access to the B{Particle} in Blender.
 		- LINE: Draw as lines
 		- PATH: Draw pathes
 		- OBJECT: Draw object
-		- GROUP: Draw goup
+		- GROUP: Draw group
 		- BILLBOARD: Draw as billboard 
 @type CHILDTYPE: readonly dictionary
 @var CHILDTYPE: Constant dict used for whith L{Particle.CHILDTYPE}
 		- NONE: set no children
 		- PARTICLES: set children born from particles
 		- FACES: set children born from faces
+@type CHILDKINK: readonly dictionary
+@var CHILDKINK: Type of periodic offset on the path
+		- NOTHING: set no offset on the path 
+		- CURL: set curl offset on the path
+		- RADIAL: set radial offset on the path
+		- WAVE: set wave offset on the path
+		- BRAID: set braid offset on the path
+@type CHILDKINKAXIS: readonly dictionary
+@var CHILDKINKAXIS: Which axis to use for offset
+		- X: set X axis for offset
+		- Y: set Y axis for offset
+		- Z: set Z axis for offset
 """
 
 class Particle:
@@ -141,6 +153,38 @@ class Particle:
 	@type childSize: float
 	@ivar childRand: Random variation to the size of the child particles
 	@type childRand: float
+	@ivar childRough1: Amount of location dependant rough
+	@type childRough1: float
+	@ivar childRough1Size: Size of location dependant rough
+	@type childRough1Size: float
+	@ivar childRough2: Amount of random rough
+	@type childRough2: float
+	@ivar childRough2Size: Size of random rough
+	@type childRough2Size: float
+	@ivar childRough2Thresh: Amount of particles left untouched by random rough
+	@type childRough2Thresh: float
+	@ivar childRoughE: Amount of end point rough
+	@type childRoughE: float
+	@ivar childRoughEShape: Shape of end point rough
+	@type childRoughEShape: float
+	@ivar childKink: Type of periodic offset on the path (Particle.CHILDKINK[ 'BRAID' | 'WAVE' | 'RADIAL' | 'CURL' | 'NOTHING' ])
+	@type childKink: int
+	@ivar childKinkAxis: Which axis to use for offset (Particle.CHILDKINKAXIS[ 'Z' | 'Y' | 'X' ])
+	@type childKinkAxis: int
+	@ivar childKinkFreq: The frequency of the offset (1/total length)
+	@type childKinkFreq: float
+	@ivar childKinkShape: Adjust the offset to the beginning/end
+	@type childKinkShape: float
+	@ivar childKinkAmp: The amplitude of the offset
+	@type childKinkAmp: float
+	@ivar childBranch: Branch child paths from eachother
+	@type childBranch: int
+	@ivar childBranch: Animate branching
+	@type childBranch: int
+	@ivar childBranch: Start and end points are the same
+	@type childBranch: int
+	@ivar childBranch: Threshold of branching
+	@type childBranch: float
 	"""
 	
 	def freeEdit():
diff --git a/source/blender/python/api2_2x/doc/SConscript b/source/blender/python/api2_2x/doc/SConscript
index eca5d9a615cc2eef011398a9e66a40d3ca5d3341..c95b844c1f472bde01efd31e2e9a29fb65db8953 100644
--- a/source/blender/python/api2_2x/doc/SConscript
+++ b/source/blender/python/api2_2x/doc/SConscript
@@ -3,26 +3,27 @@ Import ('env')
 
 
 from optparse import OptionParser
-try:
-    import epydoc
-except ImportError:
-    print "No epydoc install detected, Python API Docs will not be generated "
-if epydoc:
-    from epydoc.docbuilder import build_doc_index
-    from epydoc import cli
-    names = env.Glob("source/blender/python/api2_2x/doc/[A-Z]*.py")
-    docindex = build_doc_index(names)
-    optvalues = cli.OPTION_DEFAULTS
-    optvalues["verbose"] = 1
-    optvalues["target"] = env["BF_DOCDIR"]+"/BPY_API/"
-    optvalues["url"] = "http://www.blender.org"
-    optvalues["top"] = "API_intro"
-    optvalues["name"] = "Blender"
-    optvalues["noprivate"] = 1
-    optvalues["noframes"] = 1
-    optvalues["names"] = names
-    optparser = OptionParser()
-    optparser.set_defaults(**optvalues)
-    (options, args) = optparser.parse_args([])
-    cli.write_html(docindex, options)
+import epydoc
+from epydoc.docbuilder import build_doc_index
+from epydoc import cli
+names = env.Glob("source/blender/python/api2_2x/doc/[A-Z]*.py")
+docindex = build_doc_index(names)
+optvalues = cli.OPTION_DEFAULTS
+optvalues["verbose"] = 1
+optvalues["quiet"] = 0
+optvalues["include_source_code"] = 0
+optvalues["inheritance"] = "included"
+optvalues["show_private"] = 0
+optvalues["target"] = env["BF_DOCDIR"]+"/BPY_API/"
+optvalues["url"] = "http://www.blender.org"
+optvalues["top"] = "API_intro"
+optvalues["name"] = "Blender"
+optvalues["noprivate"] = 1
+optvalues["noframes"] = 1
+optvalues["names"] = names
+optparser = OptionParser()
+optparser.set_defaults(**optvalues)
+(options, args) = optparser.parse_args([])
+print "Writing Blender Python epydocs to \"%s\"" % optvalues["target"]
+cli.write_html(docindex, options)
 
diff --git a/source/blender/python/api2_2x/euler.c b/source/blender/python/api2_2x/euler.c
index e349dd26532e1c65285f7afe9a5098b1ee05720c..23f82fc0eb023909b8a57d013a179740b6781d8a 100644
--- a/source/blender/python/api2_2x/euler.c
+++ b/source/blender/python/api2_2x/euler.c
@@ -31,7 +31,6 @@
 #include "BLI_arithb.h"
 #include "BKE_utildefines.h"
 #include "BLI_blenlib.h"
-#include "gen_utils.h"
 
 
 //-------------------------DOC STRINGS ---------------------------
@@ -128,7 +127,8 @@ PyObject *Euler_Unique(EulerObject * self)
 	self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
 	self->eul[2] = (float)(bank * 180 / (float)Py_PI);
 
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject *)self;
 }
 //----------------------------Euler.zero()-------------------------
 //sets the euler to 0,0,0
@@ -138,7 +138,8 @@ PyObject *Euler_Zero(EulerObject * self)
 	self->eul[1] = 0.0;
 	self->eul[2] = 0.0;
 
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject *)self;
 }
 //----------------------------Euler.rotate()-----------------------
 //rotates a euler a certain amount and returns the result
@@ -150,12 +151,12 @@ PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
 	int x;
 
 	if(!PyArg_ParseTuple(args, "fs", &angle, &axis)){
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"euler.rotate():expected angle (float) and axis (x,y,z)");
+		PyErr_SetString(PyExc_TypeError, "euler.rotate():expected angle (float) and axis (x,y,z)");
+		return NULL;
 	}
 	if(!STREQ3(axis,"x","y","z")){
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"euler.rotate(): expected axis to be 'x', 'y' or 'z'");
+		PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'x', 'y' or 'z'");
+		return NULL;
 	}
 
 	//covert to radians
@@ -169,7 +170,8 @@ PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
 		self->eul[x] *= (180 / (float)Py_PI);
 	}
 
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject *)self;
 }
 //----------------------------Euler.rotate()-----------------------
 // return a copy of the euler
@@ -189,71 +191,13 @@ static void Euler_dealloc(EulerObject * self)
 	}
 	PyObject_DEL(self);
 }
-//----------------------------getattr()(internal) ------------------
-//object.attribute access (get)
-static PyObject *Euler_getattr(EulerObject * self, char *name)
-{
-	if(STREQ(name,"x")){
-		return PyFloat_FromDouble(self->eul[0]);
-	}else if(STREQ(name, "y")){
-		return PyFloat_FromDouble(self->eul[1]);
-	}else if(STREQ(name, "z")){
-		return PyFloat_FromDouble(self->eul[2]);
-	}
-	if(STREQ(name, "wrapped")){
-		if(self->wrapped == Py_WRAP)
-			return EXPP_incr_ret((PyObject *)Py_True);
-		else 
-			return EXPP_incr_ret((PyObject *)Py_False);
-	}
-	return Py_FindMethod(Euler_methods, (PyObject *) self, name);
-}
-//----------------------------setattr()(internal) ------------------
-//object.attribute access (set)
-static int Euler_setattr(EulerObject * self, char *name, PyObject * e)
-{
-	PyObject *f = NULL;
-
-	f = PyNumber_Float(e);
-	if(f == NULL) { // parsed item not a number
-		return EXPP_ReturnIntError(PyExc_TypeError, 
-			"euler.attribute = x: argument not a number\n");
-	}
-
-	if(STREQ(name,"x")){
-		self->eul[0] = (float)PyFloat_AS_DOUBLE(f);
-	}else if(STREQ(name, "y")){
-		self->eul[1] = (float)PyFloat_AS_DOUBLE(f);
-	}else if(STREQ(name, "z")){
-		self->eul[2] = (float)PyFloat_AS_DOUBLE(f);
-	}else{
-		Py_DECREF(f);
-		return EXPP_ReturnIntError(PyExc_AttributeError,
-				"euler.attribute = x: unknown attribute\n");
-	}
 
-	Py_DECREF(f);
-	return 0;
-}
 //----------------------------print object (internal)--------------
 //print the object to screen
 static PyObject *Euler_repr(EulerObject * self)
 {
-	int i;
-	char buffer[48], str[1024];
-
-	BLI_strncpy(str,"[",1024);
-	for(i = 0; i < 3; i++){
-		if(i < (2)){
-			sprintf(buffer, "%.6f, ", self->eul[i]);
-			strcat(str,buffer);
-		}else{
-			sprintf(buffer, "%.6f", self->eul[i]);
-			strcat(str,buffer);
-		}
-	}
-	strcat(str, "](euler)");
-
+	char str[64];
+	sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
 	return PyString_FromString(str);
 }
 //------------------------tp_richcmpr
@@ -265,9 +209,9 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar
 
 	if (!EulerObject_Check(objectA) || !EulerObject_Check(objectB)){
 		if (comparison_type == Py_NE){
-			return EXPP_incr_ret(Py_True); 
+			Py_RETURN_TRUE;
 		}else{
-			return EXPP_incr_ret(Py_False);
+			Py_RETURN_FALSE;
 		}
 	}
 	eulA = (EulerObject*)objectA;
@@ -290,9 +234,9 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar
 			break;
 	}
 	if (result == 1){
-		return EXPP_incr_ret(Py_True);
+		Py_RETURN_TRUE;
 	}else{
-		return EXPP_incr_ret(Py_False);
+		Py_RETURN_FALSE;
 	}
 }
 //------------------------tp_doc
@@ -308,32 +252,36 @@ static int Euler_len(EulerObject * self)
 //sequence accessor (get)
 static PyObject *Euler_item(EulerObject * self, int i)
 {
-	if(i < 0 || i >= 3)
-		return EXPP_ReturnPyObjError(PyExc_IndexError,
-		"euler[attribute]: array index out of range\n");
-
+	if(i<0)
+		i= 3-i;
+	
+	if(i < 0 || i >= 3) {
+		PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
+		return NULL;
+	}
 	return PyFloat_FromDouble(self->eul[i]);
 
 }
 //----------------------------object[]-------------------------
 //sequence accessor (set)
-static int Euler_ass_item(EulerObject * self, int i, PyObject * ob)
+static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
 {
-	PyObject *f = NULL;
+	float f = PyFloat_AsDouble(value);
 
-	f = PyNumber_Float(ob);
-	if(f == NULL) { // parsed item not a number
-		return EXPP_ReturnIntError(PyExc_TypeError, 
-			"euler[attribute] = x: argument not a number\n");
+	if(f == -1 && PyErr_Occurred()) { // parsed item not a number
+		PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
+		return -1;
 	}
 
+	if(i<0)
+		i= 3-i;
+	
 	if(i < 0 || i >= 3){
-		Py_DECREF(f);
-		return EXPP_ReturnIntError(PyExc_IndexError,
-			"euler[attribute] = x: array assignment index out of range\n");
+		PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
+		return -1;
 	}
-	self->eul[i] = (float)PyFloat_AS_DOUBLE(f);
-	Py_DECREF(f);
+	
+	self->eul[i] = f;
 	return 0;
 }
 //----------------------------object[z:y]------------------------
@@ -372,26 +320,27 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end,
 
 	size = PySequence_Length(seq);
 	if(size != (end - begin)){
-		return EXPP_ReturnIntError(PyExc_TypeError,
-			"euler[begin:end] = []: size mismatch in slice assignment\n");
+		PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
+		return -1;
 	}
 
 	for (i = 0; i < size; i++) {
 		e = PySequence_GetItem(seq, i);
 		if (e == NULL) { // Failed to read sequence
-			return EXPP_ReturnIntError(PyExc_RuntimeError, 
-				"euler[begin:end] = []: unable to read sequence\n");
+			PyErr_SetString(PyExc_RuntimeError, "euler[begin:end] = []: unable to read sequence");
+			return -1;
 		}
 
 		f = PyNumber_Float(e);
 		if(f == NULL) { // parsed item not a number
 			Py_DECREF(e);
-			return EXPP_ReturnIntError(PyExc_TypeError, 
-				"euler[begin:end] = []: sequence argument not a number\n");
+			PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
+			return -1;
 		}
 
 		eul[i] = (float)PyFloat_AS_DOUBLE(f);
-		EXPP_decr2(f,e);
+		Py_DECREF(f);
+		Py_DECREF(e);
 	}
 	//parsed well - now set in vector
 	for(y = 0; y < 3; y++){
@@ -409,17 +358,100 @@ static PySequenceMethods Euler_SeqMethods = {
 	(intobjargproc) Euler_ass_item,				/* sq_ass_item */
 	(intintobjargproc) Euler_ass_slice,			/* sq_ass_slice */
 };
+
+
+
+/*
+ * vector axis, vector.x/y/z/w
+ */
+	
+static PyObject *Euler_getAxis( EulerObject * self, void *type )
+{
+	switch( (long)type ) {
+    case 'X':	/* these are backwards, but that how it works */
+		return PyFloat_FromDouble(self->eul[0]);
+    case 'Y':
+		return PyFloat_FromDouble(self->eul[1]);
+    case 'Z':
+		return PyFloat_FromDouble(self->eul[2]);
+	}
+	
+	PyErr_SetString(PyExc_SystemError, "corrupt euler, cannot get axis");
+	return NULL;
+}
+
+static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
+{
+	float param= (float)PyFloat_AsDouble( value );
+	
+	if (param==-1 && PyErr_Occurred()) {
+		PyErr_SetString(PyExc_TypeError, "expected a number for the vector axis");
+		return -1;
+	}
+	
+	switch( (long)type ) {
+    case 'X':	/* these are backwards, but that how it works */
+		self->eul[0]= param;
+		break;
+    case 'Y':
+		self->eul[1]= param;
+		break;
+    case 'Z':
+		self->eul[2]= param;
+		break;
+	}
+
+	return 0;
+}
+
+static PyObject *Euler_getWrapped( VectorObject * self, void *type )
+{
+	if (self->wrapped == Py_WRAP)
+		Py_RETURN_TRUE;
+	else
+		Py_RETURN_FALSE;
+}
+
+
+/*****************************************************************************/
+/* Python attributes get/set structure:                                      */
+/*****************************************************************************/
+static PyGetSetDef Euler_getseters[] = {
+	{"x",
+	 (getter)Euler_getAxis, (setter)Euler_setAxis,
+	 "Euler X axis",
+	 (void *)'X'},
+	{"y",
+	 (getter)Euler_getAxis, (setter)Euler_setAxis,
+	 "Euler Y axis",
+	 (void *)'Y'},
+	{"z",
+	 (getter)Euler_getAxis, (setter)Euler_setAxis,
+	 "Euler Z axis",
+	 (void *)'Z'},
+	{"wrapped",
+	 (getter)Euler_getWrapped, (setter)NULL,
+	 "True when this wraps blenders internal data",
+	 NULL},
+	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
+};
+
 //------------------PY_OBECT DEFINITION--------------------------
 PyTypeObject euler_Type = {
-	PyObject_HEAD_INIT(NULL)		//tp_head
-	0,								//tp_internal
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"euler",						//tp_name
 	sizeof(EulerObject),			//tp_basicsize
 	0,								//tp_itemsize
 	(destructor)Euler_dealloc,		//tp_dealloc
 	0,								//tp_print
-	(getattrfunc)Euler_getattr,	//tp_getattr
-	(setattrfunc) Euler_setattr,	//tp_setattr
+	0,								//tp_getattr
+	0,								//tp_setattr
 	0,								//tp_compare
 	(reprfunc) Euler_repr,			//tp_repr
 	0,				//tp_as_number
@@ -439,9 +471,9 @@ PyTypeObject euler_Type = {
 	0,								//tp_weaklistoffset
 	0,								//tp_iter
 	0,								//tp_iternext
-	0,								//tp_methods
+	Euler_methods,					//tp_methods
 	0,								//tp_members
-	0,								//tp_getset
+	Euler_getseters,				//tp_getset
 	0,								//tp_base
 	0,								//tp_dict
 	0,								//tp_descr_get
@@ -494,6 +526,6 @@ PyObject *newEulerObject(float *eul, int type)
 	}else{ //bad type
 		return NULL;
 	}
-	return (PyObject *) self;
+	return (PyObject *)self;
 }
 
diff --git a/source/blender/python/api2_2x/gen_utils.c b/source/blender/python/api2_2x/gen_utils.c
index de3704164ac081b6b6e41f3d87bf41b6ed3a5e23..53ace2759a2a4b6aa09f9cc1e4c2c7cbbbe3258b 100644
--- a/source/blender/python/api2_2x/gen_utils.c
+++ b/source/blender/python/api2_2x/gen_utils.c
@@ -42,36 +42,6 @@
 
 #include "constant.h"
 
-/*---------------------- EXPP_FloatsAreEqual -------------------------
-  Floating point comparisons 
-  floatStep = number of representable floats allowable in between
-   float A and float B to be considered equal. */
-int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
-{
-	int a, b, delta;
-    assert(floatSteps > 0 && floatSteps < (4 * 1024 * 1024));
-    a = *(int*)&A;
-    if (a < 0)	
-		a = 0x80000000 - a;
-    b = *(int*)&B;
-    if (b < 0)	
-		b = 0x80000000 - b;
-    delta = abs(a - b);
-    if (delta <= floatSteps)	
-		return 1;
-    return 0;
-}
-/*---------------------- EXPP_VectorsAreEqual -------------------------
-  Builds on EXPP_FloatsAreEqual to test vectors */
-int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
-
-	int x;
-	for (x=0; x< size; x++){
-		if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
-			return 0;
-	}
-	return 1;
-}
 /*---------------------- EXPP_GetModuleConstant -------------------------
   Helper function for returning a module constant */
 PyObject *EXPP_GetModuleConstant(char *module, char *constant)
@@ -781,7 +751,7 @@ int EXPP_setModuleConstant ( BPy_constant *constant, void *param, char type )
 {
 	PyObject *item;
 
-	if( constant->ob_type != &constant_Type )
+	if( ((PyObject *)constant)->ob_type != &constant_Type )
 		return EXPP_ReturnIntError( PyExc_TypeError,
 			   "expected module constant" );
 
diff --git a/source/blender/python/api2_2x/gen_utils.h b/source/blender/python/api2_2x/gen_utils.h
index f33dc69d703621518f3c7fdfb5e5fcddf45ebdf6..3486b2659498b8b813bfe56e6b0d131b5c443f34 100644
--- a/source/blender/python/api2_2x/gen_utils.h
+++ b/source/blender/python/api2_2x/gen_utils.h
@@ -37,9 +37,9 @@
 
 #include "constant.h"
 
-#define Py_PI  3.14159265358979323846
-#define Py_WRAP 1024
-#define Py_NEW  2048
+// #define Py_PI  3.14159265358979323846
+// #define Py_WRAP 1024
+// #define Py_NEW  2048
 
 /* 
    Py_RETURN_NONE
@@ -77,9 +77,6 @@ typedef int Py_ssize_t;
 /* name of list of Armature weak refs built into __main__ */
 #define ARM_WEAKREF_LIST_NAME "__arm_weakrefs"
 
-int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
-int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
-
 PyObject *EXPP_GetModuleConstant(char *module, char *constant);
 
 int StringEqual( const char *string1, const char *string2 );
diff --git a/source/blender/python/api2_2x/matrix.c b/source/blender/python/api2_2x/matrix.c
index 7802de822cb3fce5ee613dab62811b46a890c6e8..659f746468ad95184f1de23bf6007b9ebe490423 100644
--- a/source/blender/python/api2_2x/matrix.c
+++ b/source/blender/python/api2_2x/matrix.c
@@ -30,7 +30,6 @@
 #include "BKE_utildefines.h"
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
-#include "gen_utils.h"
 
 /*-------------------------DOC STRINGS ---------------------------*/
 char Matrix_Zero_doc[] = "() - set all values in the matrix to 0";
@@ -70,8 +69,8 @@ PyObject *Matrix_toQuat(MatrixObject * self)
 
 	/*must be 3-4 cols, 3-4 rows, square matrix*/
 	if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) {
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
+		return NULL;
 	} 
 	if(self->colSize == 3){
         Mat3ToQuat((float (*)[3])*self->matrix, quat);
@@ -95,10 +94,10 @@ PyObject *Matrix_toEuler(MatrixObject * self)
 		float tempmat3[3][3];
 		Mat3CpyMat4(tempmat3, (float (*)[4])*self->matrix);
 		Mat3ToEul(tempmat3, eul);
-	}else
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
-	
+	}else {
+		PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
+		return NULL;
+	}
 	/*have to convert to degrees*/
 	for(x = 0; x < 3; x++) {
 		eul[x] *= (float) (180 / Py_PI);
@@ -111,20 +110,20 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
 	int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
 
 	if(self->data.blend_data){
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"cannot resize wrapped data - only python matrices\n");
+		PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - only python matrices");
+		return NULL;
 	}
 
 	self->data.py_data = PyMem_Realloc(self->data.py_data, (sizeof(float) * 16));
 	if(self->data.py_data == NULL) {
-		return EXPP_ReturnPyObjError(PyExc_MemoryError,
-			"matrix.resize4x4(): problem allocating pointer space\n\n");
+		PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
+		return NULL;
 	}
 	self->contigPtr = self->data.py_data;  /*force*/
 	self->matrix = PyMem_Realloc(self->matrix, (sizeof(float *) * 4));
 	if(self->matrix == NULL) {
-		return EXPP_ReturnPyObjError(PyExc_MemoryError,
-			"matrix.resize4x4(): problem allocating pointer space\n\n");
+		PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
+		return NULL;
 	}
 	/*set row pointers*/
 	for(x = 0; x < 4; x++) {
@@ -155,7 +154,9 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
 	}
 	self->rowSize = 4;
 	self->colSize = 4;
-	return EXPP_incr_ret((PyObject*)self);
+	
+	Py_INCREF(self);
+	return (PyObject *)self;
 }
 /*---------------------------Matrix.translationPart() ------------*/
 PyObject *Matrix_TranslationPart(MatrixObject * self)
@@ -163,8 +164,8 @@ PyObject *Matrix_TranslationPart(MatrixObject * self)
 	float vec[4];
 
 	if(self->colSize < 3 || self->rowSize < 4){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.translationPart: inappropriate matrix size\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix.translationPart: inappropriate matrix size");
+		return NULL;
 	}
 
 	vec[0] = self->matrix[3][0];
@@ -180,8 +181,8 @@ PyObject *Matrix_RotationPart(MatrixObject * self)
 		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
 
 	if(self->colSize < 3 || self->rowSize < 3){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.rotationPart: inappropriate matrix size\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix.rotationPart: inappropriate matrix size\n");
+		return NULL;
 	}
 
 	mat[0] = self->matrix[0][0];
@@ -207,10 +208,10 @@ PyObject *Matrix_scalePart(MatrixObject * self)
 		Mat3CpyMat4(mat, (float (*)[4])*self->matrix);
 	else if(self->colSize == 3 && self->rowSize == 3)
 		Mat3CpyMat3(mat, (float (*)[3])*self->matrix);
-	else
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.scalePart(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
-	
+	else {
+		PyErr_SetString(PyExc_AttributeError, "Matrix.scalePart(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
+		return NULL;
+	}
 	/* functionality copied from editobject.c apply_obmat */
 	Mat3ToEul(mat, rot);
 	EulToMat3(rot, tmat);
@@ -233,8 +234,8 @@ PyObject *Matrix_Invert(MatrixObject * self)
 		0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
 
 	if(self->rowSize != self->colSize){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.invert(ed): only square matrices are supported\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix.invert(ed): only square matrices are supported");
+		return NULL;
 	}
 
 	/*calculate the determinant*/
@@ -268,10 +269,12 @@ PyObject *Matrix_Invert(MatrixObject * self)
 		/*transpose
 		Matrix_Transpose(self);*/
 	} else {
-		return EXPP_ReturnPyObjError(PyExc_ValueError,
-				"matrix does not have an inverse");
+		PyErr_SetString(PyExc_ValueError, "matrix does not have an inverse");
+		return NULL;
 	}
-	return EXPP_incr_ret((PyObject*)self);
+	
+	Py_INCREF(self);
+	return (PyObject *)self;
 }
 
 
@@ -281,8 +284,8 @@ PyObject *Matrix_Determinant(MatrixObject * self)
 	float det = 0.0f;
 
 	if(self->rowSize != self->colSize){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.determinant: only square matrices are supported\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix.determinant: only square matrices are supported");
+		return NULL;
 	}
 
 	if(self->rowSize == 2) {
@@ -306,8 +309,8 @@ PyObject *Matrix_Transpose(MatrixObject * self)
 	float t = 0.0f;
 
 	if(self->rowSize != self->colSize){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.transpose(d): only square matrices are supported\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix.transpose(d): only square matrices are supported");
+		return NULL;
 	}
 
 	if(self->rowSize == 2) {
@@ -320,7 +323,8 @@ PyObject *Matrix_Transpose(MatrixObject * self)
 		Mat4Transp((float (*)[4])*self->matrix);
 	}
 
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject *)self;
 }
 
 
@@ -334,14 +338,15 @@ PyObject *Matrix_Zero(MatrixObject * self)
 			self->matrix[row][col] = 0.0f;
 		}
 	}
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject *)self;
 }
 /*---------------------------Matrix.identity(() ------------------*/
 PyObject *Matrix_Identity(MatrixObject * self)
 {
 	if(self->rowSize != self->colSize){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix.identity: only square matrices are supported\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix.identity: only square matrices are supported\n");
+		return NULL;
 	}
 
 	if(self->rowSize == 2) {
@@ -355,7 +360,8 @@ PyObject *Matrix_Identity(MatrixObject * self)
 		Mat4One((float (*)[4]) *self->matrix);
 	}
 
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject *)self;
 }
 
 /*---------------------------Matrix.inverted() ------------------*/
@@ -387,9 +393,9 @@ static PyObject *Matrix_getattr(MatrixObject * self, char *name)
 	}
 	if(STREQ(name, "wrapped")){
 		if(self->wrapped == Py_WRAP)
-			return EXPP_incr_ret((PyObject *)Py_True);
+			Py_RETURN_TRUE;
 		else 
-			return EXPP_incr_ret((PyObject *)Py_False);
+			Py_RETURN_FALSE;
 	}
 	return Py_FindMethod(Matrix_methods, (PyObject *) self, name);
 }
@@ -435,9 +441,9 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa
 
 	if (!MatrixObject_Check(objectA) || !MatrixObject_Check(objectB)){
 		if (comparison_type == Py_NE){
-			return EXPP_incr_ret(Py_True); 
+			Py_RETURN_TRUE;
 		}else{
-			return EXPP_incr_ret(Py_False);
+			Py_RETURN_FALSE;
 		}
 	}
 	matA = (MatrixObject*)objectA;
@@ -445,9 +451,9 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa
 
 	if (matA->colSize != matB->colSize || matA->rowSize != matB->rowSize){
 		if (comparison_type == Py_NE){
-			return EXPP_incr_ret(Py_True); 
+			Py_RETURN_TRUE;
 		}else{
-			return EXPP_incr_ret(Py_False);
+			Py_RETURN_FALSE;
 		}
 	}
 
@@ -471,9 +477,9 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa
 			break;
 	}
 	if (result == 1){
-		return EXPP_incr_ret(Py_True);
+		Py_RETURN_TRUE;
 	}else{
-		return EXPP_incr_ret(Py_False);
+		Py_RETURN_FALSE;
 	}
 }
 /*------------------------tp_doc*/
@@ -490,10 +496,10 @@ static int Matrix_len(MatrixObject * self)
   the wrapped vector gives direct access to the matrix data*/
 static PyObject *Matrix_item(MatrixObject * self, int i)
 {
-	if(i < 0 || i >= self->rowSize)
-		return EXPP_ReturnPyObjError(PyExc_IndexError,
-		"matrix[attribute]: array index out of range\n");
-
+	if(i < 0 || i >= self->rowSize) {
+		PyErr_SetString(PyExc_IndexError, "matrix[attribute]: array index out of range");
+		return NULL;
+	}
 	return newVectorObject(self->matrix[i], self->colSize, Py_WRAP);
 }
 /*----------------------------object[]-------------------------
@@ -505,32 +511,33 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
 	PyObject *m, *f;
 
 	if(i >= self->rowSize || i < 0){
-		return EXPP_ReturnIntError(PyExc_TypeError,
-			"matrix[attribute] = x: bad row\n");
+		PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad row\n");
+		return -1;
 	}
 
 	if(PySequence_Check(ob)){
 		size = PySequence_Length(ob);
 		if(size != self->colSize){
-			return EXPP_ReturnIntError(PyExc_TypeError,
-				"matrix[attribute] = x: bad sequence size\n");
+			PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad sequence size\n");
+			return -1;
 		}
 		for (x = 0; x < size; x++) {
 			m = PySequence_GetItem(ob, x);
 			if (m == NULL) { /*Failed to read sequence*/
-				return EXPP_ReturnIntError(PyExc_RuntimeError, 
-					"matrix[attribute] = x: unable to read sequence\n");
+				PyErr_SetString(PyExc_RuntimeError, "matrix[attribute] = x: unable to read sequence\n");
+				return -1;
 			}
 
 			f = PyNumber_Float(m);
 			if(f == NULL) { /*parsed item not a number*/
 				Py_DECREF(m);
-				return EXPP_ReturnIntError(PyExc_TypeError, 
-					"matrix[attribute] = x: sequence argument not a number\n");
+				PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: sequence argument not a number\n");
+				return -1;
 			}
 
 			vec[x] = (float)PyFloat_AS_DOUBLE(f);
-			EXPP_decr2(m, f);
+			Py_DECREF(m);
+			Py_DECREF(f);
 		}
 		/*parsed well - now set in matrix*/
 		for(y = 0; y < size; y++){
@@ -538,8 +545,8 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
 		}
 		return 0;
 	}else{
-		return EXPP_ReturnIntError(PyExc_TypeError,
-			"matrix[attribute] = x: expects a sequence of column size\n");
+		PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: expects a sequence of column size\n");
+		return -1;
 	}
 }
 /*----------------------------object[z:y]------------------------
@@ -568,9 +575,9 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
 			     PyObject * seq)
 {
 	int i, x, y, size, sub_size = 0;
-	float mat[16];
+	float mat[16], f;
 	PyObject *subseq;
-	PyObject *m, *f;
+	PyObject *m;
 
 	CLAMP(begin, 0, self->rowSize);
 	CLAMP(end, 0, self->rowSize);
@@ -579,16 +586,16 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
 	if(PySequence_Check(seq)){
 		size = PySequence_Length(seq);
 		if(size != (end - begin)){
-			return EXPP_ReturnIntError(PyExc_TypeError,
-				"matrix[begin:end] = []: size mismatch in slice assignment\n");
+			PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: size mismatch in slice assignment\n");
+			return -1;
 		}
 		/*parse sub items*/
 		for (i = 0; i < size; i++) {
 			/*parse each sub sequence*/
 			subseq = PySequence_GetItem(seq, i);
 			if (subseq == NULL) { /*Failed to read sequence*/
-				return EXPP_ReturnIntError(PyExc_RuntimeError, 
-					"matrix[begin:end] = []: unable to read sequence\n");
+				PyErr_SetString(PyExc_RuntimeError, "matrix[begin:end] = []: unable to read sequence");
+				return -1;
 			}
 
 			if(PySequence_Check(subseq)){
@@ -596,31 +603,32 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
 				sub_size = PySequence_Length(subseq);
 				if(sub_size != self->colSize){
 					Py_DECREF(subseq);
-					return EXPP_ReturnIntError(PyExc_TypeError,
-						"matrix[begin:end] = []: size mismatch in slice assignment\n");
+					PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: size mismatch in slice assignment\n");
+					return -1;
 				}
 				for (y = 0; y < sub_size; y++) {
 					m = PySequence_GetItem(subseq, y);
 					if (m == NULL) { /*Failed to read sequence*/
 						Py_DECREF(subseq);
-						return EXPP_ReturnIntError(PyExc_RuntimeError, 
-							"matrix[begin:end] = []: unable to read sequence\n");
+						PyErr_SetString(PyExc_RuntimeError, "matrix[begin:end] = []: unable to read sequence\n");
+						return -1;
 					}
-
-					f = PyNumber_Float(m);
-					if(f == NULL) { /*parsed item not a number*/
-						EXPP_decr2(m, subseq);
-						return EXPP_ReturnIntError(PyExc_TypeError, 
-							"matrix[begin:end] = []: sequence argument not a number\n");
+					
+					f = PyFloat_AsDouble(m); /* faster to assume a float and raise an error after */
+					if(f == -1 && PyErr_Occurred()) { /*parsed item not a number*/
+						Py_DECREF(m);
+						Py_DECREF(subseq);
+						PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: sequence argument not a number\n");
+						return -1;
 					}
 
-					mat[(i * self->colSize) + y] = (float)PyFloat_AS_DOUBLE(f);
-					EXPP_decr2(f, m);
+					mat[(i * self->colSize) + y] = f;
+					Py_DECREF(m);
 				}
 			}else{
 				Py_DECREF(subseq);
-				return EXPP_ReturnIntError(PyExc_TypeError,
-					"matrix[begin:end] = []: illegal argument type for built-in operation\n");
+				PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n");
+				return -1;
 			}
 			Py_DECREF(subseq);
 		}
@@ -630,8 +638,8 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
 		}
 		return 0;
 	}else{
-		return EXPP_ReturnIntError(PyExc_TypeError,
-			"matrix[begin:end] = []: illegal argument type for built-in operation\n");
+		PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n");
+		return -1;
 	}
 }
 /*------------------------NUMERIC PROTOCOLS----------------------
@@ -647,12 +655,12 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2)
 	mat2 = (MatrixObject*)m2;
 
 	if(mat1->coerced_object || mat2->coerced_object){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix addition: arguments not valid for this operation....\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
+		return NULL;
 	}
 	if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix addition: matrices must have the same dimensions for this operation\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
+		return NULL;
 	}
 
 	for(x = 0; x < mat1->rowSize; x++) {
@@ -676,12 +684,12 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
 	mat2 = (MatrixObject*)m2;
 
 	if(mat1->coerced_object || mat2->coerced_object){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix addition: arguments not valid for this operation....\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
+		return NULL;
 	}
 	if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Matrix addition: matrices must have the same dimensions for this operation\n");
+		PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
+		return NULL;
 	}
 
 	for(x = 0; x < mat1->rowSize; x++) {
@@ -703,7 +711,6 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
 	double dot = 0.0f;
 	MatrixObject *mat1 = NULL, *mat2 = NULL;
 	PyObject *f = NULL;
-	PointObject *pt = NULL;
 
 	mat1 = (MatrixObject*)m1;
 	mat2 = (MatrixObject*)m2;
@@ -713,8 +720,8 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
 			PyInt_Check(mat1->coerced_object)){	/*FLOAT/INT * MATRIX*/
 			f = PyNumber_Float(mat1->coerced_object);
 			if(f == NULL) { /*parsed item not a number*/
-				return EXPP_ReturnPyObjError(PyExc_TypeError, 
-					"Matrix multiplication: arguments not acceptable for this operation\n");
+				PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
+				return NULL;
 			}
 
 			scalar = (float)PyFloat_AS_DOUBLE(f);
@@ -733,15 +740,11 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
 				vec = (VectorObject*)mat2->coerced_object;
 				return column_vector_multiplication(mat1, vec);
 			}else */
-			if(PointObject_Check(mat2->coerced_object)){ /*MATRIX * POINT*/
-				pt = (PointObject*)mat2->coerced_object;
-				return column_point_multiplication(mat1, pt);
-			}else if (PyFloat_Check(mat2->coerced_object) || 
-				PyInt_Check(mat2->coerced_object)){	/*MATRIX * FLOAT/INT*/
+			if (PyFloat_Check(mat2->coerced_object) || PyInt_Check(mat2->coerced_object)){	/*MATRIX * FLOAT/INT*/
 				f = PyNumber_Float(mat2->coerced_object);
 				if(f == NULL) { /*parsed item not a number*/
-					return EXPP_ReturnPyObjError(PyExc_TypeError, 
-						"Matrix multiplication: arguments not acceptable for this operation\n");
+					PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation\n");
+					return NULL;
 				}
 
 				scalar = (float)PyFloat_AS_DOUBLE(f);
@@ -755,8 +758,8 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
 			}
 		}else{  /*MATRIX * MATRIX*/
 			if(mat1->colSize != mat2->rowSize){
-				return EXPP_ReturnPyObjError(PyExc_AttributeError,
-					"Matrix multiplication: matrix A rowsize must equal matrix B colsize\n");
+				PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize");
+				return NULL;
 			}
 			for(x = 0; x < mat1->rowSize; x++) {
 				for(y = 0; y < mat2->colSize; y++) {
@@ -771,8 +774,8 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
 		}
 	}
 
-	return EXPP_ReturnPyObjError(PyExc_TypeError, 
-		"Matrix multiplication: arguments not acceptable for this operation\n");
+	PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation\n");
+	return NULL;
 }
 static PyObject* Matrix_inv(MatrixObject *self)
 {
@@ -789,17 +792,17 @@ static PyObject* Matrix_inv(MatrixObject *self)
  then call vector.multiply(vector, scalar_cast_as_vector)*/
 static int Matrix_coerce(PyObject ** m1, PyObject ** m2)
 {
-	if(VectorObject_Check(*m2) || PyFloat_Check(*m2) || PyInt_Check(*m2) ||
-			PointObject_Check(*m2)) {
-		PyObject *coerced = EXPP_incr_ret(*m2);
+	if(VectorObject_Check(*m2) || PyFloat_Check(*m2) || PyInt_Check(*m2)) {
+		PyObject *coerced = (PyObject *)(*m2);
+		Py_INCREF(coerced);
 		*m2 = newMatrixObject(NULL,3,3,Py_NEW);
 		((MatrixObject*)*m2)->coerced_object = coerced;
 		Py_INCREF (*m1);
 		return 0;
 	}
 
-	return EXPP_ReturnIntError(PyExc_TypeError, 
-		"matrix.coerce(): unknown operand - can't coerce for numeric protocols");
+	PyErr_SetString(PyExc_TypeError, "matrix.coerce(): unknown operand - can't coerce for numeric protocols");
+	return -1;
 }
 /*-----------------PROTOCOL DECLARATIONS--------------------------*/
 static PySequenceMethods Matrix_SeqMethods = {
@@ -838,8 +841,13 @@ static PyNumberMethods Matrix_NumMethods = {
 };
 /*------------------PY_OBECT DEFINITION--------------------------*/
 PyTypeObject matrix_Type = {
-	PyObject_HEAD_INIT(NULL)		/*tp_head*/
-	0,								/*tp_internal*/
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"matrix",						/*tp_name*/
 	sizeof(MatrixObject),			/*tp_basicsize*/
 	0,								/*tp_itemsize*/
@@ -910,8 +918,8 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
 
 	/*matrix objects can be any 2-4row x 2-4col matrix*/
 	if(rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4){
-		return EXPP_ReturnPyObjError(PyExc_RuntimeError,
-			"matrix(): row and column sizes must be between 2 and 4\n");
+		PyErr_SetString(PyExc_RuntimeError, "matrix(): row and column sizes must be between 2 and 4");
+		return NULL;
 	}
 
 	self = PyObject_NEW(MatrixObject, &matrix_Type);
@@ -927,8 +935,8 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
 		/*create pointer array*/
 		self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
 		if(self->matrix == NULL) { /*allocation failure*/
-			return EXPP_ReturnPyObjError( PyExc_MemoryError,
-				"matrix(): problem allocating pointer space\n");
+			PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space");
+			return NULL;
 		}
 		/*pointer array points to contigous memory*/
 		for(x = 0; x < rowSize; x++) {
@@ -938,16 +946,16 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
 	}else if (type == Py_NEW){
 		self->data.py_data = PyMem_Malloc(rowSize * colSize * sizeof(float));
 		if(self->data.py_data == NULL) { /*allocation failure*/
-			return EXPP_ReturnPyObjError( PyExc_MemoryError,
-				"matrix(): problem allocating pointer space\n");
+			PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space\n");
+			return NULL;
 		}
 		self->contigPtr = self->data.py_data;
 		/*create pointer array*/
 		self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
 		if(self->matrix == NULL) { /*allocation failure*/
 			PyMem_Free(self->data.py_data);
-			return EXPP_ReturnPyObjError( PyExc_MemoryError,
-				"matrix(): problem allocating pointer space\n");
+			PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space");
+			return NULL;
 		}
 		/*pointer array points to contigous memory*/
 		for(x = 0; x < rowSize; x++) {
diff --git a/source/blender/python/api2_2x/modules.h b/source/blender/python/api2_2x/modules.h
index 8700188b2e92ee1e1227dd2108382821ea5b67f8..0273e357d981b35b1c4007fd1aafbf21ef05ed1d 100644
--- a/source/blender/python/api2_2x/modules.h
+++ b/source/blender/python/api2_2x/modules.h
@@ -52,7 +52,7 @@ BGL is a special case.  It still has data declarations in the .h file
 and cannot be #included until it is cleaned up.
 ****************************************************************************/
 
-PyObject *BGL_Init( void );
+PyObject *BGL_Init( const char *from );
 
 PyObject *Library_Init( void );
 PyObject *Noise_Init( void );
diff --git a/source/blender/python/api2_2x/point.c b/source/blender/python/api2_2x/point.c
deleted file mode 100644
index 0bdedfecdd60f98b13e9fb2d3495ba511e39d6dc..0000000000000000000000000000000000000000
--- a/source/blender/python/api2_2x/point.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/* 
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * 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 2
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA	02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
-*/
-#include "Mathutils.h"
-
-#include "BLI_blenlib.h"
-#include "BKE_utildefines.h"
-#include "gen_utils.h"
-
-//-------------------------DOC STRINGS ---------------------------
-char Point_Zero_doc[] = "() - set all values in the point to 0";
-char Point_toVector_doc[] = "() - create a vector representation of this point";
-//-----------------------METHOD DEFINITIONS ----------------------
-struct PyMethodDef Point_methods[] = {
-	{"zero", (PyCFunction) Point_Zero, METH_NOARGS, Point_Zero_doc},
-	{"toVector", (PyCFunction) Point_toVector, METH_NOARGS, Point_toVector_doc},
-	{NULL, NULL, 0, NULL}
-};
-//-----------------------------METHODS----------------------------
-//--------------------------Vector.toPoint()----------------------
-//create a new point object to represent this vector
-PyObject *Point_toVector(PointObject * self)
-{
-	float vec[3];
-	int x;
-
-	for(x = 0; x < self->size; x++){
-		vec[x] = self->coord[x];
-	}
-	
-	return newVectorObject(vec, self->size, Py_NEW);
-}
-//----------------------------Point.zero() ----------------------
-//set the point data to 0,0,0
-PyObject *Point_Zero(PointObject * self)
-{
-	int x;
-	for(x = 0; x < self->size; x++) {
-		self->coord[x] = 0.0f;
-	}
-	return EXPP_incr_ret((PyObject*)self);
-}
-//----------------------------dealloc()(internal) ----------------
-//free the py_object
-static void Point_dealloc(PointObject * self)
-{
-	Py_XDECREF(self->coerced_object);
-	//only free py_data
-	if(self->data.py_data){
-		PyMem_Free(self->data.py_data);
-	}
-	PyObject_DEL(self);
-}
-//----------------------------getattr()(internal) ----------------
-//object.attribute access (get)
-static PyObject *Point_getattr(PointObject * self, char *name)
-{
-	if(STREQ(name,"x")){
-		return PyFloat_FromDouble(self->coord[0]);
-	}else if(STREQ(name, "y")){
-		return PyFloat_FromDouble(self->coord[1]);
-	}else if(STREQ(name, "z")){
-		if(self->size > 2){
-			return PyFloat_FromDouble(self->coord[2]);
-		}else{
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"point.z: illegal attribute access\n");
-		}
-	}
-	if(STREQ(name, "wrapped")){
-		if(self->wrapped == Py_WRAP)
-			return EXPP_incr_ret((PyObject *)Py_True);
-		else 
-			return EXPP_incr_ret((PyObject *)Py_False);
-	}
-	return Py_FindMethod(Point_methods, (PyObject *) self, name);
-}
-//----------------------------setattr()(internal) ----------------
-//object.attribute access (set)
-static int Point_setattr(PointObject * self, char *name, PyObject * v)
-{
-	PyObject *f = NULL;
-
-	f = PyNumber_Float(v);
-	if(f == NULL) { // parsed item not a number
-		return EXPP_ReturnIntError(PyExc_TypeError, 
-			"point.attribute = x: argument not a number\n");
-	}
-
-	if(STREQ(name,"x")){
-		self->coord[0] = (float)PyFloat_AS_DOUBLE(f);
-	}else if(STREQ(name, "y")){
-		self->coord[1] = (float)PyFloat_AS_DOUBLE(f);
-	}else if(STREQ(name, "z")){
-		if(self->size > 2){
-			self->coord[2] = (float)PyFloat_AS_DOUBLE(f);
-		}else{
-			Py_DECREF(f);
-			return EXPP_ReturnIntError(PyExc_AttributeError,
-				"point.z = x: illegal attribute access\n");
-		}
-	}else{
-		Py_DECREF(f);
-		return EXPP_ReturnIntError(PyExc_AttributeError,
-				"point.attribute = x: unknown attribute\n");
-	}
-
-	Py_DECREF(f);
-	return 0;
-}
-//----------------------------print object (internal)-------------
-//print the object to screen
-static PyObject *Point_repr(PointObject * self)
-{
-	int i;
-	char buffer[48], str[1024];
-
-	BLI_strncpy(str,"[",1024);
-	for(i = 0; i < self->size; i++){
-		if(i < (self->size - 1)){
-			sprintf(buffer, "%.6f, ", self->coord[i]);
-			strcat(str,buffer);
-		}else{
-			sprintf(buffer, "%.6f", self->coord[i]);
-			strcat(str,buffer);
-		}
-	}
-	strcat(str, "](point)");
-
-	return PyString_FromString(str);
-}
-//---------------------SEQUENCE PROTOCOLS------------------------
-//----------------------------len(object)------------------------
-//sequence length
-static int Point_len(PointObject * self)
-{
-	return self->size;
-}
-//----------------------------object[]---------------------------
-//sequence accessor (get)
-static PyObject *Point_item(PointObject * self, int i)
-{
-	if(i < 0 || i >= self->size)
-		return EXPP_ReturnPyObjError(PyExc_IndexError,
-		"point[attribute]: array index out of range\n");
-
-	return PyFloat_FromDouble( (double)self->coord[i] );
-
-}
-//----------------------------object[]-------------------------
-//sequence accessor (set)
-static int Point_ass_item(PointObject * self, int i, PyObject * ob)
-{
-	PyObject *f = NULL;
-
-	f = PyNumber_Float(ob);
-	if(f == NULL) { // parsed item not a number
-		return EXPP_ReturnIntError(PyExc_TypeError, 
-			"point[attribute] = x: argument not a number\n");
-	}
-
-	if(i < 0 || i >= self->size){
-		Py_DECREF(f);
-		return EXPP_ReturnIntError(PyExc_IndexError,
-			"point[attribute] = x: array assignment index out of range\n");
-	}
-	self->coord[i] = (float)PyFloat_AS_DOUBLE(f);
-	Py_DECREF(f);
-	return 0;
-}
-//----------------------------object[z:y]------------------------
-//sequence slice (get)
-static PyObject *Point_slice(PointObject * self, int begin, int end)
-{
-	PyObject *list = NULL;
-	int count;
-
-	CLAMP(begin, 0, self->size);
-	CLAMP(end, 0, self->size);
-	begin = MIN2(begin,end);
-
-	list = PyList_New(end - begin);
-	for(count = begin; count < end; count++) {
-		PyList_SetItem(list, count - begin,
-				PyFloat_FromDouble(self->coord[count]));
-	}
-
-	return list;
-}
-//----------------------------object[z:y]------------------------
-//sequence slice (set)
-static int Point_ass_slice(PointObject * self, int begin, int end,
-			     PyObject * seq)
-{
-	int i, y, size = 0;
-	float coord[3];
-	PyObject *v, *f;
-
-	CLAMP(begin, 0, self->size);
-	CLAMP(end, 0, self->size);
-	begin = MIN2(begin,end);
-
-	size = PySequence_Length(seq);
-	if(size != (end - begin)){
-		return EXPP_ReturnIntError(PyExc_TypeError,
-			"point[begin:end] = []: size mismatch in slice assignment\n");
-	}
-
-	for (i = 0; i < size; i++) {
-		v = PySequence_GetItem(seq, i);
-		if (v == NULL) { // Failed to read sequence
-			return EXPP_ReturnIntError(PyExc_RuntimeError, 
-				"point[begin:end] = []: unable to read sequence\n");
-		}
-		f = PyNumber_Float(v);
-		if(f == NULL) { // parsed item not a number
-			Py_DECREF(v);
-			return EXPP_ReturnIntError(PyExc_TypeError, 
-				"point[begin:end] = []: sequence argument not a number\n");
-		}
-
-		coord[i] = (float)PyFloat_AS_DOUBLE(f);
-		EXPP_decr2(f,v);
-	}
-	//parsed well - now set in point
-	for(y = 0; y < size; y++){
-		self->coord[begin + y] = coord[y];
-	}
-	return 0;
-}
-//------------------------NUMERIC PROTOCOLS----------------------
-//------------------------obj + obj------------------------------
-//addition
-static PyObject *Point_add(PyObject * v1, PyObject * v2)
-{
-	int x, size;
-	float coord[3];
-	PointObject *coord1 = NULL, *coord2 = NULL;
-	VectorObject *vec = NULL;
-
-	coord1 = (PointObject*)v1;
-	coord2 = (PointObject*)v2;
-
-	if(!coord1->coerced_object){
-		if(coord2->coerced_object){
-			if(VectorObject_Check(coord2->coerced_object)){  //POINT + VECTOR
-				//Point translation
-				vec = (VectorObject*)coord2->coerced_object;
-				size = coord1->size;
-				if(vec->size == size){
-					for(x = 0; x < size; x++){
-						coord[x] = coord1->coord[x] + vec->vec[x];
-					}	
-				}else{
-					return EXPP_ReturnPyObjError(PyExc_AttributeError,
-						"Point addition: arguments are the wrong size....\n");
-				}
-				return newPointObject(coord, size, Py_NEW);
-			}	
-		}else{  //POINT + POINT
-			size = coord1->size;
-			if(coord2->size == size){
-				for(x = 0; x < size; x++) {
-					coord[x] = coord1->coord[x] + coord2->coord[x];
-				}
-			}else{
-				return EXPP_ReturnPyObjError(PyExc_AttributeError,
-					"Point addition: arguments are the wrong size....\n");
-			}
-			return newPointObject(coord, size, Py_NEW);
-		}
-	}
-
-	return EXPP_ReturnPyObjError(PyExc_AttributeError,
-		"Point addition: arguments not valid for this operation....\n");
-}
-//------------------------obj - obj------------------------------
-//subtraction
-static PyObject *Point_sub(PyObject * v1, PyObject * v2)
-{
-	int x, size;
-	float coord[3];
-	PointObject *coord1 = NULL, *coord2 = NULL;
-
-	coord1 = (PointObject*)v1;
-	coord2 = (PointObject*)v2;
-
-	if(coord1->coerced_object || coord2->coerced_object){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Point subtraction: arguments not valid for this operation....\n");
-	}
-	if(coord1->size != coord2->size){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-		"Point subtraction: points must have the same dimensions for this operation\n");
-	}
-
-	size = coord1->size;
-	for(x = 0; x < size; x++) {
-		coord[x] = coord1->coord[x] -	coord2->coord[x];
-	}
-
-	//Point - Point = Vector
-	return newVectorObject(coord, size, Py_NEW);
-}
-//------------------------obj * obj------------------------------
-//mulplication
-static PyObject *Point_mul(PyObject * p1, PyObject * p2)
-{
-	int x, size;
-	float coord[3], scalar;
-	PointObject *coord1 = NULL, *coord2 = NULL;
-	PyObject *f = NULL;
-	MatrixObject *mat = NULL;
-	QuaternionObject *quat = NULL;
-
-	coord1 = (PointObject*)p1;
-	coord2 = (PointObject*)p2;
-
-	if(coord1->coerced_object){
-		if (PyFloat_Check(coord1->coerced_object) || 
-			PyInt_Check(coord1->coerced_object)){	// FLOAT/INT * POINT
-			f = PyNumber_Float(coord1->coerced_object);
-			if(f == NULL) { // parsed item not a number
-				return EXPP_ReturnPyObjError(PyExc_TypeError, 
-					"Point multiplication: arguments not acceptable for this operation\n");
-			}
-
-			scalar = (float)PyFloat_AS_DOUBLE(f);
-			size = coord2->size;
-			for(x = 0; x < size; x++) {
-				coord[x] = coord2->coord[x] *	scalar;
-			}
-			Py_DECREF(f);
-			return newPointObject(coord, size, Py_NEW);
-		}
-	}else{
-		if(coord2->coerced_object){
-			if (PyFloat_Check(coord2->coerced_object) || 
-				PyInt_Check(coord2->coerced_object)){	// POINT * FLOAT/INT
-				f = PyNumber_Float(coord2->coerced_object);
-				if(f == NULL) { // parsed item not a number
-					return EXPP_ReturnPyObjError(PyExc_TypeError, 
-						"Point multiplication: arguments not acceptable for this operation\n");
-				}
-
-				scalar = (float)PyFloat_AS_DOUBLE(f);
-				size = coord1->size;
-				for(x = 0; x < size; x++) {
-					coord[x] = coord1->coord[x] *	scalar;
-				}
-				Py_DECREF(f);
-				return newPointObject(coord, size, Py_NEW);
-			}else if(MatrixObject_Check(coord2->coerced_object)){ //POINT * MATRIX
-				mat = (MatrixObject*)coord2->coerced_object;
-				return row_point_multiplication(coord1, mat);
-			}else if(QuaternionObject_Check(coord2->coerced_object)){  //POINT * QUATERNION
-				quat = (QuaternionObject*)coord2->coerced_object;
-				if(coord1->size != 3){
-					return EXPP_ReturnPyObjError(PyExc_TypeError, 
-						"Point multiplication: only 3D point rotations (with quats) currently supported\n");
-				}
-				return quat_rotation((PyObject*)coord1, (PyObject*)quat);
-			}
-		}
-	}
-
-	return EXPP_ReturnPyObjError(PyExc_TypeError, 
-		"Point multiplication: arguments not acceptable for this operation\n");
-}
-//-------------------------- -obj -------------------------------
-//returns the negative of this object
-static PyObject *Point_neg(PointObject *self)
-{
-	int x;
-	float coord[3];
-
-	for(x = 0; x < self->size; x++)
-		coord[x] = -self->coord[x];
-
-	return newPointObject(coord, self->size, Py_NEW);
-}
-
-//------------------------coerce(obj, obj)-----------------------
-//coercion of unknown types to type PointObject for numeric protocols
-/*Coercion() is called whenever a math operation has 2 operands that
- it doesn't understand how to evaluate. 2+Matrix for example. We want to 
- evaluate some of these operations like: (vector * 2), however, for math
- to proceed, the unknown operand must be cast to a type that python math will
- understand. (e.g. in the case above case, 2 must be cast to a vector and 
- then call vector.multiply(vector, scalar_cast_as_vector)*/
-static int Point_coerce(PyObject ** p1, PyObject ** p2)
-{
-	if(VectorObject_Check(*p2) || PyFloat_Check(*p2) || PyInt_Check(*p2) ||
-			MatrixObject_Check(*p2) || QuaternionObject_Check(*p2)) {
-		PyObject *coerced = EXPP_incr_ret(*p2);
-		*p2 = newPointObject(NULL,3,Py_NEW);
-		((PointObject*)*p2)->coerced_object = coerced;
-		Py_INCREF (*p1);
-		return 0;
-	}
-
-	return EXPP_ReturnIntError(PyExc_TypeError, 
-		"point.coerce(): unknown operand - can't coerce for numeric protocols");
-}
-//-----------------PROTOCOL DECLARATIONS--------------------------
-static PySequenceMethods Point_SeqMethods = {
-	(inquiry) Point_len,						/* sq_length */
-	(binaryfunc) 0,								/* sq_concat */
-	(intargfunc) 0,								/* sq_repeat */
-	(intargfunc) Point_item,					/* sq_item */
-	(intintargfunc) Point_slice,				/* sq_slice */
-	(intobjargproc) Point_ass_item,				/* sq_ass_item */
-	(intintobjargproc) Point_ass_slice,			/* sq_ass_slice */
-};
-static PyNumberMethods Point_NumMethods = {
-	(binaryfunc) Point_add,						/* __add__ */
-	(binaryfunc) Point_sub,						/* __sub__ */
-	(binaryfunc) Point_mul,						/* __mul__ */
-	(binaryfunc) 0,								/* __div__ */
-	(binaryfunc) 0,								/* __mod__ */
-	(binaryfunc) 0,								/* __divmod__ */
-	(ternaryfunc) 0,							/* __pow__ */
-	(unaryfunc) Point_neg,						/* __neg__ */
-	(unaryfunc) 0,								/* __pos__ */
-	(unaryfunc) 0,								/* __abs__ */
-	(inquiry) 0,								/* __nonzero__ */
-	(unaryfunc) 0,								/* __invert__ */
-	(binaryfunc) 0,								/* __lshift__ */
-	(binaryfunc) 0,								/* __rshift__ */
-	(binaryfunc) 0,								/* __and__ */
-	(binaryfunc) 0,								/* __xor__ */
-	(binaryfunc) 0,								/* __or__ */
-	(coercion)  Point_coerce,					/* __coerce__ */
-	(unaryfunc) 0,								/* __int__ */
-	(unaryfunc) 0,								/* __long__ */
-	(unaryfunc) 0,								/* __float__ */
-	(unaryfunc) 0,								/* __oct__ */
-	(unaryfunc) 0,								/* __hex__ */
-
-};
-//------------------PY_OBECT DEFINITION--------------------------
-PyTypeObject point_Type = {
-	PyObject_HEAD_INIT(NULL) 
-	0,											/*ob_size */
-	"point",									/*tp_name */
-	sizeof(PointObject),						/*tp_basicsize */
-	0,											/*tp_itemsize */
-	(destructor) Point_dealloc,					/*tp_dealloc */
-	(printfunc) 0,								/*tp_print */
-	(getattrfunc) Point_getattr,				/*tp_getattr */
-	(setattrfunc) Point_setattr,				/*tp_setattr */
-	0,											/*tp_compare */
-	(reprfunc) Point_repr,						/*tp_repr */
-	&Point_NumMethods,							/*tp_as_number */
-	&Point_SeqMethods,							/*tp_as_sequence */
-};
-//------------------------newPointObject (internal)-------------
-//creates a new point object
-/*pass Py_WRAP - if point is a WRAPPER for data allocated by BLENDER
- (i.e. it was allocated elsewhere by MEM_mallocN())
-  pass Py_NEW - if point is not a WRAPPER and managed by PYTHON
- (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *newPointObject(float *coord, int size, int type)
-{
-	PointObject *self;
-	int x;
-
-	point_Type.ob_type = &PyType_Type;
-	self = PyObject_NEW(PointObject, &point_Type);
-	self->data.blend_data = NULL;
-	self->data.py_data = NULL;
-	if(size > 3 || size < 2)
-		return NULL;
-	self->size = size;
-	self->coerced_object = NULL;
-
-	if(type == Py_WRAP){
-		self->data.blend_data = coord;
-		self->coord = self->data.blend_data;
-		self->wrapped = Py_WRAP;
-	}else if (type == Py_NEW){
-		self->data.py_data = PyMem_Malloc(size * sizeof(float));
-		self->coord = self->data.py_data;
-		if(!coord) { //new empty
-			for(x = 0; x < size; x++){
-				self->coord[x] = 0.0f;
-			}
-		}else{
-			for(x = 0; x < size; x++){
-				self->coord[x] = coord[x];
-			}
-		}
-		self->wrapped = Py_NEW;
-	}else{ //bad type
-		return NULL;
-	}
-	return (PyObject *) self;
-}
diff --git a/source/blender/python/api2_2x/point.h b/source/blender/python/api2_2x/point.h
deleted file mode 100644
index a9c4e5e4e2c8736c7289dee0753d155209735628..0000000000000000000000000000000000000000
--- a/source/blender/python/api2_2x/point.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * 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 2
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA	02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
-*/
-
-#ifndef EXPP_point_h
-#define EXPP_point_h
-
-#include <Python.h>
-
-extern PyTypeObject point_Type;
-
-#define PointObject_Check(v) ((v)->ob_type == &point_Type)
-
-typedef struct {
-	PyObject_VAR_HEAD 
-	struct{
-		float *py_data;		//python managed
-		float *blend_data;	//blender managed
-	}data;
-	float *coord;			//1D array of data (alias)
-	int size;
-	int wrapped;			//is wrapped data?
-	PyObject *coerced_object;
-} PointObject;
-/*coerced_object is a pointer to the object that it was
-coerced from when a dummy vector needs to be created from
-the coerce() function for numeric protocol operations*/
-
-/*struct data contains a pointer to the actual data that the
-object uses. It can use either PyMem allocated data (which will
-be stored in py_data) or be a wrapper for data allocated through
-blender (stored in blend_data). This is an either/or struct not both*/
-
-//prototypes
-PyObject *Point_Zero( PointObject * self );
-PyObject *Point_toVector(PointObject * self);
-PyObject *newPointObject(float *coord, int size, int type);
-
-#endif				/* EXPP_point_h */
diff --git a/source/blender/python/api2_2x/quat.c b/source/blender/python/api2_2x/quat.c
index 7cfc1a7cde865da82d0931ab2760e9493fe68e67..9c718d95c63d191ad0b9b2bebae279c2bd79355a 100644
--- a/source/blender/python/api2_2x/quat.c
+++ b/source/blender/python/api2_2x/quat.c
@@ -31,7 +31,6 @@
 #include "BLI_arithb.h"
 #include "BKE_utildefines.h"
 #include "BLI_blenlib.h"
-#include "gen_utils.h"
 
 
 //-------------------------DOC STRINGS ---------------------------
@@ -84,7 +83,8 @@ PyObject *Quaternion_ToMatrix(QuaternionObject * self)
 PyObject *Quaternion_Normalize(QuaternionObject * self)
 {
 	NormalQuat(self->quat);
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 //----------------------------Quaternion.inverse()------------------
 //invert the quat
@@ -104,7 +104,8 @@ PyObject *Quaternion_Inverse(QuaternionObject * self)
 		self->quat[x] /= (float)(mag * mag);
 	}
 
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 //----------------------------Quaternion.identity()-----------------
 //generate the identity quaternion
@@ -115,7 +116,8 @@ PyObject *Quaternion_Identity(QuaternionObject * self)
 	self->quat[2] = 0.0;
 	self->quat[3] = 0.0;
 
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 //----------------------------Quaternion.negate()-------------------
 //negate the quat
@@ -125,7 +127,8 @@ PyObject *Quaternion_Negate(QuaternionObject * self)
 	for(x = 0; x < 4; x++) {
 		self->quat[x] = -self->quat[x];
 	}
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 //----------------------------Quaternion.conjugate()----------------
 //negate the vector part
@@ -135,7 +138,8 @@ PyObject *Quaternion_Conjugate(QuaternionObject * self)
 	for(x = 1; x < 4; x++) {
 		self->quat[x] = -self->quat[x];
 	}
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 //----------------------------Quaternion.copy()----------------
 //return a copy of the quat
@@ -155,109 +159,13 @@ static void Quaternion_dealloc(QuaternionObject * self)
 	}
 	PyObject_DEL(self);
 }
-//----------------------------getattr()(internal) ------------------
-//object.attribute access (get)
-static PyObject *Quaternion_getattr(QuaternionObject * self, char *name)
-{
-	int x;
-	double mag = 0.0f;
-	float vec[3];
-
-	if(STREQ(name,"w")){
-		return PyFloat_FromDouble(self->quat[0]);
-	}else if(STREQ(name, "x")){
-		return PyFloat_FromDouble(self->quat[1]);
-	}else if(STREQ(name, "y")){
-		return PyFloat_FromDouble(self->quat[2]);
-	}else if(STREQ(name, "z")){
-		return PyFloat_FromDouble(self->quat[3]);
-	}
-	if(STREQ(name, "magnitude")) {
-		for(x = 0; x < 4; x++) {
-			mag += self->quat[x] * self->quat[x];
-		}
-		mag = sqrt(mag);
-		return PyFloat_FromDouble(mag);
-	}
-	if(STREQ(name, "angle")) {
-		mag = self->quat[0];
-		mag = 2 * (saacos(mag));
-		mag *= (180 / Py_PI);
-		return PyFloat_FromDouble(mag);
-	}
-	if(STREQ(name, "axis")) {
-		mag = self->quat[0] * (Py_PI / 180);
-		mag = 2 * (saacos(mag));
-		mag = sin(mag / 2);
-		for(x = 0; x < 3; x++) {
-			vec[x] = (float)(self->quat[x + 1] / mag);
-		}
-		Normalize(vec);
-		//If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations
-		if( EXPP_FloatsAreEqual(vec[0], 0.0f, 10) &&
-			EXPP_FloatsAreEqual(vec[1], 0.0f, 10) &&
-			EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
-			vec[0] = 1.0f;
-		}
-		return (PyObject *) newVectorObject(vec, 3, Py_NEW);
-	}
-	if(STREQ(name, "wrapped")){
-		if(self->wrapped == Py_WRAP)
-			return EXPP_incr_ret((PyObject *)Py_True);
-		else 
-			return EXPP_incr_ret((PyObject *)Py_False);
-	}
-
-	return Py_FindMethod(Quaternion_methods, (PyObject *) self, name);
-}
-//----------------------------setattr()(internal) ------------------
-//object.attribute access (set)
-static int Quaternion_setattr(QuaternionObject * self, char *name, PyObject * q)
-{
-	PyObject *f = NULL;
 
-	f = PyNumber_Float(q);
-	if(f == NULL) { // parsed item not a number
-		return EXPP_ReturnIntError(PyExc_TypeError, 
-			"quaternion.attribute = x: argument not a number\n");
-	}
-
-	if(STREQ(name,"w")){
-		self->quat[0] = (float)PyFloat_AS_DOUBLE(f);
-	}else if(STREQ(name, "x")){
-		self->quat[1] = (float)PyFloat_AS_DOUBLE(f);
-	}else if(STREQ(name, "y")){
-		self->quat[2] = (float)PyFloat_AS_DOUBLE(f);
-	}else if(STREQ(name, "z")){
-		self->quat[3] = (float)PyFloat_AS_DOUBLE(f);
-	}else{
-		Py_DECREF(f);
-		return EXPP_ReturnIntError(PyExc_AttributeError,
-				"quaternion.attribute = x: unknown attribute\n");
-	}
-
-	Py_DECREF(f);
-	return 0;
-}
 //----------------------------print object (internal)--------------
 //print the object to screen
 static PyObject *Quaternion_repr(QuaternionObject * self)
 {
-	int i;
-	char buffer[48], str[1024];
-
-	BLI_strncpy(str,"[",1024);
-	for(i = 0; i < 4; i++){
-		if(i < (3)){
-			sprintf(buffer, "%.6f, ", self->quat[i]);
-			strcat(str,buffer);
-		}else{
-			sprintf(buffer, "%.6f", self->quat[i]);
-			strcat(str,buffer);
-		}
-	}
-	strcat(str, "](quaternion)");
-
+	char str[64];
+	sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]);
 	return PyString_FromString(str);
 }
 //------------------------tp_richcmpr
@@ -269,9 +177,9 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c
 
 	if (!QuaternionObject_Check(objectA) || !QuaternionObject_Check(objectB)){
 		if (comparison_type == Py_NE){
-			return EXPP_incr_ret(Py_True); 
+			Py_RETURN_TRUE;
 		}else{
-			return EXPP_incr_ret(Py_False);
+			Py_RETURN_FALSE;
 		}
 	}
 	quatA = (QuaternionObject*)objectA;
@@ -294,9 +202,9 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c
 			break;
 	}
 	if (result == 1){
-		return EXPP_incr_ret(Py_True);
+		Py_RETURN_TRUE;
 	}else{
-		return EXPP_incr_ret(Py_False);
+		Py_RETURN_FALSE;
 	}
 }
 //------------------------tp_doc
@@ -312,9 +220,10 @@ static int Quaternion_len(QuaternionObject * self)
 //sequence accessor (get)
 static PyObject *Quaternion_item(QuaternionObject * self, int i)
 {
-	if(i < 0 || i >= 4)
-		return EXPP_ReturnPyObjError(PyExc_IndexError,
-		"quaternion[attribute]: array index out of range\n");
+	if(i < 0 || i >= 4) {
+		PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n");
+		return NULL;
+	}
 	return PyFloat_FromDouble(self->quat[i]);
 
 }
@@ -326,14 +235,14 @@ static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
 
 	f = PyNumber_Float(ob);
 	if(f == NULL) { // parsed item not a number
-		return EXPP_ReturnIntError(PyExc_TypeError, 
-			"quaternion[attribute] = x: argument not a number\n");
+		PyErr_SetString(PyExc_TypeError, "quaternion[attribute] = x: argument not a number\n");
+		return -1;
 	}
 
 	if(i < 0 || i >= 4){
 		Py_DECREF(f);
-		return EXPP_ReturnIntError(PyExc_IndexError,
-			"quaternion[attribute] = x: array assignment index out of range\n");
+		PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n");
+		return -1;
 	}
 	self->quat[i] = (float)PyFloat_AS_DOUBLE(f);
 	Py_DECREF(f);
@@ -375,26 +284,27 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end,
 
 	size = PySequence_Length(seq);
 	if(size != (end - begin)){
-		return EXPP_ReturnIntError(PyExc_TypeError,
-			"quaternion[begin:end] = []: size mismatch in slice assignment\n");
+		PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: size mismatch in slice assignment\n");
+		return -1;
 	}
 
 	for (i = 0; i < size; i++) {
 		q = PySequence_GetItem(seq, i);
 		if (q == NULL) { // Failed to read sequence
-			return EXPP_ReturnIntError(PyExc_RuntimeError, 
-				"quaternion[begin:end] = []: unable to read sequence\n");
+			PyErr_SetString(PyExc_RuntimeError, "quaternion[begin:end] = []: unable to read sequence\n");
+			return -1;
 		}
 
 		f = PyNumber_Float(q);
 		if(f == NULL) { // parsed item not a number
 			Py_DECREF(q);
-			return EXPP_ReturnIntError(PyExc_TypeError, 
-				"quaternion[begin:end] = []: sequence argument not a number\n");
+			PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n");
+			return -1;
 		}
 
 		quat[i] = (float)PyFloat_AS_DOUBLE(f);
-		EXPP_decr2(f,q);
+		Py_DECREF(f);
+		Py_DECREF(q);
 	}
 	//parsed well - now set in vector
 	for(y = 0; y < size; y++){
@@ -415,8 +325,8 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
 	quat2 = (QuaternionObject*)q2;
 
 	if(quat1->coerced_object || quat2->coerced_object){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Quaternion addition: arguments not valid for this operation....\n");
+		PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
+		return NULL;
 	}
 	for(x = 0; x < 4; x++) {
 		quat[x] = quat1->quat[x] + quat2->quat[x];
@@ -436,8 +346,8 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
 	quat2 = (QuaternionObject*)q2;
 
 	if(quat1->coerced_object || quat2->coerced_object){
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Quaternion addition: arguments not valid for this operation....\n");
+		PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
+		return NULL;
 	}
 	for(x = 0; x < 4; x++) {
 		quat[x] = quat1->quat[x] - quat2->quat[x];
@@ -455,7 +365,6 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
 	QuaternionObject *quat1 = NULL, *quat2 = NULL;
 	PyObject *f = NULL;
 	VectorObject *vec = NULL;
-	PointObject *pt = NULL;
 
 	quat1 = (QuaternionObject*)q1;
 	quat2 = (QuaternionObject*)q2;
@@ -465,8 +374,8 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
 			PyInt_Check(quat1->coerced_object)){	// FLOAT/INT * QUAT
 			f = PyNumber_Float(quat1->coerced_object);
 			if(f == NULL) { // parsed item not a number
-				return EXPP_ReturnPyObjError(PyExc_TypeError, 
-					"Quaternion multiplication: arguments not acceptable for this operation\n");
+				PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
+				return NULL;
 			}
 
 			scalar = (float)PyFloat_AS_DOUBLE(f);
@@ -482,8 +391,8 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
 				PyInt_Check(quat2->coerced_object)){	// QUAT * FLOAT/INT
 				f = PyNumber_Float(quat2->coerced_object);
 				if(f == NULL) { // parsed item not a number
-					return EXPP_ReturnPyObjError(PyExc_TypeError, 
-						"Quaternion multiplication: arguments not acceptable for this operation\n");
+					PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
+					return NULL;
 				}
 
 				scalar = (float)PyFloat_AS_DOUBLE(f);
@@ -495,17 +404,10 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
 			}else if(VectorObject_Check(quat2->coerced_object)){  //QUAT * VEC
 				vec = (VectorObject*)quat2->coerced_object;
 				if(vec->size != 3){
-					return EXPP_ReturnPyObjError(PyExc_TypeError, 
-						"Quaternion multiplication: only 3D vector rotations currently supported\n");
+					PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
+					return NULL;
 				}
 				return quat_rotation((PyObject*)quat1, (PyObject*)vec);
-			}else if(PointObject_Check(quat2->coerced_object)){  //QUAT * POINT
-				pt = (PointObject*)quat2->coerced_object;
-				if(pt->size != 3){
-					return EXPP_ReturnPyObjError(PyExc_TypeError, 
-						"Quaternion multiplication: only 3D point rotations currently supported\n");
-				}
-				return quat_rotation((PyObject*)quat1, (PyObject*)pt);
 			}
 		}else{  //QUAT * QUAT (dot product)
 			for(x = 0; x < 4; x++) {
@@ -515,8 +417,8 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
 		}
 	}
 
-	return EXPP_ReturnPyObjError(PyExc_TypeError, 
-		"Quaternion multiplication: arguments not acceptable for this operation\n");
+	PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
+	return NULL;
 }
 //------------------------coerce(obj, obj)-----------------------
 //coercion of unknown types to type QuaternionObject for numeric protocols
@@ -528,17 +430,18 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
  then call vector.multiply(vector, scalar_cast_as_vector)*/
 static int Quaternion_coerce(PyObject ** q1, PyObject ** q2)
 {
-	if(VectorObject_Check(*q2) || PyFloat_Check(*q2) || PyInt_Check(*q2) ||
-			PointObject_Check(*q2)) {
-		PyObject *coerced = EXPP_incr_ret(*q2);
+	if(VectorObject_Check(*q2) || PyFloat_Check(*q2) || PyInt_Check(*q2)) {
+		PyObject *coerced = (PyObject *)(*q2);
+		Py_INCREF(coerced);
+		
 		*q2 = newQuaternionObject(NULL,Py_NEW);
 		((QuaternionObject*)*q2)->coerced_object = coerced;
 		Py_INCREF (*q1);
 		return 0;
 	}
 
-	return EXPP_ReturnIntError(PyExc_TypeError, 
-		"quaternion.coerce(): unknown operand - can't coerce for numeric protocols");
+	PyErr_SetString(PyExc_TypeError, "quaternion.coerce(): unknown operand - can't coerce for numeric protocols");
+	return -1;
 }
 //-----------------PROTOCOL DECLARATIONS--------------------------
 static PySequenceMethods Quaternion_SeqMethods = {
@@ -576,6 +479,138 @@ static PyNumberMethods Quaternion_NumMethods = {
 	(unaryfunc) 0,								/* __hex__ */
 
 };
+
+
+static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
+{
+	switch( (long)type ) {
+    case 'W':
+		return PyFloat_FromDouble(self->quat[0]);
+    case 'X':
+		return PyFloat_FromDouble(self->quat[1]);
+    case 'Y':
+		return PyFloat_FromDouble(self->quat[2]);
+    case 'Z':
+		return PyFloat_FromDouble(self->quat[3]);
+	}
+	
+	PyErr_SetString(PyExc_SystemError, "corrupt quaternion, cannot get axis");
+	return NULL;
+}
+
+static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
+{
+	float param= (float)PyFloat_AsDouble( value );
+	
+	if (param==-1 && PyErr_Occurred()) {
+		PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
+		return -1;
+	}
+	switch( (long)type ) {
+    case 'W':
+		self->quat[0]= param;
+		break;
+    case 'X':
+		self->quat[1]= param;
+		break;
+    case 'Y':
+		self->quat[2]= param;
+		break;
+    case 'Z':
+		self->quat[3]= param;
+		break;
+	}
+
+	return 0;
+}
+
+static PyObject *Quaternion_getWrapped( QuaternionObject * self, void *type )
+{
+	if (self->wrapped == Py_WRAP)
+		Py_RETURN_TRUE;
+	else
+		Py_RETURN_FALSE;
+}
+
+static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
+{
+	double mag = 0.0;
+	int i;
+	for(i = 0; i < 4; i++) {
+		mag += self->quat[i] * self->quat[i];
+	}
+	return PyFloat_FromDouble(sqrt(mag));
+}
+
+static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
+{
+	double ang = self->quat[0];
+	ang = 2 * (saacos(ang));
+	ang *= (180 / Py_PI);
+	return PyFloat_FromDouble(ang);
+}
+
+static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
+{
+	int i;
+	float vec[3];
+	double mag = self->quat[0] * (Py_PI / 180);
+	mag = 2 * (saacos(mag));
+	mag = sin(mag / 2);
+	for(i = 0; i < 3; i++)
+		vec[i] = (float)(self->quat[i + 1] / mag);
+	
+	Normalize(vec);
+	//If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations
+	if( EXPP_FloatsAreEqual(vec[0], 0.0f, 10) &&
+		EXPP_FloatsAreEqual(vec[1], 0.0f, 10) &&
+		EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
+		vec[0] = 1.0f;
+	}
+	return (PyObject *) newVectorObject(vec, 3, Py_NEW);
+}
+
+
+/*****************************************************************************/
+/* Python attributes get/set structure:                                      */
+/*****************************************************************************/
+static PyGetSetDef Quaternion_getseters[] = {
+	{"w",
+	 (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
+	 "Quaternion W value",
+	 (void *)'W'},
+	{"x",
+	 (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
+	 "Quaternion X axis",
+	 (void *)'X'},
+	{"y",
+	 (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
+	 "Quaternion Y axis",
+	 (void *)'Y'},
+	{"z",
+	 (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
+	 "Quaternion Z axis",
+	 (void *)'Z'},
+	{"magnitude",
+	 (getter)Quaternion_getMagnitude, (setter)NULL,
+	 "Size of the quaternion",
+	 NULL},
+	{"angle",
+	 (getter)Quaternion_getAngle, (setter)NULL,
+	 "angle of the quaternion",
+	 NULL},
+	{"axis",
+	 (getter)Quaternion_getAxisVec, (setter)NULL,
+	 "quaternion axis as a vector",
+	 NULL},
+	{"wrapped",
+	 (getter)Quaternion_getWrapped, (setter)NULL,
+	 "True when this wraps blenders internal data",
+	 NULL},
+	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
+};
+
+
 //------------------PY_OBECT DEFINITION--------------------------
 PyTypeObject quaternion_Type = {
 PyObject_HEAD_INIT(NULL)		//tp_head
@@ -585,8 +620,8 @@ PyObject_HEAD_INIT(NULL)		//tp_head
 	0,								//tp_itemsize
 	(destructor)Quaternion_dealloc,		//tp_dealloc
 	0,								//tp_print
-	(getattrfunc)Quaternion_getattr,	//tp_getattr
-	(setattrfunc) Quaternion_setattr,	//tp_setattr
+	0,								//tp_getattr
+	0,								//tp_setattr
 	0,								//tp_compare
 	(reprfunc) Quaternion_repr,			//tp_repr
 	&Quaternion_NumMethods,				//tp_as_number
@@ -606,9 +641,9 @@ PyObject_HEAD_INIT(NULL)		//tp_head
 	0,								//tp_weaklistoffset
 	0,								//tp_iter
 	0,								//tp_iternext
-	0,								//tp_methods
+	Quaternion_methods,				//tp_methods
 	0,								//tp_members
-	0,								//tp_getset
+	Quaternion_getseters,			//tp_getset
 	0,								//tp_base
 	0,								//tp_dict
 	0,								//tp_descr_get
diff --git a/source/blender/python/api2_2x/vector.c b/source/blender/python/api2_2x/vector.c
index fe28f0fac425274921be669889b7adce6005ace5..f4504a13f72c94493172c48beb04680e2b7bb7f8 100644
--- a/source/blender/python/api2_2x/vector.c
+++ b/source/blender/python/api2_2x/vector.c
@@ -20,7 +20,7 @@
  * All rights reserved.
  *
  * 
- * Contributor(s): Willian P. Germano & Joseph Gilbert, Ken Hughes
+ * Contributor(s): Willian P. Germano, Joseph Gilbert, Ken Hughes, Alex Fraser, Campbell Barton
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -30,8 +30,14 @@
 #include "BLI_blenlib.h"
 #include "BKE_utildefines.h"
 #include "BLI_arithb.h"
-#include "gen_utils.h"
 
+#define MAX_DIMENSIONS 4
+/* Swizzle axes get packed into a single value that is used as a closure. Each
+   axis uses SWIZZLE_BITS_PER_AXIS bits. The first bit (SWIZZLE_VALID_AXIS) is
+   used as a sentinel: if it is unset, the axis is not valid. */
+#define SWIZZLE_BITS_PER_AXIS 3
+#define SWIZZLE_VALID_AXIS 0x4
+#define SWIZZLE_AXIS       0x3
 
 /*-------------------------DOC STRINGS ---------------------------*/
 char Vector_Zero_doc[] = "() - set all values in the vector to 0";
@@ -40,10 +46,10 @@ char Vector_Negate_doc[] = "() - changes vector to it's additive inverse";
 char Vector_Resize2D_doc[] = "() - resize a vector to [x,y]";
 char Vector_Resize3D_doc[] = "() - resize a vector to [x,y,z]";
 char Vector_Resize4D_doc[] = "() - resize a vector to [x,y,z,w]";
-char Vector_toPoint_doc[] = "() - create a new Point Object from this vector";
 char Vector_ToTrackQuat_doc[] = "(track, up) - extract a quaternion from the vector and the track and up axis";
 char Vector_reflect_doc[] = "(mirror) - return a vector reflected on the mirror normal";
 char Vector_copy_doc[] = "() - return a copy of the vector";
+char Vector_swizzle_doc[] = "Swizzle: Get or set axes in specified order";
 /*-----------------------METHOD DEFINITIONS ----------------------*/
 struct PyMethodDef Vector_methods[] = {
 	{"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc},
@@ -52,7 +58,6 @@ struct PyMethodDef Vector_methods[] = {
 	{"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc},
 	{"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize2D_doc},
 	{"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize2D_doc},
-	{"toPoint", (PyCFunction) Vector_toPoint, METH_NOARGS, Vector_toPoint_doc},
 	{"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc},
 	{"reflect", ( PyCFunction ) Vector_reflect, METH_O, Vector_reflect_doc},
 	{"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
@@ -60,24 +65,7 @@ struct PyMethodDef Vector_methods[] = {
 	{NULL, NULL, 0, NULL}
 };
 
-/*-----------------------------METHODS----------------------------
-  --------------------------Vector.toPoint()----------------------
-  create a new point object to represent this vector */
-PyObject *Vector_toPoint(VectorObject * self)
-{
-	float coord[3];
-	int i;
-
-	if(self->size < 2 || self->size > 3) {
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Vector.toPoint(): inappropriate vector size - expects 2d or 3d vector\n");
-	} 
-	for(i = 0; i < self->size; i++){
-		coord[i] = self->vec[i];
-	}
-	
-	return newPointObject(coord, self->size, Py_NEW);
-}
+/*-----------------------------METHODS---------------------------- */
 /*----------------------------Vector.zero() ----------------------
   set the vector data to 0,0,0 */
 PyObject *Vector_Zero(VectorObject * self)
@@ -86,7 +74,8 @@ PyObject *Vector_Zero(VectorObject * self)
 	for(i = 0; i < self->size; i++) {
 		self->vec[i] = 0.0f;
 	}
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 /*----------------------------Vector.normalize() -----------------
   normalize the vector data to a unit vector */
@@ -102,7 +91,8 @@ PyObject *Vector_Normalize(VectorObject * self)
 	for(i = 0; i < self->size; i++) {
 		self->vec[i] /= norm;
 	}
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 
 
@@ -110,50 +100,54 @@ PyObject *Vector_Normalize(VectorObject * self)
   resize the vector to x,y */
 PyObject *Vector_Resize2D(VectorObject * self)
 {
-	if(self->wrapped==Py_WRAP)
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"vector.resize2d(): cannot resize wrapped data - only python vectors\n");
-
+	if(self->wrapped==Py_WRAP) {
+		PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize wrapped data - only python vectors\n");
+		return NULL;
+	}
 	self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2));
-	if(self->vec == NULL)
-		return EXPP_ReturnPyObjError(PyExc_MemoryError,
-			"vector.resize2d(): problem allocating pointer space\n\n");
+	if(self->vec == NULL) {
+		PyErr_SetString(PyExc_MemoryError, "vector.resize2d(): problem allocating pointer space\n\n");
+		return NULL;
+	}
 	
 	self->size = 2;
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 /*----------------------------Vector.resize3D() ------------------
   resize the vector to x,y,z */
 PyObject *Vector_Resize3D(VectorObject * self)
 {
-	if (self->wrapped==Py_WRAP)
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"vector.resize3d(): cannot resize wrapped data - only python vectors\n");
-
+	if (self->wrapped==Py_WRAP) {
+		PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize wrapped data - only python vectors\n");
+		return NULL;
+	}
 	self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3));
-	if(self->vec == NULL)
-		return EXPP_ReturnPyObjError(PyExc_MemoryError,
-			"vector.resize3d(): problem allocating pointer space\n\n");
+	if(self->vec == NULL) {
+		PyErr_SetString(PyExc_MemoryError, "vector.resize3d(): problem allocating pointer space\n\n");
+		return NULL;
+	}
 	
 	if(self->size == 2)
 		self->vec[2] = 0.0f;
 	
 	self->size = 3;
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 /*----------------------------Vector.resize4D() ------------------
   resize the vector to x,y,z,w */
 PyObject *Vector_Resize4D(VectorObject * self)
 {
-	if(self->wrapped==Py_WRAP)
-		return EXPP_ReturnPyObjError(PyExc_TypeError,
-			"vector.resize4d(): cannot resize wrapped data - only python vectors\n");
-
+	if(self->wrapped==Py_WRAP) {
+		PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize wrapped data - only python vectors");
+		return NULL;
+	}
 	self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4));
-	if(self->vec == NULL)
-		return EXPP_ReturnPyObjError(PyExc_MemoryError,
-			"vector.resize4d(): problem allocating pointer space\n\n");
-	
+	if(self->vec == NULL) {
+		PyErr_SetString(PyExc_MemoryError, "vector.resize4d(): problem allocating pointer space\n\n");
+		return NULL;
+	}
 	if(self->size == 2){
 		self->vec[2] = 0.0f;
 		self->vec[3] = 1.0f;
@@ -161,7 +155,8 @@ PyObject *Vector_Resize4D(VectorObject * self)
 		self->vec[3] = 1.0f;
 	}
 	self->size = 4;
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 /*----------------------------Vector.toTrackQuat(track, up) ----------------------
   extract a quaternion from the vector and the track and up axis */
@@ -172,11 +167,12 @@ PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
 	short track = 2, up = 1;
 
 	if( !PyArg_ParseTuple ( args, "|ss", &strack, &sup ) ) {
-		return EXPP_ReturnPyObjError( PyExc_TypeError, 
-			"expected optional two strings\n" );
+		PyErr_SetString( PyExc_TypeError, "expected optional two strings\n" );
+		return NULL;
 	}
 	if (self->size != 3) {
-		return EXPP_ReturnPyObjError( PyExc_TypeError, "only for 3D vectors\n" );
+		PyErr_SetString( PyExc_TypeError, "only for 3D vectors\n" );
+		return NULL;
 	}
 
 	if (strack) {
@@ -196,13 +192,13 @@ PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
 						track = 5;
 						break;
 					default:
-						return EXPP_ReturnPyObjError( PyExc_ValueError,
-										  "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+						PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+						return NULL;
 				}
 			}
 			else {
-				return EXPP_ReturnPyObjError( PyExc_ValueError,
-								  "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+				PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+				return NULL;
 			}
 		}
 		else if (strlen(strack) == 1) {
@@ -221,13 +217,13 @@ PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
 				track = 2;
 				break;
 			default:
-				return EXPP_ReturnPyObjError( PyExc_ValueError,
-								  "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+				PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+				return NULL;
 			}
 		}
 		else {
-			return EXPP_ReturnPyObjError( PyExc_ValueError,
-							  "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+			PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+			return NULL;
 		}
 	}
 
@@ -247,19 +243,19 @@ PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
 				up = 2;
 				break;
 			default:
-				return EXPP_ReturnPyObjError( PyExc_ValueError,
-								  "only X, Y or Z for up axis\n" );
+				PyErr_SetString( PyExc_ValueError, "only X, Y or Z for up axis\n" );
+				return NULL;
 			}
 		}
 		else {
-			return EXPP_ReturnPyObjError( PyExc_ValueError,
-							  "only X, Y or Z for up axis\n" );
+			PyErr_SetString( PyExc_ValueError, "only X, Y or Z for up axis\n" );
+			return NULL;
 		}
 	}
 
 	if (track == up) {
-			return EXPP_ReturnPyObjError( PyExc_ValueError,
-						      "Can't have the same axis for track and up\n" );
+		PyErr_SetString( PyExc_ValueError, "Can't have the same axis for track and up\n" );
+		return NULL;
 	}
 
 	/*
@@ -291,9 +287,10 @@ PyObject *Vector_reflect( VectorObject * self, PyObject * value )
 	int i;
 	float norm = 0.0f;
 	
-	if (!VectorObject_Check(value)) 
-		return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a vector argument" );
-	
+	if (!VectorObject_Check(value)) {
+		PyErr_SetString( PyExc_TypeError, "expected a vector argument" );
+		return NULL;
+	}
 	mirrvec = (VectorObject *)value;
 	
 	mirror[0] = mirrvec->vec[0];
@@ -375,9 +372,10 @@ static int Vector_len(VectorObject * self)
   sequence accessor (get)*/
 static PyObject *Vector_item(VectorObject * self, int i)
 {
-	if(i < 0 || i >= self->size)
-		return EXPP_ReturnPyObjError(PyExc_IndexError,
-		"vector[index]: out of range\n");
+	if(i < 0 || i >= self->size) {
+		PyErr_SetString(PyExc_IndexError,"vector[index]: out of range\n");
+		return NULL;
+	}
 
 	return PyFloat_FromDouble(self->vec[i]);
 
@@ -388,13 +386,13 @@ static int Vector_ass_item(VectorObject * self, int i, PyObject * ob)
 {
 	
 	if(!(PyNumber_Check(ob))) { /* parsed item not a number */
-		return EXPP_ReturnIntError(PyExc_TypeError, 
-			"vector[index] = x: index argument not a number\n");
+		PyErr_SetString(PyExc_TypeError, "vector[index] = x: index argument not a number\n");
+		return -1;
 	}
 
 	if(i < 0 || i >= self->size){
-		return EXPP_ReturnIntError(PyExc_IndexError,
-			"vector[index] = x: assignment index out of range\n");
+		PyErr_SetString(PyExc_IndexError, "vector[index] = x: assignment index out of range\n");
+		return -1;
 	}
 	self->vec[i] = (float)PyFloat_AsDouble(ob);
 	return 0;
@@ -436,21 +434,21 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end,
 
 	size = PySequence_Length(seq);
 	if(size != (end - begin)){
-		return EXPP_ReturnIntError(PyExc_TypeError,
-			"vector[begin:end] = []: size mismatch in slice assignment\n");
+		PyErr_SetString(PyExc_TypeError, "vector[begin:end] = []: size mismatch in slice assignment\n");
+		return -1;
 	}
 
 	for (i = 0; i < size; i++) {
 		v = PySequence_GetItem(seq, i);
 		if (v == NULL) { /* Failed to read sequence */
-			return EXPP_ReturnIntError(PyExc_RuntimeError, 
-				"vector[begin:end] = []: unable to read sequence\n");
+			PyErr_SetString(PyExc_RuntimeError, "vector[begin:end] = []: unable to read sequence\n");
+			return -1;
 		}
 		
 		if(!PyNumber_Check(v)) { /* parsed item not a number */
 			Py_DECREF(v);
-			return EXPP_ReturnIntError(PyExc_TypeError, 
-				"vector[begin:end] = []: sequence argument not a number\n");
+			PyErr_SetString(PyExc_TypeError, "vector[begin:end] = []: sequence argument not a number\n");
+			return -1;
 		}
 
 		vec[i] = (float)PyFloat_AsDouble(v);
@@ -481,33 +479,18 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2)
 	/* make sure v1 is always the vector */
 	if (vec1 && vec2 ) {
 		/*VECTOR + VECTOR*/
-		if(vec1->size != vec2->size)
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Vector addition: vectors must have the same dimensions for this operation\n");
-		
+		if(vec1->size != vec2->size) {
+			PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n");
+			return NULL;
+		}
 		for(i = 0; i < vec1->size; i++) {
 			vec[i] = vec1->vec[i] +	vec2->vec[i];
 		}
 		return newVectorObject(vec, vec1->size, Py_NEW);
 	}
 	
-	if(PointObject_Check(v2)){  /*VECTOR + POINT*/
-		/*Point translation*/
-		PointObject *pt = (PointObject*)v2;
-		
-		if(pt->size == vec1->size){
-			for(i = 0; i < vec1->size; i++){
-				vec[i] = vec1->vec[i] + pt->coord[i];
-			}
-		}else{
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"Vector addition: arguments are the wrong size....\n");
-		}
-		return newPointObject(vec, vec1->size, Py_NEW);
-	}
-	
-	return EXPP_ReturnPyObjError(PyExc_AttributeError,
-		"Vector addition: arguments not valid for this operation....\n");
+	PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n");
+	return NULL;
 }
 
 /*  ------------------------obj += obj------------------------------
@@ -527,10 +510,10 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
 	/* make sure v1 is always the vector */
 	if (vec1 && vec2 ) {
 		/*VECTOR + VECTOR*/
-		if(vec1->size != vec2->size)
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Vector addition: vectors must have the same dimensions for this operation\n");
-		
+		if(vec1->size != vec2->size) {
+			PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n");
+			return NULL;
+		}
 		for(i = 0; i < vec1->size; i++) {
 			vec1->vec[i] +=	vec2->vec[i];
 		}
@@ -538,24 +521,8 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
 		return v1;
 	}
 	
-	if(PointObject_Check(v2)){  /*VECTOR + POINT*/
-		/*Point translation*/
-		PointObject *pt = (PointObject*)v2;
-		
-		if(pt->size == vec1->size){
-			for(i = 0; i < vec1->size; i++){
-				vec1->vec[i] += pt->coord[i];
-			}
-		}else{
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"Vector addition: arguments are the wrong size....\n");
-		}
-		Py_INCREF( v1 );
-		return v1;
-	}
-	
-	return EXPP_ReturnPyObjError(PyExc_AttributeError,
-		"Vector addition: arguments not valid for this operation....\n");
+	PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n");
+	return NULL;
 }
 
 /*------------------------obj - obj------------------------------
@@ -566,17 +533,17 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2)
 	float vec[4];
 	VectorObject *vec1 = NULL, *vec2 = NULL;
 
-	if (!VectorObject_Check(v1) || !VectorObject_Check(v2))
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Vector subtraction: arguments not valid for this operation....\n");
-	
+	if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
+		PyErr_SetString(PyExc_AttributeError, "Vector subtraction: arguments not valid for this operation....\n");
+		return NULL;
+	}
 	vec1 = (VectorObject*)v1;
 	vec2 = (VectorObject*)v2;
 	
-	if(vec1->size != vec2->size)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-		"Vector subtraction: vectors must have the same dimensions for this operation\n");
-	
+	if(vec1->size != vec2->size) {
+		PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n");
+		return NULL;
+	}
 	for(i = 0; i < vec1->size; i++) {
 		vec[i] = vec1->vec[i] -	vec2->vec[i];
 	}
@@ -591,16 +558,17 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
 	int i, size;
 	VectorObject *vec1 = NULL, *vec2 = NULL;
 
-	if (!VectorObject_Check(v1) || !VectorObject_Check(v2))
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Vector subtraction: arguments not valid for this operation....\n");
-	
+	if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
+		PyErr_SetString(PyExc_AttributeError, "Vector subtraction: arguments not valid for this operation....\n");
+		return NULL;
+	}
 	vec1 = (VectorObject*)v1;
 	vec2 = (VectorObject*)v2;
 	
-	if(vec1->size != vec2->size)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-		"Vector subtraction: vectors must have the same dimensions for this operation\n");
+	if(vec1->size != vec2->size) {
+		PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n");
+		return NULL;
+	}
 
 	size = vec1->size;
 	for(i = 0; i < vec1->size; i++) {
@@ -628,9 +596,10 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
 		int i;
 		double dot = 0.0f;
 		
-		if(vec1->size != vec2->size)
-		return EXPP_ReturnPyObjError(PyExc_AttributeError,
-			"Vector multiplication: vectors must have the same dimensions for this operation\n");
+		if(vec1->size != vec2->size) {
+			PyErr_SetString(PyExc_AttributeError, "Vector multiplication: vectors must have the same dimensions for this operation\n");
+			return NULL;
+		}
 		
 		/*dot product*/
 		for(i = 0; i < vec1->size; i++) {
@@ -664,15 +633,15 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
 			return row_vector_multiplication(vec1, (MatrixObject*)v2);
 	} else if (QuaternionObject_Check(v2)) {
 		QuaternionObject *quat = (QuaternionObject*)v2;
-		if(vec1->size != 3)
-			return EXPP_ReturnPyObjError(PyExc_TypeError, 
-				"Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
-		
+		if(vec1->size != 3) {
+			PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
+			return NULL;
+		}
 		return quat_rotation((PyObject*)vec1, (PyObject*)quat);
 	}
 	
-	return EXPP_ReturnPyObjError(PyExc_TypeError,
-		"Vector multiplication: arguments not acceptable for this operation\n");
+	PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
+	return NULL;
 }
 
 /*------------------------obj *= obj------------------------------
@@ -702,8 +671,8 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
 		
 		if(mat->colSize != size){
 			if(mat->rowSize == 4 && vec->size != 3){
-				return EXPP_ReturnPyObjError(PyExc_AttributeError, 
-					"vector * matrix: matrix column size and the vector size must be the same");
+				PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
+				return NULL;
 			} else {
 				vecCopy[3] = 1.0f;
 			}
@@ -726,8 +695,8 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
 		Py_INCREF( v1 );
 		return v1;
 	}
-	return EXPP_ReturnPyObjError(PyExc_TypeError,
-		"Vector multiplication: arguments not acceptable for this operation\n");
+	PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
+	return NULL;
 }
 
 /*------------------------obj / obj------------------------------
@@ -738,22 +707,22 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2)
 	float vec[4], scalar;
 	VectorObject *vec1 = NULL;
 	
-	if(!VectorObject_Check(v1)) /* not a vector */
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Vector division: Vector must be divided by a float\n");
-	
+	if(!VectorObject_Check(v1)) { /* not a vector */
+		PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
+		return NULL;
+	}
 	vec1 = (VectorObject*)v1; /* vector */
 	
-	if(!PyNumber_Check(v2)) /* parsed item not a number */
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Vector division: Vector must be divided by a float\n");
-
+	if(!PyNumber_Check(v2)) { /* parsed item not a number */
+		PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
+		return NULL;
+	}
 	scalar = (float)PyFloat_AsDouble(v2);
 	
-	if(scalar==0.0) /* not a vector */
-		return EXPP_ReturnPyObjError(PyExc_ZeroDivisionError, 
-			"Vector division: divide by zero error.\n");
-	
+	if(scalar==0.0) { /* not a vector */
+		PyErr_SetString(PyExc_ZeroDivisionError, "Vector division: divide by zero error.\n");
+		return NULL;
+	}
 	size = vec1->size;
 	for(i = 0; i < size; i++) {
 		vec[i] = vec1->vec[i] /	scalar;
@@ -769,22 +738,24 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
 	float scalar;
 	VectorObject *vec1 = NULL;
 	
-	/*if(!VectorObject_Check(v1))
-		return EXPP_ReturnIntError(PyExc_TypeError, 
-			"Vector division: Vector must be divided by a float\n");*/
+	/*if(!VectorObject_Check(v1)) {
+		PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
+		return -1;
+	}*/
 	
 	vec1 = (VectorObject*)v1; /* vector */
 	
-	if(!PyNumber_Check(v2)) /* parsed item not a number */
-		return EXPP_ReturnPyObjError(PyExc_TypeError, 
-			"Vector division: Vector must be divided by a float\n");
+	if(!PyNumber_Check(v2)) { /* parsed item not a number */
+		PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
+		return NULL;
+	}
 
 	scalar = (float)PyFloat_AsDouble(v2);
 	
-	if(scalar==0.0) /* not a vector */
-		return EXPP_ReturnPyObjError(PyExc_ZeroDivisionError, 
-			"Vector division: divide by zero error.\n");
-	
+	if(scalar==0.0) { /* not a vector */
+		PyErr_SetString(PyExc_ZeroDivisionError, "Vector division: divide by zero error.\n");
+		return NULL;
+	}
 	size = vec1->size;
 	for(i = 0; i < size; i++) {
 		vec1->vec[i] /=	scalar;
@@ -854,9 +825,9 @@ PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_t
 
 	if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)){
 		if (comparison_type == Py_NE){
-			return EXPP_incr_ret(Py_True); 
+			Py_RETURN_TRUE;
 		}else{
-			return EXPP_incr_ret(Py_False);
+			Py_RETURN_FALSE;
 		}
 	}
 	vecA = (VectorObject*)objectA;
@@ -864,9 +835,9 @@ PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_t
 
 	if (vecA->size != vecB->size){
 		if (comparison_type == Py_NE){
-			return EXPP_incr_ret(Py_True); 
+			Py_RETURN_TRUE;
 		}else{
-			return EXPP_incr_ret(Py_False);
+			Py_RETURN_FALSE;
 		}
 	}
 
@@ -919,9 +890,9 @@ PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_t
 			break;
 	}
 	if (result == 1){
-		return EXPP_incr_ret(Py_True);
+		Py_RETURN_TRUE;
 	}else{
-		return EXPP_incr_ret(Py_False);
+		Py_RETURN_FALSE;
 	}
 }
 /*-----------------PROTCOL DECLARATIONS--------------------------*/
@@ -1003,37 +974,36 @@ static PyObject *Vector_getAxis( VectorObject * self, void *type )
     case 'Y':
 		return PyFloat_FromDouble(self->vec[1]);
     case 'Z':	/* these are backwards, but that how it works */
-		if(self->size < 3)
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"vector.z: error, cannot get this axis for a 2D vector\n");
-		else
+		if(self->size < 3) {
+			PyErr_SetString(PyExc_AttributeError, "vector.z: error, cannot get this axis for a 2D vector\n");
+			return NULL;
+		}
+		else {
 			return PyFloat_FromDouble(self->vec[2]);
+		}
     case 'W':
-		if(self->size < 4)
-			return EXPP_ReturnPyObjError(PyExc_AttributeError,
-				"vector.w: error, cannot get this axis for a 3D vector\n");
+		if(self->size < 4) {
+			PyErr_SetString(PyExc_AttributeError, "vector.w: error, cannot get this axis for a 3D vector\n");
+			return NULL;
+		}
 	
 		return PyFloat_FromDouble(self->vec[3]);
 	default:
 		{
-			char errstr[1024];
-			sprintf( errstr, "undefined type '%d' in Vector_getAxis",
-					(int)((long)type & 0xff));
-			return EXPP_ReturnPyObjError( PyExc_RuntimeError, errstr );
+			PyErr_SetString( PyExc_RuntimeError, "undefined type in Vector_getAxis" );
+			return NULL;
 		}
 	}
 }
 
 static int Vector_setAxis( VectorObject * self, PyObject * value, void * type )
 {
-	float param;
-	
-	if (!PyNumber_Check(value))
-		return EXPP_ReturnIntError( PyExc_TypeError,
-			"expected a number for the vector axis" );
-	
-	param= (float)PyFloat_AsDouble( value );
+	float param= (float)PyFloat_AsDouble( value );
 	
+	if (param==-1 && PyErr_Occurred()) {
+		PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
+		return -1;
+	}
 	switch( (long)type ) {
     case 'X':	/* these are backwards, but that how it works */
 		self->vec[0]= param;
@@ -1042,25 +1012,19 @@ static int Vector_setAxis( VectorObject * self, PyObject * value, void * type )
 		self->vec[1]= param;
 		break;
     case 'Z':	/* these are backwards, but that how it works */
-		if(self->size < 3)
-			return EXPP_ReturnIntError(PyExc_AttributeError,
-				"vector.z: error, cannot get this axis for a 2D vector\n");
+		if(self->size < 3) {
+			PyErr_SetString(PyExc_AttributeError, "vector.z: error, cannot get this axis for a 2D vector\n");
+			return -1;
+		}
 		self->vec[2]= param;
 		break;
     case 'W':
-		if(self->size < 4)
-			return EXPP_ReturnIntError(PyExc_AttributeError,
-				"vector.w: error, cannot get this axis for a 3D vector\n");
-	
+		if(self->size < 4) {
+			PyErr_SetString(PyExc_AttributeError, "vector.w: error, cannot get this axis for a 3D vector\n");
+			return -1;
+		}
 		self->vec[3]= param;
 		break;
-	default:
-		{
-			char errstr[1024];
-			sprintf( errstr, "undefined type '%d' in Vector_setAxis",
-					(int)((long)type & 0xff));
-			return EXPP_ReturnIntError( PyExc_RuntimeError, errstr );
-		}
 	}
 
 	return 0;
@@ -1083,16 +1047,16 @@ static int Vector_setLength( VectorObject * self, PyObject * value )
 	double dot = 0.0f, param;
 	int i;
 	
-	if (!PyNumber_Check(value))
-		return EXPP_ReturnIntError( PyExc_TypeError,
-			"expected a number for the vector axis" );
-	
+	if (!PyNumber_Check(value)) {
+		PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
+		return -1;
+	}
 	param= PyFloat_AsDouble( value );
 	
-	if (param < 0)
-		return EXPP_ReturnIntError( PyExc_TypeError,
-			"cannot set a vectors length to a negative value" );
-	
+	if (param < 0) {
+		PyErr_SetString( PyExc_TypeError, "cannot set a vectors length to a negative value" );
+		return -1;
+	}
 	if (param==0) {
 		for(i = 0; i < self->size; i++){
 			self->vec[i]= 0;
@@ -1130,6 +1094,130 @@ static PyObject *Vector_getWrapped( VectorObject * self, void *type )
 }
 
 
+/* Get a new Vector according to the provided swizzle. This function has little
+   error checking, as we are in control of the inputs: the closure is set by us
+   in Vector_createSwizzleGetSeter. */
+static PyObject *Vector_getSwizzle(VectorObject * self, void *closure)
+{
+	size_t axisA;
+	size_t axisB;
+	float vec[MAX_DIMENSIONS];
+	unsigned int swizzleClosure;
+	
+	/* Unpack the axes from the closure into an array. */
+	axisA = 0;
+	swizzleClosure = (unsigned int) closure;
+	while (swizzleClosure & SWIZZLE_VALID_AXIS)
+	{
+		axisB = swizzleClosure & SWIZZLE_AXIS;
+		vec[axisA] = self->vec[axisB];
+		swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
+		axisA++;
+	}
+	
+	return newVectorObject(vec, axisA, Py_NEW);
+}
+
+/* Set the items of this vector using a swizzle.
+   - If value is a vector or list this operates like an array copy, except that
+     the destination is effectively re-ordered as defined by the swizzle. At
+     most min(len(source), len(dest)) values will be copied.
+   - If the value is scalar, it is copied to all axes listed in the swizzle.
+   - If an axis appears more than once in the swizzle, the final occurrance is
+     the one that determines its value.
+
+   Returns 0 on success and -1 on failure. On failure, the vector will be
+   unchanged. */
+static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closure)
+{
+	VectorObject *vecVal;
+	PyObject *item;
+	size_t listLen;
+	float scalarVal;
+
+	size_t axisB;
+	size_t axisA;
+	unsigned int swizzleClosure;
+	
+	float vecTemp[MAX_DIMENSIONS];
+	
+	/* Check that the closure can be used with this vector: even 2D vectors have
+	   swizzles defined for axes z and w, but they would be invalid. */
+	swizzleClosure = (unsigned int) closure;
+	while (swizzleClosure & SWIZZLE_VALID_AXIS)
+	{
+		axisA = swizzleClosure & SWIZZLE_AXIS;
+		if (axisA >= self->size)
+		{
+			PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis.\n");
+			return -1;
+		}
+		swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
+	}
+	
+	if (VectorObject_Check(value))
+	{
+		/* Copy vector contents onto swizzled axes. */
+		vecVal = (VectorObject*) value;
+		axisB = 0;
+		swizzleClosure = (unsigned int) closure;
+		while (swizzleClosure & SWIZZLE_VALID_AXIS && axisB < vecVal->size)
+		{
+			axisA = swizzleClosure & SWIZZLE_AXIS;
+			vecTemp[axisA] = vecVal->vec[axisB];
+			
+			swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
+			axisB++;
+		}
+		memcpy(self->vec, vecTemp, axisB * sizeof(float));
+		return 0;
+	}
+	else if (PyList_Check(value))
+	{
+		/* Copy list contents onto swizzled axes. */
+		listLen = PyList_Size(value);
+		swizzleClosure = (unsigned int) closure;
+		axisB = 0;
+		while (swizzleClosure & SWIZZLE_VALID_AXIS && axisB < listLen)
+		{
+			item = PyList_GetItem(value, axisB);
+			if (!PyNumber_Check(item))
+			{
+				PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis.\n");
+				return -1;
+			}
+			scalarVal = (float)PyFloat_AsDouble(item);
+			
+			axisA = swizzleClosure & SWIZZLE_AXIS;
+			vecTemp[axisA] = scalarVal;
+			
+			swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
+			axisB++;
+		}
+		memcpy(self->vec, vecTemp, axisB * sizeof(float));
+		return 0;
+	}
+	else if (PyNumber_Check(value))
+	{
+		/* Assign the same value to each axis. */
+		scalarVal = (float)PyFloat_AsDouble(value);
+		swizzleClosure = (unsigned int) closure;
+		while (swizzleClosure & SWIZZLE_VALID_AXIS)
+		{
+			axisA = swizzleClosure & SWIZZLE_AXIS;
+			self->vec[axisA] = scalarVal;
+			
+			swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
+		}
+		return 0;
+	}
+	else
+	{
+		PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." );
+		return -1;
+	}
+}
+
 /*****************************************************************************/
 /* Python attributes get/set structure:                                      */
 /*****************************************************************************/
@@ -1160,11 +1248,391 @@ static PyGetSetDef Vector_getseters[] = {
 	 NULL},
 	{"wrapped",
 	 (getter)Vector_getWrapped, (setter)NULL,
-	 "Vector Length",
+	 "True when this wraps blenders internal data",
 	 NULL},
+	
+	/* autogenerated swizzle attrs, see python script below */
+	{"xx",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 36 */
+	{"xxx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 292 */
+	{"xxxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2340 */
+	{"xxxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2852 */
+	{"xxxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3364 */
+	{"xxxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3876 */
+	{"xxy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 356 */
+	{"xxyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2404 */
+	{"xxyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2916 */
+	{"xxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3428 */
+	{"xxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3940 */
+	{"xxz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 420 */
+	{"xxzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2468 */
+	{"xxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2980 */
+	{"xxzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3492 */
+	{"xxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4004 */
+	{"xxw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 484 */
+	{"xxwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2532 */
+	{"xxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3044 */
+	{"xxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3556 */
+	{"xxww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4068 */
+	{"xy",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 44 */
+	{"xyx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 300 */
+	{"xyxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2348 */
+	{"xyxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2860 */
+	{"xyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3372 */
+	{"xyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3884 */
+	{"xyy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 364 */
+	{"xyyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2412 */
+	{"xyyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2924 */
+	{"xyyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3436 */
+	{"xyyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3948 */
+	{"xyz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 428 */
+	{"xyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2476 */
+	{"xyzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2988 */
+	{"xyzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3500 */
+	{"xyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4012 */
+	{"xyw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 492 */
+	{"xywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2540 */
+	{"xywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3052 */
+	{"xywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3564 */
+	{"xyww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4076 */
+	{"xz",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 52 */
+	{"xzx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 308 */
+	{"xzxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2356 */
+	{"xzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2868 */
+	{"xzxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3380 */
+	{"xzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3892 */
+	{"xzy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 372 */
+	{"xzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2420 */
+	{"xzyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2932 */
+	{"xzyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3444 */
+	{"xzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3956 */
+	{"xzz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 436 */
+	{"xzzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2484 */
+	{"xzzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2996 */
+	{"xzzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3508 */
+	{"xzzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4020 */
+	{"xzw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 500 */
+	{"xzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2548 */
+	{"xzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3060 */
+	{"xzwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3572 */
+	{"xzww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4084 */
+	{"xw",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 60 */
+	{"xwx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 316 */
+	{"xwxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2364 */
+	{"xwxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2876 */
+	{"xwxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3388 */
+	{"xwxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3900 */
+	{"xwy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 380 */
+	{"xwyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2428 */
+	{"xwyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2940 */
+	{"xwyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3452 */
+	{"xwyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3964 */
+	{"xwz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 444 */
+	{"xwzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2492 */
+	{"xwzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3004 */
+	{"xwzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3516 */
+	{"xwzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4028 */
+	{"xww",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 508 */
+	{"xwwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2556 */
+	{"xwwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3068 */
+	{"xwwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3580 */
+	{"xwww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4092 */
+	{"yx",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 37 */
+	{"yxx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 293 */
+	{"yxxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2341 */
+	{"yxxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2853 */
+	{"yxxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3365 */
+	{"yxxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3877 */
+	{"yxy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 357 */
+	{"yxyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2405 */
+	{"yxyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2917 */
+	{"yxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3429 */
+	{"yxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3941 */
+	{"yxz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 421 */
+	{"yxzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2469 */
+	{"yxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2981 */
+	{"yxzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3493 */
+	{"yxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4005 */
+	{"yxw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 485 */
+	{"yxwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2533 */
+	{"yxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3045 */
+	{"yxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3557 */
+	{"yxww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4069 */
+	{"yy",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 45 */
+	{"yyx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 301 */
+	{"yyxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2349 */
+	{"yyxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2861 */
+	{"yyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3373 */
+	{"yyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3885 */
+	{"yyy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 365 */
+	{"yyyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2413 */
+	{"yyyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2925 */
+	{"yyyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3437 */
+	{"yyyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3949 */
+	{"yyz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 429 */
+	{"yyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2477 */
+	{"yyzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2989 */
+	{"yyzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3501 */
+	{"yyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4013 */
+	{"yyw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 493 */
+	{"yywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2541 */
+	{"yywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3053 */
+	{"yywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3565 */
+	{"yyww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4077 */
+	{"yz",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 53 */
+	{"yzx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 309 */
+	{"yzxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2357 */
+	{"yzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2869 */
+	{"yzxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3381 */
+	{"yzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3893 */
+	{"yzy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 373 */
+	{"yzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2421 */
+	{"yzyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2933 */
+	{"yzyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3445 */
+	{"yzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3957 */
+	{"yzz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 437 */
+	{"yzzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2485 */
+	{"yzzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2997 */
+	{"yzzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3509 */
+	{"yzzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4021 */
+	{"yzw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 501 */
+	{"yzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2549 */
+	{"yzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3061 */
+	{"yzwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3573 */
+	{"yzww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4085 */
+	{"yw",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 61 */
+	{"ywx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 317 */
+	{"ywxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2365 */
+	{"ywxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2877 */
+	{"ywxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3389 */
+	{"ywxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3901 */
+	{"ywy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 381 */
+	{"ywyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2429 */
+	{"ywyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2941 */
+	{"ywyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3453 */
+	{"ywyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3965 */
+	{"ywz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 445 */
+	{"ywzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2493 */
+	{"ywzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3005 */
+	{"ywzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3517 */
+	{"ywzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4029 */
+	{"yww",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 509 */
+	{"ywwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2557 */
+	{"ywwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3069 */
+	{"ywwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3581 */
+	{"ywww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4093 */
+	{"zx",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 38 */
+	{"zxx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 294 */
+	{"zxxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2342 */
+	{"zxxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2854 */
+	{"zxxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3366 */
+	{"zxxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3878 */
+	{"zxy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 358 */
+	{"zxyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2406 */
+	{"zxyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2918 */
+	{"zxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3430 */
+	{"zxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3942 */
+	{"zxz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 422 */
+	{"zxzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2470 */
+	{"zxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2982 */
+	{"zxzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3494 */
+	{"zxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4006 */
+	{"zxw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 486 */
+	{"zxwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2534 */
+	{"zxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3046 */
+	{"zxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3558 */
+	{"zxww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4070 */
+	{"zy",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 46 */
+	{"zyx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 302 */
+	{"zyxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2350 */
+	{"zyxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2862 */
+	{"zyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3374 */
+	{"zyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3886 */
+	{"zyy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 366 */
+	{"zyyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2414 */
+	{"zyyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2926 */
+	{"zyyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3438 */
+	{"zyyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3950 */
+	{"zyz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 430 */
+	{"zyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2478 */
+	{"zyzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2990 */
+	{"zyzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3502 */
+	{"zyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4014 */
+	{"zyw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 494 */
+	{"zywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2542 */
+	{"zywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3054 */
+	{"zywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3566 */
+	{"zyww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4078 */
+	{"zz",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 54 */
+	{"zzx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 310 */
+	{"zzxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2358 */
+	{"zzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2870 */
+	{"zzxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3382 */
+	{"zzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3894 */
+	{"zzy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 374 */
+	{"zzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2422 */
+	{"zzyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2934 */
+	{"zzyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3446 */
+	{"zzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3958 */
+	{"zzz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 438 */
+	{"zzzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2486 */
+	{"zzzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2998 */
+	{"zzzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3510 */
+	{"zzzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4022 */
+	{"zzw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 502 */
+	{"zzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2550 */
+	{"zzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3062 */
+	{"zzwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3574 */
+	{"zzww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4086 */
+	{"zw",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 62 */
+	{"zwx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 318 */
+	{"zwxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2366 */
+	{"zwxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2878 */
+	{"zwxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3390 */
+	{"zwxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3902 */
+	{"zwy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 382 */
+	{"zwyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2430 */
+	{"zwyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2942 */
+	{"zwyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3454 */
+	{"zwyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3966 */
+	{"zwz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 446 */
+	{"zwzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2494 */
+	{"zwzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3006 */
+	{"zwzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3518 */
+	{"zwzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4030 */
+	{"zww",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 510 */
+	{"zwwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2558 */
+	{"zwwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3070 */
+	{"zwwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3582 */
+	{"zwww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4094 */
+	{"wx",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 39 */
+	{"wxx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 295 */
+	{"wxxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2343 */
+	{"wxxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2855 */
+	{"wxxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3367 */
+	{"wxxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3879 */
+	{"wxy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 359 */
+	{"wxyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2407 */
+	{"wxyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2919 */
+	{"wxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3431 */
+	{"wxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3943 */
+	{"wxz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 423 */
+	{"wxzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2471 */
+	{"wxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2983 */
+	{"wxzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3495 */
+	{"wxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4007 */
+	{"wxw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 487 */
+	{"wxwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2535 */
+	{"wxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3047 */
+	{"wxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3559 */
+	{"wxww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4071 */
+	{"wy",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 47 */
+	{"wyx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 303 */
+	{"wyxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2351 */
+	{"wyxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2863 */
+	{"wyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3375 */
+	{"wyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3887 */
+	{"wyy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 367 */
+	{"wyyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2415 */
+	{"wyyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2927 */
+	{"wyyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3439 */
+	{"wyyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3951 */
+	{"wyz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 431 */
+	{"wyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2479 */
+	{"wyzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2991 */
+	{"wyzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3503 */
+	{"wyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4015 */
+	{"wyw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 495 */
+	{"wywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2543 */
+	{"wywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3055 */
+	{"wywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3567 */
+	{"wyww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4079 */
+	{"wz",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 55 */
+	{"wzx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 311 */
+	{"wzxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2359 */
+	{"wzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2871 */
+	{"wzxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3383 */
+	{"wzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3895 */
+	{"wzy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 375 */
+	{"wzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2423 */
+	{"wzyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2935 */
+	{"wzyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3447 */
+	{"wzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3959 */
+	{"wzz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 439 */
+	{"wzzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2487 */
+	{"wzzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2999 */
+	{"wzzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3511 */
+	{"wzzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4023 */
+	{"wzw",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 503 */
+	{"wzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2551 */
+	{"wzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3063 */
+	{"wzwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3575 */
+	{"wzww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4087 */
+	{"ww",   (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 63 */
+	{"wwx",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 319 */
+	{"wwxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2367 */
+	{"wwxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2879 */
+	{"wwxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3391 */
+	{"wwxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3903 */
+	{"wwy",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 383 */
+	{"wwyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2431 */
+	{"wwyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2943 */
+	{"wwyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3455 */
+	{"wwyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3967 */
+	{"wwz",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 447 */
+	{"wwzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2495 */
+	{"wwzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3007 */
+	{"wwzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3519 */
+	{"wwzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4031 */
+	{"www",  (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 511 */
+	{"wwwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 2559 */
+	{"wwwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3071 */
+	{"wwwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 3583 */
+	{"wwww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  )}, /* 4095 */
 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
 };
 
+/* Python script used to make swizzle array */
+/*
+SWIZZLE_BITS_PER_AXIS = 3
+SWIZZLE_VALID_AXIS = 0x4
+
+axis_dict = {}
+axis_pos = {'x':0, 'y':1, 'z':2, 'w':3}
+axises = 'xyzw'
+while len(axises) >= 2:
+	
+	for axis_0 in axises:
+		axis_0_pos = axis_pos[axis_0]
+		for axis_1 in axises:
+			axis_1_pos = axis_pos[axis_1]
+			axis_dict[axis_0+axis_1] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS))' % (axis_0_pos, axis_1_pos)
+			if len(axises)>2:
+				for axis_2 in axises:
+					axis_2_pos = axis_pos[axis_2]
+					axis_dict[axis_0+axis_1+axis_2] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)))' % (axis_0_pos, axis_1_pos, axis_2_pos)
+					if len(axises)>3:
+						for axis_3 in axises:
+							axis_3_pos = axis_pos[axis_3]
+							axis_dict[axis_0+axis_1+axis_2+axis_3] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3)))  ' % (axis_0_pos, axis_1_pos, axis_2_pos, axis_3_pos)
+	
+	axises = axises[:-1]
+
+
+items = axis_dict.items()
+items.sort(key = lambda a: a[0].replace('x', '0').replace('y', '1').replace('z', '2').replace('w', '3'))
+
+unique = set()
+for key, val in items:
+	num = eval(val)
+	print '\t{"%s", %s(getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)%s)}, // %s' % (key, (' '*(4-len(key))), axis_dict[key], num)
+	unique.add(num)
+
+if len(unique) != len(items):
+	print "ERROR"
+
+*/
+
+
 
 
 /* Note
@@ -1233,7 +1701,7 @@ PyTypeObject vector_Type = {
   /*** Attribute descriptor and subclassing stuff ***/
 	Vector_methods,           /* struct PyMethodDef *tp_methods; */
 	NULL,                       /* struct PyMemberDef *tp_members; */
-	Vector_getseters,         /* struct PyGetSetDef *tp_getset; */
+	Vector_getseters,           /* struct PyGetSetDef *tp_getset; */
 	NULL,                       /* struct _typeobject *tp_base; */
 	NULL,                       /* PyObject *tp_dict; */
 	NULL,                       /* descrgetfunc tp_descr_get; */
@@ -1306,8 +1774,8 @@ PyObject *Vector_Negate(VectorObject * self)
 		self->vec[i] = -(self->vec[i]);
 	}
 	/*printf("Vector.negate(): Deprecated: use -vector instead\n");*/
-	return EXPP_incr_ret((PyObject*)self);
+	Py_INCREF(self);
+	return (PyObject*)self;
 }
 /*###################################################################
   ###########################DEPRECATED##############################*/
-
diff --git a/source/blender/python/api2_2x/vector.h b/source/blender/python/api2_2x/vector.h
index 61b50d5f458554a4c0105d0954713731c0a3362f..9ec2eff80476b7c16bf357213e89010a0fdcc01f 100644
--- a/source/blender/python/api2_2x/vector.h
+++ b/source/blender/python/api2_2x/vector.h
@@ -34,7 +34,7 @@
 
 extern PyTypeObject vector_Type;
 
-#define VectorObject_Check(v) ((v)->ob_type == &vector_Type)
+#define VectorObject_Check(v) (((PyObject *)v)->ob_type == &vector_Type)
 
 typedef struct {
 	PyObject_VAR_HEAD 
@@ -50,7 +50,6 @@ PyObject *Vector_Negate( VectorObject * self );
 PyObject *Vector_Resize2D( VectorObject * self );
 PyObject *Vector_Resize3D( VectorObject * self );
 PyObject *Vector_Resize4D( VectorObject * self );
-PyObject *Vector_toPoint( VectorObject * self );
 PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args );
 PyObject *Vector_reflect( VectorObject * self, PyObject * value );
 PyObject *Vector_copy( VectorObject * self );
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 9e474c1961910fd1e98af3d980eefac1f2b9669c..cd141799f645501900dbb67dcac0ebd55a7c5257 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1437,7 +1437,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 	Object *ob= obr->ob;
 	Object *tob=0;
 	Material *ma=0;
-	MTFace *mtface;
 	ParticleSystemModifierData *psmd;
 	ParticleSystem *tpsys=0;
 	ParticleSettings *part, *tpart=0;
@@ -4374,24 +4373,8 @@ void RE_Database_Free(Render *re)
 static int allow_render_object(Object *ob, int nolamps, int onlyselected, Object *actob)
 {
 	/* override not showing object when duplis are used with particles */
-	if(ob->transflag & OB_DUPLIPARTS){
-		int allow= 0;
-
-		if(ob->particlesystem.first) {
-			ParticleSystem *psys;
-			ParticleSettings *part;
-
-			for(psys=ob->particlesystem.first; psys; psys=psys->next){
-				part=psys->part;
-
-				if(part->draw & PART_DRAW_EMITTER)
-					allow= 1;
-			}
-		}
-
-		if(!allow)
-			return 0;
-	}
+	if(ob->transflag & OB_DUPLIPARTS)
+		; /* let particle system(s) handle showing vs. not showing */
 	else if((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES))
 		return 0;
 	
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index 494feb96c187ff1a0d302bea7e7317900409390a..f9301bc0805200b97cf5cb00672e7860a03aed1a 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -1632,7 +1632,7 @@ void sample_occ(Render *re, ShadeInput *shi)
 			sample_occ_surface(shi);
 		}
 		/* try to get result from the cache if possible */
-		else if(!sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) {
+		else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) {
 			/* no luck, let's sample the occlusion */
 			exclude.obi= shi->obi - re->objectinstance;
 			exclude.facenr= shi->vlr->index;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 5c3c954aa8ec1d6ceaa01af4b83e635f36a416ba..96edb4ee73ceca339947a4b2866a7f820661ee0b 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1639,6 +1639,42 @@ static void do_render_3d(Render *re)
 	RE_Database_Free(re);
 }
 
+/* called by blur loop, accumulate RGBA key alpha */
+static void addblur_rect_key(RenderResult *rr, float *rectf, float *rectf1, float blurfac)
+{
+	float mfac= 1.0f - blurfac;
+	int a, b, stride= 4*rr->rectx;
+	int len= stride*sizeof(float);
+	
+	for(a=0; a<rr->recty; a++) {
+		if(blurfac==1.0f) {
+			memcpy(rectf, rectf1, len);
+		}
+		else {
+			float *rf= rectf, *rf1= rectf1;
+			
+			for( b= rr->rectx; b>0; b--, rf+=4, rf1+=4) {
+				if(rf1[3]<0.01f)
+					rf[3]= mfac*rf[3];
+				else if(rf[3]<0.01f) {
+					rf[0]= rf1[0];
+					rf[1]= rf1[1];
+					rf[2]= rf1[2];
+					rf[3]= blurfac*rf1[3];
+				}
+				else {
+					rf[0]= mfac*rf[0] + blurfac*rf1[0];
+					rf[1]= mfac*rf[1] + blurfac*rf1[1];
+					rf[2]= mfac*rf[2] + blurfac*rf1[2];
+					rf[3]= mfac*rf[3] + blurfac*rf1[3];
+				}				
+			}
+		}
+		rectf+= stride;
+		rectf1+= stride;
+	}
+}
+
 /* called by blur loop, accumulate renderlayers */
 static void addblur_rect(RenderResult *rr, float *rectf, float *rectf1, float blurfac, int channels)
 {
@@ -1662,8 +1698,9 @@ static void addblur_rect(RenderResult *rr, float *rectf, float *rectf1, float bl
 	}
 }
 
+
 /* called by blur loop, accumulate renderlayers */
-static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float blurfac)
+static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float blurfac, int key_alpha)
 {
 	RenderLayer *rl, *rl1;
 	RenderPass *rpass, *rpass1;
@@ -1672,8 +1709,12 @@ static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float b
 	for(rl= rr->layers.first; rl && rl1; rl= rl->next, rl1= rl1->next) {
 		
 		/* combined */
-		if(rl->rectf && rl1->rectf)
-			addblur_rect(rr, rl->rectf, rl1->rectf, blurfac, 4);
+		if(rl->rectf && rl1->rectf) {
+			if(key_alpha)
+				addblur_rect_key(rr, rl->rectf, rl1->rectf, blurfac);
+			else
+				addblur_rect(rr, rl->rectf, rl1->rectf, blurfac, 4);
+		}
 		
 		/* passes are allocated in sync */
 		rpass1= rl1->passes.first;
@@ -1703,7 +1744,7 @@ static void do_render_blur_3d(Render *re)
 		
 		blurfac= 1.0f/(float)(re->r.osa-blur);
 		
-		merge_renderresult_blur(rres, re->result, blurfac);
+		merge_renderresult_blur(rres, re->result, blurfac, re->r.alphamode & R_ALPHAKEY);
 		if(re->test_break()) break;
 	}
 	
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 46a7a1c556c596aa1feab2e2e3de3e9cd7d6b7c6..97ac866618199e9cb064c6df7f69396ae0f76f5c 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -262,13 +262,14 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
 
 	shade_input_set_shade_texco(shi);
 	
-	if(is->mode==RE_RAY_SHADOW_TRA) 
+	if(is->mode==RE_RAY_SHADOW_TRA) {
 		if(shi->mat->nodetree && shi->mat->use_nodes) {
 			ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
 			shi->mat= vlr->mat;		/* shi->mat is being set in nodetree */
 		}
 		else
 			shade_color(shi, shr);
+	}
 	else {
 		if(shi->mat->nodetree && shi->mat->use_nodes) {
 			ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
@@ -1273,7 +1274,7 @@ static void addAlphaLight(float *shadfac, float *col, float alpha, float filter)
 	shadfac[3]= (1.0f-alpha)*shadfac[3];
 }
 
-static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
+static void ray_trace_shadow_tra(Isect *is, int thread, int depth, int traflag)
 {
 	/* ray to lamp, find first face that intersects, check alpha properties,
 	   if it has col[3]>0.0f  continue. so exit when alpha is full */
@@ -1291,15 +1292,9 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
 		
 		shi.depth= 1;					/* only used to indicate tracing */
 		shi.mask= 1;
-		
-		/*shi.osatex= 0;
-		shi.thread= shi.sample= 0;
-		shi.lay= 0;
-		shi.passflag= 0;
-		shi.combinedflag= 0;
-		shi.do_preview= 0;
-		shi.light_override= NULL;
-		shi.mat_override= NULL;*/
+		shi.thread= thread;
+		shi.passflag= SCE_PASS_COMBINED;
+		shi.combinedflag= 0xFFFFFF;		 /* ray trace does all options */
 		
 		shade_ray(is, &shi, &shr);
 		if (traflag & RAY_TRA)
@@ -1315,7 +1310,7 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
 			is->oborig= RAY_OBJECT_SET(&R, shi.obi);
 			is->faceorig= (RayFace*)shi.vlr;
 
-			ray_trace_shadow_tra(is, depth-1, traflag | RAY_TRA);
+			ray_trace_shadow_tra(is, thread, depth-1, traflag | RAY_TRA);
 		}
 	}
 }
@@ -1943,7 +1938,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
 			isec->col[0]= isec->col[1]= isec->col[2]=  1.0f;
 			isec->col[3]= 1.0f;
 			
-			ray_trace_shadow_tra(isec, DEPTH_SHADOW_TRA, 0);
+			ray_trace_shadow_tra(isec, shi->thread, DEPTH_SHADOW_TRA, 0);
 			shadfac[0] += isec->col[0];
 			shadfac[1] += isec->col[1];
 			shadfac[2] += isec->col[2];
@@ -2041,7 +2036,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa
 			isec->col[0]= isec->col[1]= isec->col[2]=  1.0f;
 			isec->col[3]= 1.0f;
 			
-			ray_trace_shadow_tra(isec, DEPTH_SHADOW_TRA, 0);
+			ray_trace_shadow_tra(isec, shi->thread, DEPTH_SHADOW_TRA, 0);
 			shadfac[0] += isec->col[0];
 			shadfac[1] += isec->col[1];
 			shadfac[2] += isec->col[2];
@@ -2122,7 +2117,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
 				isec.col[0]= isec.col[1]= isec.col[2]=  1.0f;
 				isec.col[3]= 1.0f;
 
-				ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0);
+				ray_trace_shadow_tra(&isec, shi->thread, DEPTH_SHADOW_TRA, 0);
 				QUATCOPY(shadfac, isec.col);
 			}
 			else if(RE_ray_tree_intersect(R.raytree, &isec)) shadfac[3]= 0.0f;
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index d44b49cc7065a812d603db7928141e2f247235b9..621831fb34111883f64f8423e43c9d9afbfdbedb 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -1032,9 +1032,11 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,   float *vec,   f
 				har->g= (yn*tg+ zn*ma->g);
 				har->b= (yn*tb+ zn*ma->b);
 			}
-			if(mtex->texco & 16) {
+			if(mtex->texco & TEXCO_UV) {
 				har->alfa= tin;
 			}
+			if(mtex->mapto & MAP_ALPHA)
+				har->alfa= tin;
 		}
 	}
 
diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c
index 61e9d9cf4128948900e6c250c0a30c0e116cfa96..d41f68c021a55fbd110409f58df71e534fb816e8 100644
--- a/source/blender/render/intern/source/texture.c
+++ b/source/blender/render/intern/source/texture.c
@@ -2031,6 +2031,10 @@ void do_material_tex(ShadeInput *shi)
 					shi->amb= texture_value_blend(mtex->def_var, shi->amb, texres.tin, varfac, mtex->blendtype, flip);
 					if(shi->amb<0.0) shi->amb= 0.0;
 					else if(shi->amb>1.0) shi->amb= 1.0;
+					
+					shi->ambr= shi->amb*R.wrld.ambr;
+					shi->ambg= shi->amb*R.wrld.ambg;
+					shi->ambb= shi->amb*R.wrld.ambb;
 				}
 			}
 		}
diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript
index 2e5dda6c772a86a9ebf34ea0174390a9346812f0..ff6db036459ff614cd76701b87e45330cc4e15db 100644
--- a/source/blender/src/SConscript
+++ b/source/blender/src/SConscript
@@ -34,39 +34,41 @@ incs += ' ' + env['BF_OPENGL_INC']
 defs = []
 
 if env['WITH_BF_PYTHON']:
-    incs += ' ../python ' + env['BF_PYTHON_INC']
+	incs += ' ../python ' + env['BF_PYTHON_INC']
+	if env['BF_DEBUG']:
+		defs.append('_DEBUG')
 else:
-    defs.append('DISABLE_PYTHON')
+	defs.append('DISABLE_PYTHON')
 
 
 if env['BF_TWEAK_MODE']:
-    defs.append('TWEAK_MODE')
+	defs.append('TWEAK_MODE')
 
 if not env['WITH_BF_YAFRAY']:
-    defs.append('DISABLE_YAFRAY')
+	defs.append('DISABLE_YAFRAY')
 
 if env['WITH_BF_INTERNATIONAL']:
-    incs += ' ../ftfont'
-    defs.append('INTERNATIONAL')
-    defs.append('FTGL_STATIC_LIBRARY')
+	incs += ' ../ftfont'
+	defs.append('INTERNATIONAL')
+	defs.append('FTGL_STATIC_LIBRARY')
 
 if env['WITH_BF_OPENEXR']:
-    defs.append('WITH_OPENEXR')
+	defs.append('WITH_OPENEXR')
 
 if env['WITH_BF_OPENJPEG']:
-    defs.append('WITH_OPENJPEG')
+	defs.append('WITH_OPENJPEG')
 
 if env['WITH_BF_DDS']:
-    defs.append('WITH_DDS')
+	defs.append('WITH_DDS')
 
 if env['WITH_BF_QUICKTIME']:
-    incs += ' ' + env['BF_QUICKTIME_INC']
-    defs.append('WITH_QUICKTIME')
+	incs += ' ' + env['BF_QUICKTIME_INC']
+	defs.append('WITH_QUICKTIME')
 
 if env['WITH_BF_ICONV']:
-    incs += ' ../quicktime'
-    incs += ' ' + env['BF_ICONV_INC']
-    defs.append('WITH_ICONV')
+	incs += ' ../quicktime'
+	incs += ' ' + env['BF_ICONV_INC']
+	defs.append('WITH_ICONV')
 
 if env['WITH_BF_GAMEENGINE']:
 	defs.append('GAMEBLENDER=1')
@@ -74,33 +76,33 @@ if env['WITH_BF_GAMEENGINE']:
 		defs.append('USE_SUMO_SOLID')
 	
 if env['WITH_BF_FFMPEG']:
-    defs.append('WITH_FFMPEG')
-    incs += ' ' + env['BF_FFMPEG_INC']
+	defs.append('WITH_FFMPEG')
+	incs += ' ' + env['BF_FFMPEG_INC']
 
 if env['WITH_BF_OGG']:
-    defs.append('WITH_OGG')
+	defs.append('WITH_OGG')
 
 if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'):
-    incs += ' ' + env['BF_PTHREADS_INC']
+	incs += ' ' + env['BF_PTHREADS_INC']
 
 if env['WITH_BF_VERSE']:
-    defs.append('WITH_VERSE')
-    incs += ' ' + env['BF_VERSE_INCLUDE']
+	defs.append('WITH_VERSE')
+	incs += ' ' + env['BF_VERSE_INCLUDE']
 
 # TODO buildinfo
 if env['BF_BUILDINFO']:
-    defs.append('NAN_BUILDINFO')
+	defs.append('NAN_BUILDINFO')
 
 if env['BF_NO_ELBEEM']:
-    defs.append('DISABLE_ELBEEM')
+	defs.append('DISABLE_ELBEEM')
 
 if env['WITH_BF_SDL']:
-    incs += ' ' + env['BF_SDL_INC']
+	incs += ' ' + env['BF_SDL_INC']
 else:
-    defs.append('DISABLE_SDL')
+	defs.append('DISABLE_SDL')
 
 if env['WITH_BF_BULLET']:
-    defs.append('WITH_BULLET')
+	defs.append('WITH_BULLET')
 
 if env['BF_SPLIT_SRC'] and (env['OURPLATFORM'] == 'win32-mingw'): 	 
 	for i in range(numlibs): 	 
diff --git a/source/blender/src/booleanops.c b/source/blender/src/booleanops.c
index 14766d1f746baa4490f4f800f0c0721693783e7e..c5b97e475a9f79f2542744c35429daaa0cfb826a 100644
--- a/source/blender/src/booleanops.c
+++ b/source/blender/src/booleanops.c
@@ -68,7 +68,7 @@
  */
 
 typedef struct {
-	Mesh *mesh;
+	DerivedMesh *dm;
 	Object *ob;
 	int pos;
 } VertexIt;
@@ -96,13 +96,13 @@ static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator)
 static int VertexIt_Done(CSG_IteratorPtr it)
 {
 	VertexIt * iterator = (VertexIt *)it;
-	return(iterator->pos >= iterator->mesh->totvert);
+	return(iterator->pos >= iterator->dm->getNumVerts(iterator->dm));
 }
 
 static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert)
 {
 	VertexIt * iterator = (VertexIt *)it;
-	MVert *verts = iterator->mesh->mvert;
+	MVert *verts = iterator->dm->getVertArray(iterator->dm);
 
 	float global_pos[3];
 
@@ -130,7 +130,7 @@ static void VertexIt_Reset(CSG_IteratorPtr it)
 	iterator->pos = 0;
 }
 
-static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, Object *ob)
+static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh *dm, Object *ob)
 {
 
 	VertexIt *it;
@@ -142,8 +142,8 @@ static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, Object *ob)
 		return;
 	}
 	// assign blender specific variables
-	it->ob = ob;
-	it->mesh = ob->data;
+	it->dm = dm;
+	it->ob = ob; // needed for obmat transformations 
 	
 	it->pos = 0;
 
@@ -152,7 +152,7 @@ static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, Object *ob)
 	output->Fill = VertexIt_Fill;
 	output->Done = VertexIt_Done;
 	output->Reset = VertexIt_Reset;
-	output->num_elements = it->mesh->totvert;
+	output->num_elements = it->dm->getNumVerts(it->dm);
 	output->it = it;
 }
 
@@ -161,7 +161,7 @@ static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, Object *ob)
  */
 
 typedef struct {
-	Mesh *mesh;
+	DerivedMesh *dm;
 	int pos;
 	int offset;
 } FaceIt;
@@ -180,14 +180,14 @@ static int FaceIt_Done(CSG_IteratorPtr it)
 {
 	// assume CSG_IteratorPtr is of the correct type.
 	FaceIt * iterator = (FaceIt *)it;
-	return(iterator->pos >= iterator->mesh->totface);
+	return(iterator->pos >= iterator->dm->getNumFaces(iterator->dm));
 }
 
 static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face)
 {
 	// assume CSG_IteratorPtr is of the correct type.
 	FaceIt *face_it = (FaceIt *)it;
-	MFace *mfaces = face_it->mesh->mface;
+	MFace *mfaces = face_it->dm->getFaceArray(face_it->dm);
 	MFace *mface = &mfaces[face_it->pos];
 
 	face->vertex_index[0] = mface->v1;
@@ -216,7 +216,7 @@ static void FaceIt_Reset(CSG_IteratorPtr it)
 }	
 
 static void FaceIt_Construct(
-	CSG_FaceIteratorDescriptor *output, Object *ob, int offset)
+	CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset)
 {
 	FaceIt *it;
 	if (output == 0) return;
@@ -227,7 +227,7 @@ static void FaceIt_Construct(
 		return ;
 	}
 	// assign blender specific variables
-	it->mesh = ob->data;
+	it->dm = dm;
 	it->offset = offset;
 	it->pos = 0;
 
@@ -236,7 +236,7 @@ static void FaceIt_Construct(
 	output->Fill = FaceIt_Fill;
 	output->Done = FaceIt_Done;
 	output->Reset = FaceIt_Reset;
-	output->num_elements = it->mesh->totface;
+	output->num_elements = it->dm->getNumFaces(it->dm);
 	output->it = it;
 }
 
@@ -280,7 +280,7 @@ static Object *AddNewBlenderMesh(Base *base)
 }
 
 static void InterpCSGFace(
-	DerivedMesh *dm, Mesh *orig_me, int index, int orig_index, int nr,
+	DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr,
 	float mapmat[][4])
 {
 	float obco[3], *co[4], *orig_co[4], w[4][4];
@@ -288,13 +288,13 @@ static void InterpCSGFace(
 	int j;
 
 	mface = CDDM_get_face(dm, index);
-	orig_mface = orig_me->mface + orig_index;
+	orig_mface = orig_dm->getFaceArray(orig_dm) + orig_index;
 
 	// get the vertex coordinates from the original mesh
-	orig_co[0] = (orig_me->mvert + orig_mface->v1)->co;
-	orig_co[1] = (orig_me->mvert + orig_mface->v2)->co;
-	orig_co[2] = (orig_me->mvert + orig_mface->v3)->co;
-	orig_co[3] = (orig_mface->v4)? (orig_me->mvert + orig_mface->v4)->co: NULL;
+	orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co;
+	orig_co[1] = (orig_dm->getVertArray(orig_dm) + orig_mface->v2)->co;
+	orig_co[2] = (orig_dm->getVertArray(orig_dm) + orig_mface->v3)->co;
+	orig_co[3] = (orig_mface->v4)? (orig_dm->getVertArray(orig_dm) + orig_mface->v4)->co: NULL;
 
 	// get the vertex coordinates from the new derivedmesh
 	co[0] = CDDM_get_vert(dm, mface->v1)->co;
@@ -312,7 +312,7 @@ static void InterpCSGFace(
 		InterpWeightsQ3Dfl(orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco, w[j]);
 	}
 
-	CustomData_interp(&orig_me->fdata, &dm->faceData, &orig_index, NULL, (float*)w, 1, index);
+	CustomData_interp(&orig_dm->faceData, &dm->faceData, &orig_index, NULL, (float*)w, 1, index);
 }
 
 /* Iterate over the CSG Output Descriptors and create a new DerivedMesh
@@ -324,27 +324,28 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
 	float mapmat[][4],
 	Material **mat,
 	int *totmat,
+	DerivedMesh *dm1,
 	Object *ob1,
+	DerivedMesh *dm2,
 	Object *ob2)
 {
-	DerivedMesh *dm;
+	DerivedMesh *result, *orig_dm;
 	GHash *material_hash = NULL;
 	Mesh *me1= (Mesh*)ob1->data;
 	Mesh *me2= (Mesh*)ob2->data;
 	int i;
 
 	// create a new DerivedMesh
-	dm = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
-
-	CustomData_merge(&me1->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
-	                 CD_DEFAULT, face_it->num_elements); 
-	CustomData_merge(&me2->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
-	                 CD_DEFAULT, face_it->num_elements); 
+	result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
+	CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
+	                  CD_DEFAULT, face_it->num_elements); 
+	CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
+	                  CD_DEFAULT, face_it->num_elements); 
 
 	// step through the vertex iterators:
 	for (i = 0; !vertex_it->Done(vertex_it->it); i++) {
 		CSG_IVertex csgvert;
-		MVert *mvert = CDDM_get_vert(dm, i);
+		MVert *mvert = CDDM_get_vert(result, i);
 
 		// retrieve a csg vertex from the boolean module
 		vertex_it->Fill(vertex_it->it, &csgvert);
@@ -375,15 +376,16 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
 		face_it->Step(face_it->it);
 
 		// find the original mesh and data
-		orig_ob = (csgface.orig_face < me1->totface)? ob1: ob2;
+		orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2;
+		orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2;
 		orig_me = (orig_ob == ob1)? me1: me2;
-		orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - me1->totface;
+		orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1);
 
 		// copy all face layers, including mface
-		CustomData_copy_data(&orig_me->fdata, &dm->faceData, orig_index, i, 1);
+		CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1);
 
 		// set mface
-		mface = CDDM_get_face(dm, i);
+		mface = CDDM_get_face(result, i);
 		mface->v1 = csgface.vertex_index[0];
 		mface->v2 = csgface.vertex_index[1];
 		mface->v3 = csgface.vertex_index[2];
@@ -404,29 +406,30 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
 		else
 			mface->mat_nr = 0;
 
-		InterpCSGFace(dm, orig_me, i, orig_index, csgface.vertex_number,
+		InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number,
 		              (orig_me == me2)? mapmat: NULL);
 
-		test_index_face(mface, &dm->faceData, i, csgface.vertex_number);
+		test_index_face(mface, &result->faceData, i, csgface.vertex_number);
 	}
 
 	if (material_hash)
 		BLI_ghash_free(material_hash, NULL, NULL);
 
-	CDDM_calc_edges(dm);
-	CDDM_calc_normals(dm);
+	CDDM_calc_edges(result);
+	CDDM_calc_normals(result);
 
-	return dm;
+	return result;
 }
 	
 static void BuildMeshDescriptors(
+	struct DerivedMesh *dm,
 	struct Object *ob,
 	int face_offset,
 	struct CSG_FaceIteratorDescriptor * face_it,
 	struct CSG_VertexIteratorDescriptor * vertex_it)
 {
-	VertexIt_Construct(vertex_it,ob);
-	FaceIt_Construct(face_it,ob,face_offset);
+	VertexIt_Construct(vertex_it,dm, ob);
+	FaceIt_Construct(face_it,dm,face_offset);
 }
 	
 static void FreeMeshDescriptors(
@@ -438,19 +441,17 @@ static void FreeMeshDescriptors(
 }
 
 DerivedMesh *NewBooleanDerivedMesh_intern(
-	struct Object *ob, struct Object *ob_select,
+	DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
 	int int_op_type, Material **mat, int *totmat)
 {
 
 	float inv_mat[4][4];
 	float map_mat[4][4];
 
-	DerivedMesh *dm = NULL;
-	Mesh *me1 = get_mesh(ob_select);
-	Mesh *me2 = get_mesh(ob);
+	DerivedMesh *result = NULL;
 
-	if (me1 == NULL || me2 == NULL) return 0;
-	if (!me1->totface || !me2->totface) return 0;
+	if (dm == NULL || dm_select == NULL) return 0;
+	if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0;
 
 	// we map the final object back into ob's local coordinate space. For this
 	// we need to compute the inverse transform from global to ob (inv_mat),
@@ -481,8 +482,8 @@ DerivedMesh *NewBooleanDerivedMesh_intern(
 			default : op_type = e_csg_intersection;
 		}
 		
-		BuildMeshDescriptors(ob_select, 0, &fd_1, &vd_1);
-		BuildMeshDescriptors(ob, me1->totface, &fd_2, &vd_2);
+		BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1);
+		BuildMeshDescriptors(dm, ob, dm_select->getNumFaces(dm_select) , &fd_2, &vd_2);
 
 		bool_op = CSG_NewBooleanFunction();
 
@@ -496,8 +497,8 @@ DerivedMesh *NewBooleanDerivedMesh_intern(
 
 			// iterate through results of operation and insert
 			// into new object
-			dm = ConvertCSGDescriptorsToDerivedMesh(
-				&fd_o, &vd_o, inv_mat, map_mat, mat, totmat, ob_select, ob);
+			result = ConvertCSGDescriptorsToDerivedMesh(
+				&fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob);
 
 			// free up the memory
 			CSG_FreeVertexDescriptor(&vd_o);
@@ -512,7 +513,7 @@ DerivedMesh *NewBooleanDerivedMesh_intern(
 		FreeMeshDescriptors(&fd_2, &vd_2);
 	}
 
-	return dm;
+	return result;
 }
 
 int NewBooleanMesh(Base *base, Base *base_select, int int_op_type)
@@ -521,24 +522,30 @@ int NewBooleanMesh(Base *base, Base *base_select, int int_op_type)
 	int a, maxmat, totmat= 0;
 	Object *ob_new, *ob, *ob_select;
 	Material **mat;
+	DerivedMesh *result;
+	DerivedMesh *dm_select;
 	DerivedMesh *dm;
 
 	ob= base->object;
 	ob_select= base_select->object;
 
+	dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
+	dm_select = mesh_create_derived_view(ob_select, 0); // no modifiers in editmode ??
+
 	maxmat= ob->totcol + ob_select->totcol;
 	mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat");
 	
 	/* put some checks in for nice user feedback */
-	if((!(get_mesh(ob)->totface)) || (!(get_mesh(ob_select)->totface)))
+	if (dm == NULL || dm_select == NULL) return 0;
+	if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select))
 	{
 		MEM_freeN(mat);
 		return -1;
 	}
 	
-	dm= NewBooleanDerivedMesh_intern(ob, ob_select, int_op_type, mat, &totmat);
+	result= NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat);
 
-	if (dm == NULL) {
+	if (result == NULL) {
 		MEM_freeN(mat);
 		return 0;
 	}
@@ -547,8 +554,11 @@ int NewBooleanMesh(Base *base, Base *base_select, int int_op_type)
 	ob_new= AddNewBlenderMesh(base_select);
 	me_new= ob_new->data;
 
-	DM_to_mesh(dm, me_new);
+	DM_to_mesh(result, me_new);
+	result->release(result);
+
 	dm->release(dm);
+	dm_select->release(dm_select);
 
 	/* add materials to object */
 	for (a = 0; a < totmat; a++)
@@ -562,9 +572,9 @@ int NewBooleanMesh(Base *base, Base *base_select, int int_op_type)
 	return 1;
 }
 
-DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select,
+DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
                                    int int_op_type)
 {
-	return NewBooleanDerivedMesh_intern(ob, ob_select, int_op_type, NULL, NULL);
+	return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL);
 }
 
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 80495b9ff80df34f6a53e5ba6aa66bdd27e485e3..1ecc63fe93d0fdd1bb37e3cab79b8a997c86bc31 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -1031,7 +1031,7 @@ static uiBlock *modifiers_add_menu(void *ob_v)
 		/* Only allow adding through appropriate other interfaces */
 		if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
 		
-		if(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim)) continue;
+		if(ELEM4(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Surface, eModifierType_Fluidsim)) continue;
 
 		if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
 		   (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@@ -1735,6 +1735,7 @@ static int modifier_is_fluid_particles(ModifierData *md) {
 	}
 	return 0;
 }
+
 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
 {
 	ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1771,7 +1772,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 		uiDefBut(block, TEX, B_MODIFIER_REDRAW, "", x+10, y-1, buttonWidth-60, 19, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
 
 		/* Softbody not allowed in this situation, enforce! */
-		if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) {
+		if (((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
 			uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
 			but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
 			if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
@@ -1813,7 +1814,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 		
 		// deletion over the deflection panel
 		// fluid particle modifier can't be deleted here
-		if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
+		if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && md->type!=eModifierType_Surface && !modifier_is_fluid_particles(md))
 		{
 			but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
 			uiButSetFunc(but, modifiers_del, ob, md);
@@ -1884,6 +1885,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 			height = 31;
 		} else if (md->type==eModifierType_Collision) {
 			height = 31;
+		} else if (md->type==eModifierType_Surface) {
+			height = 31;
 		} else if (md->type==eModifierType_Fluidsim) {
 			height = 31;
 		} else if (md->type==eModifierType_Boolean) {
@@ -1901,12 +1904,10 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 			height = 94;
 		} else if (md->type==eModifierType_Shrinkwrap) {
 			ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
-			height = 86 + 3;
+			height = 105 + 3;
+
 			if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
-			{
 				height += 19*5;
-				if(smd->projAxis == 0) height += 19;
-			}
 			else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE)
 				height += 19;
 		} else if (md->type == eModifierType_Mask) {
@@ -1924,7 +1925,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 
 		y -= 18;
 
-		if (!isVirtual && (md->type!=eModifierType_Collision)) {
+		if (!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) {
 			uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */
 
 			uiBlockBeginAlign(block);
@@ -2369,6 +2370,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 
 		} else if (md->type==eModifierType_Collision) {
 			uiDefBut(block, LABEL, 1, "See Collision panel.",	lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+		} else if (md->type==eModifierType_Surface) {
+			uiDefBut(block, LABEL, 1, "See Fields panel.",	lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
 		} else if (md->type==eModifierType_Fluidsim) {
 			uiDefBut(block, LABEL, 1, "See Fluidsim panel.",	lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
 		} else if (md->type==eModifierType_Boolean) {
@@ -2592,16 +2595,14 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 			cy -= 3;
 			uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, lx,(cy-=19),buttonWidth,19, &smd->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
 
+			uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:",		lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals");
+
 			if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
 
 
 				/* UI for projection axis */
 				uiBlockBeginAlign(block);
 				uiDefButC(block, ROW, B_MODIFIER_RECALC, "Normal"    , lx,(cy-=19),buttonWidth,19, &smd->projAxis, 18.0, MOD_SHRINKWRAP_PROJECT_OVER_NORMAL, 0, 0, "Projection over X axis");
-				if(smd->projAxis == 0)
-				{
-					uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:",		lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals");
-				}
 
 				uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS, B_MODIFIER_RECALC, "X",	lx+buttonWidth/3*0,(cy-=19),buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over X axis");
 				uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS, B_MODIFIER_RECALC, "Y",	lx+buttonWidth/3*1,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Y axis");
@@ -3727,6 +3728,9 @@ static void editing_panel_camera_type(Object *ob, Camera *cam)
 				  10, 160, 150, 20, &cam->ortho_scale, 0.01, 1000.0, 50, 0, "Specify the ortho scaling of the used camera");
 	} else {
 		if(cam->flag & CAM_ANGLETOGGLE) {
+			/* ensure animated lens value is always copied */
+			do_lenstoangleconversion_cb(&cam->lens, &cam->angle);
+			
 			but= uiDefButF(block, NUM,REDRAWVIEW3D, "Lens:",
 					  10, 160, 130, 20, &cam->angle, 7.323871, 172.847331, 100, 0, "Specify the lens of the camera in degrees");		
 			uiButSetFunc(but,do_angletolensconversion_cb, &cam->lens, &cam->angle);
@@ -6615,7 +6619,10 @@ static void editing_panel_mesh_uvautocalculation(void)
 	uiDefButBitS(block, TOGN, UVCALC_NO_ASPECT_CORRECT, B_NOP, "Image Aspect",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0,  "Scale the UV Unwrapping to correct for the current images aspect ratio");
 
 	row-= butHB+butS;	
-		uiDefButBitS(block, TOG, UVCALC_TRANSFORM_CORRECT, B_NOP, "Transform Correction",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0,  "Correct for UV distortion while transforming, (only works with edge slide now)");
+	uiDefButBitS(block, TOG, UVCALC_TRANSFORM_CORRECT, B_NOP, "Transform Correction",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0,  "Correct for UV distortion while transforming, (only works with edge slide now)");
+	
+	row-= butHB+butS;	
+	uiDefButF(block, NUM,B_NOP ,"Pack Margin:",100,row,200,butH, &G.scene->toolsettings->uvcalc_margin, 0.0, 1.0, 10, 2, "Add a margin between UV islands when unwrapping or with 'Pack Islands' in the UV window");
 
 	row= 180;
 	
@@ -6961,3 +6968,4 @@ void editing_panels()
 	}
 	uiClearButLock();
 }
+
diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c
index cf6d29da0d3b9c736ac87c4bb00771efbedac318..dccbc73787dcc0aca8c14f6e953788a91b27bd3c 100644
--- a/source/blender/src/buttons_logic.c
+++ b/source/blender/src/buttons_logic.c
@@ -1026,6 +1026,19 @@ static void set_col_sensor(int type, int medium)
 	BIF_ThemeColorShade(col, medium?30:0);
 }
 
+
+static void verify_logicbutton_func(void *data1, void *data2)
+{
+	bSensor *sens= (bSensor*)data1;
+	
+	if(sens->level && sens->tap) {
+		if(data2 == &(sens->level))	sens->tap= 0;
+		else							sens->level= 0;
+		allqueue(REDRAWBUTSLOGIC, 0);
+	}
+}
+
+
 /**
  * Draws a toggle for pulse mode, a frequency field and a toggle to invert
  * the value of this sensor. Operates on the shared data block of sensors.
@@ -1036,30 +1049,39 @@ static void draw_default_sensor_header(bSensor *sens,
 								short y,
 								short w) 
 {
+	uiBut *but;
+	
 	/* Pulsing and frequency */
 	uiDefIconButBitS(block, TOG, SENS_PULSE_REPEAT, 1, ICON_DOTSUP,
-			 (short)(x + 10 + 0. * (w-20)), (short)(y - 21), (short)(0.15 * (w-20)), 19,
+			 (short)(x + 10 + 0. * (w-20)), (short)(y - 21), (short)(0.1 * (w-20)), 19,
 			 &sens->pulse, 0.0, 0.0, 0, 0,
 			 "Activate TRUE level triggering (pulse mode)");
 
 	uiDefIconButBitS(block, TOG, SENS_NEG_PULSE_MODE, 1, ICON_DOTSDOWN,
-			 (short)(x + 10 + 0.15 * (w-20)), (short)(y - 21), (short)(0.15 * (w-20)), 19,
+			 (short)(x + 10 + 0.1 * (w-20)), (short)(y - 21), (short)(0.1 * (w-20)), 19,
 			 &sens->pulse, 0.0, 0.0, 0, 0,
 			 "Activate FALSE level triggering (pulse mode)");
 	uiDefButS(block, NUM, 1, "f:",
-			 (short)(x + 10 + 0.3 * (w-20)), (short)(y - 21), (short)(0.275 * (w-20)), 19,
+			 (short)(x + 10 + 0.2 * (w-20)), (short)(y - 21), (short)(0.275 * (w-20)), 19,
 			 &sens->freq, 0.0, 10000.0, 0, 0,
 			 "Delay between repeated pulses (in logic tics, 0 = no delay)");
 	
 	/* value or shift? */
+	but= uiDefButS(block, TOG, 1, "Level",
+			 (short)(x + 10 + 0.5 * (w-20)), (short)(y - 21), (short)(0.20 * (w-20)), 19,
+			 &sens->level, 0.0, 0.0, 0, 0,
+			 "Level detector, trigger controllers of new states (only applicable upon logic state transition)");
+	uiButSetFunc(but, verify_logicbutton_func, sens, &(sens->level));
+	but= uiDefButS(block, TOG, 1, "Tap",
+			 (short)(x + 10 + 0.702 * (w-20)), (short)(y - 21), (short)(0.12 * (w-20)), 19,
+			 &sens->tap, 0.0, 0.0, 0, 0,
+			 "Trigger controllers only for an instant, even while the sensor remains true");
+	uiButSetFunc(but, verify_logicbutton_func, sens, &(sens->tap));
+	
 	uiDefButS(block, TOG, 1, "Inv",
 			 (short)(x + 10 + 0.85 * (w-20)), (short)(y - 21), (short)(0.15 * (w-20)), 19,
 			 &sens->invert, 0.0, 0.0, 0, 0,
 			 "Invert the level (output) of this sensor");
-	uiDefButS(block, TOG, 1, "Level",
-			 (short)(x + 10 + 0.65 * (w-20)), (short)(y - 21), (short)(0.20 * (w-20)), 19,
-			 &sens->level, 0.0, 0.0, 0, 0,
-			 "Level detector, trigger controllers of new states (only applicable upon logic state transition)");
 }
 
 static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname)
@@ -1457,32 +1479,33 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short
 			&joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0,
 			"Specify which joystick to use");			
 
-			str= "Type %t|Button %x0|Axis %x1|Hat%x2"; 
+			str= "Type %t|Button %x0|Axis %x1|Single Axis %x3|Hat%x2"; 
 			uiDefButC(block, MENU, B_REDR, str, xco+87, yco-44, 0.26 * (width-20), 19,
 				&joy->type, 0, 31, 0, 0,
 				"The type of event this joystick sensor is triggered on.");
 			
-			if (joy->flag & SENS_JOY_ANY_EVENT) {
-				switch (joy->type) {
-				case SENS_JOY_AXIS:	
-					str = "All Axis Events";
-					break;
-				case SENS_JOY_BUTTON:	
-					str = "All Button Events";
-					break;
-				default:
-					str = "All Hat Events";
-					break;
+			if (joy->type != SENS_JOY_AXIS_SINGLE) {
+				if (joy->flag & SENS_JOY_ANY_EVENT) {
+					switch (joy->type) {
+					case SENS_JOY_AXIS:	
+						str = "All Axis Events";
+						break;
+					case SENS_JOY_BUTTON:	
+						str = "All Button Events";
+						break;
+					default:
+						str = "All Hat Events";
+						break;
+					}
+				} else {
+					str = "All";
 				}
-			} else {
-				str = "All";
+				
+				uiDefButBitS(block, TOG, SENS_JOY_ANY_EVENT, B_REDR, str,
+					xco+10 + 0.475 * (width-20), yco-68, ((joy->flag & SENS_JOY_ANY_EVENT) ? 0.525 : 0.12) * (width-20), 19,
+					&joy->flag, 0, 0, 0, 0,
+					"Triggered by all events on this joysticks current type (axis/button/hat)");
 			}
-			
-			uiDefButBitS(block, TOG, SENS_JOY_ANY_EVENT, B_REDR, str,
-				xco+10 + 0.475 * (width-20), yco-68, ((joy->flag & SENS_JOY_ANY_EVENT) ? 0.525 : 0.12) * (width-20), 19,
-				&joy->flag, 0, 0, 0, 0,
-				"Triggered by all events on this joysticks current type (axis/button/hat)");
-			
 			if(joy->type == SENS_JOY_BUTTON)
 			{
 				if ((joy->flag & SENS_JOY_ANY_EVENT)==0) {
@@ -1493,8 +1516,8 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short
 			}
 			else if(joy->type == SENS_JOY_AXIS)
 			{
-				uiDefButI(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19,
-				&joy->axis, 1, 2.0, 100, 0,
+				uiDefButS(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19,
+				&joy->axis, 1, 8.0, 100, 0,
 				"Specify which axis pair to use, 1 is useually the main direction input.");
 
 				uiDefButI(block, NUM, 1, "Threshold:", xco+10 + 0.6 * (width-20),yco-44, 0.4 * (width-20), 19,
@@ -1508,7 +1531,7 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short
 					"The direction of the axis, use 'All Events' to recieve events on any direction");
 				}
 			}
-			else
+			else if (joy->type == SENS_JOY_HAT)
 			{
 				uiDefButI(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19,
 				&joy->hat, 1, 2.0, 100, 0,
@@ -1520,6 +1543,15 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short
 					"Specify hat direction");
 				}
 			}
+			else { /* (joy->type == SENS_JOY_AXIS_SINGLE)*/
+				uiDefButS(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19,
+				&joy->axis_single, 1, 16.0, 100, 0,
+				"Specify a single axis (verticle/horizontal/other) to detect");
+				
+				uiDefButI(block, NUM, 1, "Threshold:", xco+10 + 0.6 * (width-20),yco-44, 0.4 * (width-20), 19,
+				&joy->precision, 0, 32768.0, 100, 0,
+				"Specify the precision of the axis");
+			}
 			yco-= ysize;
 			break;
 		}
@@ -1568,7 +1600,16 @@ static short draw_controllerbuttons(bController *cont, uiBlock *block, short xco
 		glRects(xco, yco-ysize, xco+width, yco);
 		uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
 
-		uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+45,yco-24,width-90, 19, &pc->text, "");
+	
+		uiBlockBeginAlign(block);
+		uiDefButI(block, MENU, B_REDR, "Execution Method%t|Script%x0|Module%x1", xco+24,yco-24, 66, 19, &pc->mode, 0, 0, 0, 0, "Python script type (textblock or module - faster)");
+		if(pc->mode==0)
+			uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "", xco+90,yco-24,width-90, 19, &pc->text, "Blender textblock to run as a script");
+		else {
+			uiDefBut(block, TEX, 1, "", xco+90,yco-24,(width-90)-25, 19, pc->module, 0, 63, 0, 0, "Module name and function to run eg \"someModule.main\", internal texts external python files can be used");
+			uiDefButBitI(block, TOG, CONT_PY_DEBUG, B_REDR, "D", (xco+width)-25, yco-24, 19, 19, &pc->flag, 0, 0, 0, 0, "Continuously reload the module from disk for editing external modules without restrting");
+		}
+		uiBlockEndAlign(block);
 		
 		yco-= ysize;
 		break;
@@ -1960,12 +2001,17 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
 			
 			pa= act->data;
 			
-			str= "Type   %t|Assign   %x0|Add %x1|Copy %x2";
+			str= "Type%t|Assign%x0|Add %x1|Copy %x2|Toggle (bool/int/float/timer)%x3";
 			uiDefButI(block, MENU, B_REDR, str,		xco+30,yco-24,width-60, 19, &pa->type, 0, 31, 0, 0, "Type");
 			
 			uiDefBut(block, TEX, 1, "Prop: ",		xco+30,yco-44,width-60, 19, pa->name, 0, 31, 0, 0, "Property name");
 			
-			if(pa->type==ACT_PROP_COPY) {
+			
+			if(pa->type==ACT_PROP_TOGGLE) {
+				/* no ui */
+				ysize -= 22;
+			}
+			else if(pa->type==ACT_PROP_COPY) {
 				uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:",	xco+10, yco-64, (width-20)/2, 19, &(pa->ob), "Copy from this Object");
 				uiDefBut(block, TEX, 1, "Prop: ",		xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, 31, 0, 0, "Copy this property");
 			}
@@ -2374,7 +2420,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
 				ysize = 48;
 				glRects(xco, yco-ysize, xco+width, yco); 
 				uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); 
-		   		uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file");
+		   		uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this blend file, use the \"//\" prefix for a path relative to the current blend file");
 //				uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation");
 			}
 /*			else if (gma->type == ACT_GAME_START)
@@ -2440,18 +2486,18 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
 			  xco + 10, yco - 20, (width - 20)/3, 19, &visAct->flag,
 			  0.0, 0.0, 0, 0,
 			  "Set the objects visible. Initialized from the objects render restriction toggle (access in the outliner)");
-		uiDefButBitI(block, TOG, ACT_VISIBILITY_INVISIBLE, B_REDR,
-			  "Invisible",
+		uiDefButBitI(block, TOG, ACT_VISIBILITY_OCCLUSION, B_REDR,
+			  "Occlusion",
 			  xco + 10 + ((width - 20)/3), yco - 20, (width - 20)/3, 19, &visAct->flag,
 			  0.0, 0.0, 0, 0,
-			  "Set the object invisible. Initialized from the objects render restriction toggle (access in the outliner)");
+			  "Set the object to occlude objects behind it. Initialized from the object type in physics button");
 		uiBlockEndAlign(block);
 		
 		uiDefButBitI(block, TOG, ACT_VISIBILITY_RECURSIVE, B_NOP,
 			  "Children",
 			  xco + 10 + (((width - 20)/3)*2)+10, yco - 20, ((width - 20)/3)-10, 19, &visAct->flag,
 			  0.0, 0.0, 0, 0,
-			  "Sets all the children of this object to the same visibility recursively");
+			  "Sets all the children of this object to the same visibility/occlusion recursively");
 
 		yco-= ysize;
 
@@ -3018,25 +3064,29 @@ static void check_body_type(void *arg1_but, void *arg2_object)
 	Object *ob = arg2_object;
 
 	switch (ob->body_type) {
+	case OB_BODY_TYPE_OCCLUDER:
+		ob->gameflag |= OB_OCCLUDER;
+		ob->gameflag &= ~(OB_COLLISION|OB_DYNAMIC);
+		break;
 	case OB_BODY_TYPE_NO_COLLISION:
-		ob->gameflag &= ~OB_COLLISION;
+		ob->gameflag &= ~(OB_COLLISION|OB_OCCLUDER|OB_DYNAMIC);
 		break;
 	case OB_BODY_TYPE_STATIC:
 		ob->gameflag |= OB_COLLISION;
-		ob->gameflag &= ~(OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY);
+		ob->gameflag &= ~(OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY|OB_OCCLUDER);
 		break;
 	case OB_BODY_TYPE_DYNAMIC:
 		ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_ACTOR;
-		ob->gameflag &= ~(OB_RIGID_BODY|OB_SOFT_BODY);
+		ob->gameflag &= ~(OB_RIGID_BODY|OB_SOFT_BODY|OB_OCCLUDER);
 		break;
 	case OB_BODY_TYPE_RIGID:
 		ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_RIGID_BODY|OB_ACTOR;
-		ob->gameflag &= ~(OB_SOFT_BODY);
+		ob->gameflag &= ~(OB_SOFT_BODY|OB_OCCLUDER);
 		break;
 	default:
 	case OB_BODY_TYPE_SOFT:
 		ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_SOFT_BODY|OB_ACTOR;
-		ob->gameflag &= ~(OB_RIGID_BODY);
+		ob->gameflag &= ~(OB_RIGID_BODY|OB_OCCLUDER);
 		
 		/* assume triangle mesh, if no bounds chosen for soft body */
 		if ((ob->gameflag & OB_BOUNDS) && (ob->boundtype<OB_BOUND_POLYH))
@@ -3054,19 +3104,19 @@ static uiBlock *advanced_bullet_menu(void *arg_ob)
 {
 	uiBlock *block;
 	Object *ob = arg_ob;
-	short yco = 20, xco = 0;
+	short yco, xco = 0;
 
 	block= uiNewBlock(&curarea->uiblocks, "advanced_bullet_options", UI_EMBOSS, UI_HELV, curarea->win);
 	/* use this for a fake extra empy space around the buttons */
 	
 
 	if (ob->gameflag & OB_SOFT_BODY) {
-		uiDefBut(block, LABEL, 0, "", -10, -10, 380, 60, NULL, 0, 0, 0, 0, "");
+		uiDefBut(block, LABEL, 0, "", -10, -10, 380, 80, NULL, 0, 0, 0, 0, "");
 
 		if (ob->bsoft)
 		{
 			
-
+			yco = 40;
 			uiBlockBeginAlign(block);
 			uiDefButBitI(block, TOG, OB_BSB_COL_CL_RS, 0, "Cluster Collision RS", 
 				xco, yco, 180, 19, &ob->bsoft->collisionflags, 0, 0, 0, 0, 
@@ -3083,6 +3133,11 @@ static uiBlock *advanced_bullet_menu(void *arg_ob)
 				xco+=180, yco, 180, 19, &ob->bsoft->piterations, 0, 10, 
 				0, 0, "Position solver iterations");
 			uiBlockEndAlign(block);
+			yco -= 20;
+			xco = 0;
+			uiDefButF(block, NUMSLI, 0, "Welding ", 
+				xco, yco, 360, 19, &ob->bsoft->welding, 0.f, 0.01f, 10, 4, 
+				"Welding threshold: distance between nearby vertices to be considered equal => set to 0.0 to disable welding test and speed up scene loading (ok if the mesh has no duplicates)");
 
 			/*
 			//too complex tweaking, disable for now
@@ -3112,7 +3167,7 @@ static uiBlock *advanced_bullet_menu(void *arg_ob)
 
 		if (ob->gameflag & OB_DYNAMIC) {
 
-			yco = 100;
+			yco = 80;
 			uiDefBut(block, LABEL, 0, "", -10, -10, 380, 120, NULL, 0, 0, 0, 0, "");
 			uiBlockBeginAlign(block);
 			if (ob->margin < 0.001f)
@@ -3120,6 +3175,7 @@ static uiBlock *advanced_bullet_menu(void *arg_ob)
 			uiDefButF(block, NUM, 0, "Margin", 
 					xco, yco, 180, 19, &ob->margin, 0.001, 1.0, 1, 0, 
 					"Collision margin");
+			
 			yco -= 20;
 
 			if (ob->gameflag & OB_RIGID_BODY)
@@ -3147,7 +3203,24 @@ static uiBlock *advanced_bullet_menu(void *arg_ob)
 				uiDefButBitI(block, TOG, OB_LOCK_RIGID_BODY_Z_ROT_AXIS, 0, "Lock Z Rot Axis", 
 					xco+=180, yco, 180, 19, &ob->gameflag2, 0, 0, 0, 0, 
 					"Disable simulation of angular motion along the Z axis");
+				yco -= 20;
 			}
+			xco = 0;
+			
+			uiBlockEndAlign(block);
+			
+			uiDefBut(block, LABEL, 0, "Clamp Velocity (0=disabled)",	  xco, yco, 180*2, 19, NULL, 0, 0, 0, 0, "");
+			
+			uiBlockBeginAlign(block);
+			
+			uiDefButF(block, NUM, 0, "Min", 
+				xco+=180, yco, 90, 19, &ob->min_vel, 0.0, 1000.0, 1, 0, 
+				"Clamp velocity to this minimum speed (except when totally still)");
+			uiDefButF(block, NUM, 0, "Max", 
+				xco+=90, yco, 90, 19, &ob->max_vel, 0.0, 1000.0, 1, 0, 
+				"Clamp velocity to this maximum speed");
+			uiBlockEndAlign(block);
+			
 			/*
 			uiDefButBitI(block, TOG, OB_BSB_COL_CL_RS, 0, "Cluster Collision RS", 
 				xco, yco, 180, 19, &ob->bsoft->collisionflags, 0, 0, 0, 0, 
@@ -3178,7 +3251,7 @@ static uiBlock *advanced_bullet_menu(void *arg_ob)
 
 
 		} else {
-			
+			yco = 20;
 			uiDefBut(block, LABEL, 0, "", -10, -10, 380, 60, NULL, 0, 0, 0, 0, "");
 			uiDefButF(block, NUM, 0, "Margin", 
 					xco, yco, 180, 19, &ob->margin, 0.0, 1.0, 1, 0, 
@@ -3201,7 +3274,7 @@ static void buttons_bullet(uiBlock *block, Object *ob)
 
 	/* determine the body_type setting based on flags */
 	if (!(ob->gameflag & OB_COLLISION))
-		ob->body_type = OB_BODY_TYPE_NO_COLLISION;
+		ob->body_type = (ob->gameflag & OB_OCCLUDER) ? OB_BODY_TYPE_OCCLUDER : OB_BODY_TYPE_NO_COLLISION;
 	else if (!(ob->gameflag & OB_DYNAMIC))
 		ob->body_type = OB_BODY_TYPE_STATIC;
 	else if (!(ob->gameflag & (OB_RIGID_BODY|OB_SOFT_BODY)))
@@ -3219,7 +3292,7 @@ static void buttons_bullet(uiBlock *block, Object *ob)
 
 	//only enable game soft body if Blender Soft Body exists
 	but = uiDefButS(block, MENU, REDRAWVIEW3D, 
-			"Object type%t|No collision%x0|Static%x1|Dynamic%x2|Rigid body%x3|Soft body%x4", 
+			"Object type%t|Occluder%x5|No collision%x0|Static%x1|Dynamic%x2|Rigid body%x3|Soft body%x4", 
 			10, 205, 100, 19, &ob->body_type, 0, 0, 0, 0, "Selects the type of physical representation");
 	uiButSetFunc(but, check_body_type, but, ob);
 
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 04aa54f2526ae912e76d7e0331faa590f4f37c15..a41f954c4d8d7bf111a0361c3fbaeef68fc4c916 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -1752,6 +1752,37 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
 				uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
 			}
 			break;
+
+		case CONSTRAINT_TYPE_SHRINKWRAP:
+			{
+				bShrinkwrapConstraint *data = con->data;
+
+				height = 78;
+				if(data->shrinkType == MOD_SHRINKWRAP_PROJECT)
+					height += 18;
+
+				uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
+
+				/* Draw parameters */
+				uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+				uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->target, "Target Object");
+
+				uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Dist:", *xco + 75, *yco-42, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+				uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+120, *yco-42, 135, 18, &data->dist, -100.0f, 100.0f, 1.0f, 0.0f, "Distance to target");
+
+				uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Type:", *xco + 70, *yco-60, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+				uiDefButS(block, MENU, B_MODIFIER_RECALC, "Shrinkwrap Type%t|Nearest Surface Point %x0|Projection %x1|Nearest Vertex %x2", *xco+120, *yco-60, 135, 18, &data->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
+
+				if(data->shrinkType == MOD_SHRINKWRAP_PROJECT)
+				{
+					/* Draw XYZ toggles */
+					uiDefBut(block, LABEL,B_CONSTRAINT_TEST, "Axis:", *xco+ 75, *yco-78, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+					uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS, B_CONSTRAINT_TEST, "X",*xco+120, *yco-78, 45, 18, &data->projAxis, 0, 0, 0, 0, "Projection over X axis");
+					uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS, B_CONSTRAINT_TEST, "Y",*xco+165, *yco-78, 45, 18, &data->projAxis, 0, 0, 0, 0, "Projection over Y axis");
+					uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS, B_CONSTRAINT_TEST, "Z",*xco+210, *yco-78, 45, 18, &data->projAxis, 0, 0, 0, 0, "Projection over Z axis");
+				}
+			}
+			break;
 		default:
 			height = 0;
 			break;
@@ -1813,6 +1844,7 @@ static uiBlock *add_constraintmenu(void *arg_unused)
 	uiDefBut(block, BUTM, B_CONSTRAINT_ADD_MINMAX, "Floor",	0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
 	uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK, "Locked Track", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
 	uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH, "Follow Path", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+	uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SHRINKWRAP, "Shrinkwrap" , 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
 		
 	uiDefBut(block, SEPR, 0, "",					0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
 	
@@ -2049,6 +2081,14 @@ void do_constraintbuts(unsigned short event)
 			BIF_undo_push("Add constraint");
 		}
 		break;
+	case B_CONSTRAINT_ADD_SHRINKWRAP:
+		{
+			con = add_new_constraint(CONSTRAINT_TYPE_SHRINKWRAP);
+			add_constraint_to_active(ob, con);
+			
+			BIF_undo_push("Add constraint");
+		}
+		break;
 
 	default:
 		break;
@@ -3340,6 +3380,35 @@ static void object_panel_collision(Object *ob)
 		}
 	}
 }
+static void object_surface__enabletoggle ( void *ob_v, void *arg2 )
+{
+	Object *ob = ob_v;
+	PartDeflect *pd= ob->pd;
+	ModifierData *md = modifiers_findByType ( ob, eModifierType_Surface );
+	
+	if(!md)
+	{
+		if(pd && (pd->flag & PFIELD_SURFACE)
+			&& ELEM5(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ))
+		{
+			md = modifier_new ( eModifierType_Surface );
+			BLI_addtail ( &ob->modifiers, md );
+			DAG_scene_sort(G.scene);
+			DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+			allqueue(REDRAWBUTSEDIT, 0);
+			allqueue(REDRAWVIEW3D, 0);
+		}
+	}
+	else if(!pd || !(pd->flag & PFIELD_SURFACE)
+		|| ELEM5(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ))
+	{
+		DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+		BLI_remlink ( &ob->modifiers, md );
+		modifier_free ( md );
+		DAG_scene_sort(G.scene);
+		allqueue(REDRAWBUTSEDIT, 0);
+	}
+}
 static void object_panel_fields(Object *ob)
 {
 	uiBlock *block;
@@ -3360,6 +3429,7 @@ static void object_panel_fields(Object *ob)
 		ob->pd->pdef_sbdamp = 0.1f;
 		ob->pd->pdef_sbift  = 0.2f;
 		ob->pd->pdef_sboft  = 0.02f;
+		ob->pd->tex_nabla = 0.025f;
 	}
 	
 	if(ob->pd) {
@@ -3424,9 +3494,12 @@ static void object_panel_fields(Object *ob)
 		}
 		
 		if(ob->particlesystem.first)
-			uiDefButS(block, MENU, B_FIELD_DEP, menustr,			80,180,70,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr);
+			but = uiDefButS(block, MENU, B_FIELD_DEP, menustr,			80,180,70,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr);
 		else
-			uiDefButS(block, MENU, B_FIELD_DEP, menustr,			10,180,140,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr);
+			but = uiDefButS(block, MENU, B_FIELD_DEP, menustr,			10,180,140,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr);
+
+		if(!particles)
+			uiButSetFunc(but, object_surface__enabletoggle, ob, NULL);
 
 		uiBlockEndAlign(block);
 		uiDefBut(block, LABEL, 0, "",160,180,150,2, NULL, 0.0, 0, 0, 0, "");
@@ -3467,11 +3540,16 @@ static void object_panel_fields(Object *ob)
 			else if(pd->forcefield==PFIELD_TEXTURE){
 				uiDefButS(block, MENU, B_FIELD_CHANGE, "Texture mode%t|RGB%x0|Gradient%x1|Curl%x2",	10,50,140,20, &pd->tex_mode, 0.0, 0.0, 0, 0, "How the texture effect is calculated (RGB & Curl need a RGB texture else Gradient will be used instead)");
 	
-				uiDefButF(block, NUM, B_FIELD_CHANGE, "Nabla:",	10,30,140,20, &pd->tex_nabla, 0.0001f, 1.0, 1, 0, "Specify the dimension of the area for gradient and curl calculation");
+				uiDefButF(block, NUM, B_FIELD_CHANGE, "Nabla:",	10,30,140,20, &pd->tex_nabla, 0.0001f, 1.0, 1, 0, "Defines size of derivative offset used for calculating gradient and curl");
 			}
 			else if(particles==0 && ELEM(pd->forcefield,PFIELD_VORTEX,PFIELD_WIND)==0){
 				//uiDefButF(block, NUM, B_FIELD_CHANGE, "Distance: ",	10,20,140,20, &pd->f_dist, 0, 1000.0, 10, 0, "Falloff power (real gravitational fallof = 2)");
-				uiDefButBitS(block, TOG, PFIELD_PLANAR, B_FIELD_CHANGE, "Planar",	10,15,140,20, &pd->flag, 0.0, 0, 0, 0, "Create planar field");
+				uiDefButBitS(block, TOG, PFIELD_PLANAR, B_FIELD_CHANGE, "Planar",	10,35,140,20, &pd->flag, 0.0, 0, 0, 0, "Create planar field");
+			}
+			
+			if(particles==0 && ELEM5(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ)) {
+				but = uiDefButBitS(block, TOG, PFIELD_SURFACE, B_FIELD_CHANGE, "Surface",	10,15,140,20, &pd->flag, 0.0, 0, 0, 0, "Use closest point on surface");
+				uiButSetFunc(but, object_surface__enabletoggle, ob, NULL);
 			}
 			uiBlockEndAlign(block);
 			
@@ -4390,11 +4468,11 @@ static void object_panel_particle_extra(Object *ob)
 		buty-=buth;
 
 	/* size changes must create a recalc event always so that sizes are updated properly */
-	uiDefButF(block, NUM, B_PART_RECALC, "Size:",	butx,(buty-=buth),butw,buth, &part->size, 0.01, 100, 10, 1, "The size of the particles");
-	uiDefButF(block, NUM, B_PART_RECALC, "Rand:",	butx,(buty-=buth),butw,buth, &part->randsize, 0.0, 1.0, 10, 1, "Give the particle size a random variation");
+	uiDefButF(block, NUM, B_PART_RECALC, "Size:",	butx,(buty-=buth),butw,buth, &part->size, 0.001, 100, 10, 0, "The size of the particles");
+	uiDefButF(block, NUM, B_PART_RECALC, "Rand:",	butx,(buty-=buth),butw,buth, &part->randsize, 0.0, 1.0, 10, 0, "Give the particle size a random variation");
 
 	uiDefButBitI(block, TOG, PART_SIZEMASS, B_PART_RECALC, "Mass from size",	 butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Multiply mass with particle size");
-	uiDefButF(block, NUM, B_PART_RECALC, "Mass:",	butx,(buty-=buth),butw,buth, &part->mass, 0.01, 100, 10, 1, "Specify the mass of the particles");
+	uiDefButF(block, NUM, B_PART_RECALC, "Mass:",	butx,(buty-=buth),butw,buth, &part->mass, 0.001, 100, 10, 0, "Specify the mass of the particles");
 }
 /* copy from buttons_shading.c */
 static void autocomplete_uv(char *str, void *arg_v)
@@ -4898,8 +4976,8 @@ static void object_panel_particle_system(Object *ob)
 	}
 
 	if(part->type!=PART_HAIR) {
-		uiDefButF(block, NUM, B_PART_INIT, "Life:",	butx,(buty-=buth),butw,buth, &part->lifetime, 1.0, MAXFRAMEF, 100, 1, "Specify the life span of the particles");
-		uiDefButF(block, NUM, B_PART_INIT, "Rand:",	butx,(buty-=buth),butw,buth, &part->randlife, 0.0, 2.0, 10, 1, "Give the particle life a random variation");
+		uiDefButF(block, NUM, B_PART_INIT, "Life:",	butx,(buty-=buth),butw,buth, &part->lifetime, 1.0, MAXFRAMEF, 100, 0, "Specify the life span of the particles");
+		uiDefButF(block, NUM, B_PART_INIT, "Rand:",	butx,(buty-=buth),butw,buth, &part->randlife, 0.0, 1.0, 10, 0, "Give the particle life a random variation");
 	}
 
 	uiBlockEndAlign(block);
diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c
index f026e5f4034cc9fb52885e74332a9c7662e0ae16..577486135b42677758902f8425b8b414d6a6476c 100644
--- a/source/blender/src/buttons_scene.c
+++ b/source/blender/src/buttons_scene.c
@@ -1772,7 +1772,7 @@ static uiBlock *framing_render_menu(void *arg_unused)
 	block= uiNewBlock(&curarea->uiblocks, "framing_options", UI_EMBOSS, UI_HELV, curarea->win);
 
 	/* use this for a fake extra empy space around the buttons */
-	uiDefBut(block, LABEL, 0, "",			-5, -10, 295, 300, NULL, 0, 0, 0, 0, "");
+	uiDefBut(block, LABEL, 0, "",			-5, -10, 295, 305, NULL, 0, 0, 0, 0, "");
 
 	uiDefBut(block, LABEL, 0, "Framing:", xco, yco, 68,19, 0, 0, 0, 0, 0, "");
 	uiBlockBeginAlign(block);
@@ -1787,16 +1787,17 @@ static uiBlock *framing_render_menu(void *arg_unused)
 	uiDefButF(block, COL, 0, "",                0, yco - 58 + 18, 33, 58, &G.scene->framing.col[0], 0, 0, 0, randomcolorindex, "");
 
 	uiBlockBeginAlign(block);
-	uiDefButF(block, NUMSLI, 0, "R ", xco,yco,243,18, &G.scene->framing.col[0], 0.0, 1.0, randomcolorindex, 0, "Set the red component of the bars");
+	uiDefButF(block, NUMSLI, 0, "R ", xco,yco,240,18, &G.scene->framing.col[0], 0.0, 1.0, randomcolorindex, 0, "Set the red component of the bars");
 	yco -= 20;
-	uiDefButF(block, NUMSLI, 0, "G ", xco,yco,243,18, &G.scene->framing.col[1], 0.0, 1.0, randomcolorindex, 0, "Set the green component of the bars");
+	uiDefButF(block, NUMSLI, 0, "G ", xco,yco,240,18, &G.scene->framing.col[1], 0.0, 1.0, randomcolorindex, 0, "Set the green component of the bars");
 	yco -= 20;
-	uiDefButF(block, NUMSLI, 0, "B ", xco,yco,243,18, &G.scene->framing.col[2], 0.0, 1.0, randomcolorindex, 0, "Set the blue component of the bars");
+	uiDefButF(block, NUMSLI, 0, "B ", xco,yco,240,18, &G.scene->framing.col[2], 0.0, 1.0, randomcolorindex, 0, "Set the blue component of the bars");
 	uiBlockEndAlign(block);
 	
 	xco = 0;
 	uiDefBut(block, LABEL, 0, "Fullscreen:",		xco, yco-=30, 100, 19, 0, 0.0, 0.0, 0, 0, "");
-	uiDefButS(block, TOG, 0, "Fullscreen", xco+70, yco, 68, 19, &G.scene->r.fullscreen, 0.0, 0.0, 0, 0, "Starts player in a new fullscreen display");
+	uiDefButS(block, TOG, 0, "Fullscreen", xco+74, yco, 68, 19, &G.scene->r.fullscreen, 0.0, 0.0, 0, 0, "Starts player in a new fullscreen display");
+	xco = 3;
 	uiBlockBeginAlign(block);
 	uiDefButS(block, NUM, 0, "X:",		xco+40, yco-=27, 100, 19, &G.scene->r.xplay, 10.0, 2000.0, 0, 0, "Displays current X screen/window resolution. Click to change.");
 	uiDefButS(block, NUM, 0, "Y:",		xco+140, yco, 100, 19, &G.scene->r.yplay,    10.0, 2000.0, 0, 0, "Displays current Y screen/window resolution. Click to change.");
@@ -1816,26 +1817,29 @@ static uiBlock *framing_render_menu(void *arg_unused)
 	 * RAS_STEREO_VINTERLACE	7
 	 * RAS_STEREO_DOME		8
 	 */
+
+	xco = 8;
 	uiBlockBeginAlign(block);
 	uiDefButS(block, ROW, 0, "No Stereo", xco, yco-=30, 88, 19, &(G.scene->r.stereomode), 7.0, 1.0, 0, 0, "Disables stereo");
-	uiDefButS(block, ROW, 0, "Pageflip", xco+=90, yco, 88, 19, &(G.scene->r.stereomode), 7.0, 2.0, 0, 0, "Enables hardware pageflip stereo method");
-	uiDefButS(block, ROW, 0, "Syncdouble", xco+=90, yco, 88, 19, &(G.scene->r.stereomode), 7.0, 3.0, 0, 0, "Enables syncdoubling stereo method");
-	uiDefButS(block, ROW, 0, "Anaglyph", xco-=180, yco-=21, 88, 19, &(G.scene->r.stereomode), 7.0, 5.0, 0, 0, "Enables anaglyph (Red-Blue) stereo method");
-	uiDefButS(block, ROW, 0, "Side by Side", xco+=90, yco, 88, 19, &(G.scene->r.stereomode), 7.0, 6.0, 0, 0, "Enables side by side left and right images");
-	uiDefButS(block, ROW, 0, "V Interlace", xco+=90, yco, 88, 19, &(G.scene->r.stereomode), 7.0, 7.0, 0, 0, "Enables interlaced vertical strips for autostereo display");
+	uiDefButS(block, ROW, 0, "Pageflip", xco+90, yco, 88, 19, &(G.scene->r.stereomode), 7.0, 2.0, 0, 0, "Enables hardware pageflip stereo method");
+	uiDefButS(block, ROW, 0, "Syncdouble", xco+180, yco, 88, 19, &(G.scene->r.stereomode), 7.0, 3.0, 0, 0, "Enables syncdoubling stereo method");
+	uiDefButS(block, ROW, 0, "Anaglyph", xco, yco-=21, 88, 19, &(G.scene->r.stereomode), 7.0, 5.0, 0, 0, "Enables anaglyph (Red-Blue) stereo method");
+	uiDefButS(block, ROW, 0, "Side by Side", xco+90, yco, 88, 19, &(G.scene->r.stereomode), 7.0, 6.0, 0, 0, "Enables side by side left and right images");
+	uiDefButS(block, ROW, 0, "V Interlace", xco+180, yco, 88, 19, &(G.scene->r.stereomode), 7.0, 7.0, 0, 0, "Enables interlaced vertical strips for autostereo display");
 	
 	uiBlockEndAlign(block);
 
+	xco = 8;
 	uiBlockBeginAlign(block);
-	uiDefButS(block, ROW, 0, "Dome", xco-=180, yco-=30, 88, 19, &(G.scene->r.stereomode), 7.0, 8.0, 0, 0, "Enables dome camera");
-	uiDefButS(block, NUM, 0, "Ang:",		xco+=90, yco, 88, 19, &G.scene->r.domeangle, 90.0, 250.0, 0, 0, "Angle (Aperture) of the Dome - it only works in mode 1");
-	uiDefButS(block, NUM, 0, "Mode:",		xco+=90, yco, 88, 19, &G.scene->r.domemode, 1.0, 3.0, 0, 0, "Dome mode - 1 fisheye, 2 truncated, 3 spherical panoramic");
+	uiDefButS(block, ROW, 0, "Dome",	xco, yco-=30, 88, 19, &(G.scene->r.stereomode), 7.0, 8.0, 0, 0, "Enables dome camera");
+	uiDefButS(block, NUM, 0, "Ang:",	xco+90, yco, 88, 19, &G.scene->r.domeangle, 90.0, 250.0, 0, 0, "Angle (Aperture) of the Dome - it only works in mode 1");
+	uiDefButS(block, NUM, 0, "Mode:",	xco+180, yco, 88, 19, &G.scene->r.domemode, 1.0, 3.0, 0, 0, "1 fisheye, 2 environment map, 3 spherical panoramic");
 
-	uiDefButF(block, NUM, 0, "Size:",		xco-=180, yco-=21, 88, 19, &G.scene->r.domesize, 0.5, 3.5, 0, 0, "Size adjustments");
-	uiDefButS(block, NUM, 0, "Tes:",		xco+=90, yco, 88, 19, &G.scene->r.domeres, 1.0, 8.0, 0, 0, "Tesselation level - 1 to 8");
-	uiDefButF(block, NUM, 0, "Res:",	xco+=90, yco, 88, 19, &G.scene->r.domeresbuf, 0.1, 1.0, 0, 0, "Buffer Resolution - decrease it to increase speed");
+	uiDefButF(block, NUM, 0, "Size:",	xco, yco-=21, 88, 19, &G.scene->r.domesize, 0.5, 3.5, 0, 0, "Size adjustments");
+	uiDefButS(block, NUM, 0, "Tes:",	xco+90, yco, 88, 19, &G.scene->r.domeres, 1.0, 8.0, 0, 0, "Tesselation level - 1 to 8");
+	uiDefButF(block, NUM, 0, "Res:",	xco+180, yco, 88, 19, &G.scene->r.domeresbuf, 0.1, 1.0, 0, 0, "Buffer Resolution - decrease it to increase speed");
 
-	uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Warp Data: ", xco-180,yco-=21,268, 19, &G.scene->r.dometext, "Custom Warp Mesh data file");
+	uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Warp Data: ", xco,yco-=21,268, 19, &G.scene->r.dometext, "Custom Warp Mesh data file");
 	uiBlockEndAlign(block);
 
 	uiBlockSetDirection(block, UI_TOP);
diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c
index fe4649f31f431e23e9babde753bdad908fd23f0d..a129698cce3306977e2e44066b1f714c295e76ed 100644
--- a/source/blender/src/buttons_shading.c
+++ b/source/blender/src/buttons_shading.c
@@ -2181,7 +2181,7 @@ static void world_panel_mistaph(World *wrld)
 	uiSetButLock(wrld->id.lib!=0, ERROR_LIBDATA_MESSAGE);
 
 #if GAMEBLENDER == 1
-	uiDefButI(block, MENU, 1, 
+	uiDefButS(block, MENU, B_REDR, 
 #ifdef USE_ODE
 			  "Physics %t|None %x0|Sumo %x2|Ode %x4 |Bullet %x5",
 #else
@@ -2198,6 +2198,12 @@ static void world_panel_mistaph(World *wrld)
 	
 	/* Gravitation for the game worlds */
 	uiDefButF(block, NUMSLI,0, "Grav ", 150,180,150,19,	&(wrld->gravity), 0.0, 25.0, 0, 0,  "Sets the gravitation constant of the game world");
+	if (wrld->physicsEngine == WOPHY_BULLET) {
+		uiDefButBitS(block, TOG, WO_DBVT_CULLING, B_REDR, "DBVT culling",	10,160,140,19, &wrld->mode, 0, 0, 0, 0, "Toggles use of optimized Bullet DBVT tree for view frustrum and occlusion culling");
+		if (wrld->mode & WO_DBVT_CULLING)
+			uiDefButS(block, NUM, B_REDR, "Occlu Res:",
+				150, 160, 150, 19, &wrld->occlusionRes, 128.0, 1024.0, 0, 0, "Sets the size of the occlusion buffer in pixel, use higher value for better precsion (slower)");
+	}
 #endif
 
 	uiBlockSetCol(block, TH_BUT_SETTING1);
diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c
index 3c6cef469a2d1fdca07364c059b5df2f30ff0189..4ec9b587b58e09849e341e3fa44169567a5ab102 100644
--- a/source/blender/src/drawgpencil.c
+++ b/source/blender/src/drawgpencil.c
@@ -139,12 +139,14 @@ void gp_ui_delstroke_cb (void *gpd, void *gpl)
 {
 	bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
 	
-	if (gpf->framenum != CFRA) return;
+	if (gpf) {
+		if (gpf->framenum != CFRA) return;
 
-	gpencil_layer_setactive(gpd, gpl);
-	gpencil_frame_delete_laststroke(gpf, gpl);
-	
-	scrarea_queue_winredraw(curarea);
+		gpencil_layer_setactive(gpd, gpl);
+		gpencil_frame_delete_laststroke(gpl, gpf);
+		
+		scrarea_queue_winredraw(curarea);
+	}
 }
 
 /* delete active frame of active layer */
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index c9fffa407ee38bc88f8f6974138164f86b1c9a74..5fb60449a250864b45866cff084ed635958ad127 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -4738,7 +4738,7 @@ void draw_object(Base *base, int flag)
 		/* don't do xray in particle mode, need the z-buffer */
 		if(!(G.f & G_PARTICLEEDIT)) {
 			/* xray and transp are set when it is drawing the 2nd/3rd pass */
-			if(!G.vd->xray && !G.vd->transp && (ob->dtx & OB_DRAWXRAY)) {
+			if(!G.vd->xray && !G.vd->transp && (ob->dtx & OB_DRAWXRAY) && !(ob->dtx & OB_DRAWTRANSP)) {
 				add_view3d_after(G.vd, base, V3D_XRAY, flag);
 				return;
 			}
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
index cd40b5e0ae22f40d16518f1e5b89d64f72bbf120..d6184f4241018e5ebc4afa6e5b0ecfd7afc29515 100644
--- a/source/blender/src/drawview.c
+++ b/source/blender/src/drawview.c
@@ -977,8 +977,8 @@ void backdrawview3d(int test)
 	int m;
 #endif
 
-	if(	G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT );
-	else if ((G.f & G_TEXTUREPAINT) && G.scene->toolsettings && (G.scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0);
+	if(	G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || (FACESEL_PAINT_TEST));
+	else if ((G.f & G_TEXTUREPAINT) && G.scene->toolsettings && (G.scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE));
 	else if(G.obedit && G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT));
 	else {
 		G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
index ec14e2aabe2fd69997d8d5bab310fcfe1d57df44..e5be396fa47a7fee97a0b49b2d5e059cd323bf3b 100644
--- a/source/blender/src/editarmature.c
+++ b/source/blender/src/editarmature.c
@@ -715,6 +715,7 @@ int join_armature(void)
 						VecSubf(delta, curbone->tail, curbone->head);
 						vec_roll_to_mat3(delta, curbone->roll, temp);
 						
+						Mat4One(premat); /* Mat4MulMat34 only sets 3x3 part */
 						Mat4MulMat34(premat, temp, mat);
 						
 						Mat4MulVecfl(mat, curbone->head);
diff --git a/source/blender/src/editarmature_generate.c b/source/blender/src/editarmature_generate.c
index ad312f079bd723e863c28f0dd697b4ed2691be8d..930ca263499620cf4a2498f541fe0e3d6a8e7ce9 100644
--- a/source/blender/src/editarmature_generate.c
+++ b/source/blender/src/editarmature_generate.c
@@ -51,14 +51,14 @@ void setBoneRollFromNormal(EditBone *bone, float *no, float invmat[][4], float t
 {
 	if (no != NULL && !VecIsNull(no))
 	{
-		float tangent[3], cotangent[3], normal[3];
+		float tangent[3], vec[3], normal[3];
 
 		VECCOPY(normal, no);	
 		Mat3MulVecfl(tmat, normal);
 
 		VecSubf(tangent, bone->tail, bone->head);
-		Crossf(cotangent, tangent, normal);
-		Crossf(normal, cotangent, tangent);
+		Projf(vec, tangent, normal);
+		VecSubf(normal, normal, vec);
 		
 		Normalize(normal);
 		
diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c
index 38e44319b47b8c9dd5378beb0828b2330794be44..dbf53bedbf932d6f871a24db29333a6ec471b673 100644
--- a/source/blender/src/editarmature_sketch.c
+++ b/source/blender/src/editarmature_sketch.c
@@ -1011,7 +1011,22 @@ void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
 		}
 		
 		glEnd();
-	
+
+#if 0	
+		glColor3f(0, 0, 1);
+		glBegin(GL_LINES);
+
+		for (i = 0; i < stk->nb_points; i++)
+		{
+			float *p = stk->points[i].p;
+			float *no = stk->points[i].no;
+			glVertex3fv(p);
+			glVertex3f(p[0] + no[0], p[1] + no[1], p[2] + no[2]);
+		}
+		
+		glEnd();
+#endif
+
 		glColor3f(0, 0, 0);
 		glBegin(GL_POINTS);
 	
@@ -1961,7 +1976,7 @@ void sk_convertStroke(SK_Stroke *stk)
 
 					Mat4MulVecfl(invmat, bone->head);
 					Mat4MulVecfl(invmat, bone->tail);
-					setBoneRollFromNormal(bone, pt->no, invmat, tmat);
+					setBoneRollFromNormal(bone, head->no, invmat, tmat);
 				}
 				
 				new_parent = bone;
@@ -2215,6 +2230,7 @@ void sk_applyCutGesture(SK_Gesture *gest, SK_Sketch *sketch)
 		pt.type = PT_EXACT;
 		pt.mode = PT_PROJECT; /* take mode from neighbouring points */
 		VECCOPY(pt.p, isect->p);
+		VECCOPY(pt.no, isect->stroke->points[isect->before].no);
 		
 		sk_insertStrokePoint(isect->stroke, &pt, isect->after);
 	}
@@ -2256,6 +2272,7 @@ void sk_applyTrimGesture(SK_Gesture *gest, SK_Sketch *sketch)
 		pt.type = PT_EXACT;
 		pt.mode = PT_PROJECT; /* take mode from neighbouring points */
 		VECCOPY(pt.p, isect->p);
+		VECCOPY(pt.no, isect->stroke->points[isect->before].no);
 		
 		VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
 		
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c
index 42972e4aa5dd32b25341fbb4042e16b167a3f6a2..865bf1ba29de0ca7e149c99c1d0ae3fff256732d 100644
--- a/source/blender/src/editconstraint.c
+++ b/source/blender/src/editconstraint.c
@@ -366,6 +366,8 @@ void add_constraint (short only_IK)
 				nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
 			else if ((obsel) && (obsel->type==OB_CURVE))
 				nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
+			else if ((obsel) && (obsel->type==OB_MESH))
+				nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Shrinkwrap%x22|Stretch To%x7|%l|Action%x16|Script%x18");
 			else if (obsel)
 				nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
 			else
@@ -374,6 +376,8 @@ void add_constraint (short only_IK)
 		else {
 			if ((obsel) && (obsel->type==OB_CURVE))
 				nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18");
+			else if ((obsel) && (obsel->type==OB_MESH))
+				nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Shrinkwrap%x22|%l|Action%x16|Script%x18");
 			else if (obsel)
 				nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
 			else
@@ -476,6 +480,7 @@ void add_constraint (short only_IK)
 		}
 		else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
 		else if (nr==21) con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT);
+		else if (nr==22) con = add_new_constraint(CONSTRAINT_TYPE_SHRINKWRAP);
 		
 		if (con==NULL) return;	/* paranoia */
 		
diff --git a/source/blender/src/editfont.c b/source/blender/src/editfont.c
index a3b05a008c8d6b3ba851221cb9646319bba3c08a..682125dabb123cf2ec8db5c3dadf4c5a944d4f8d 100644
--- a/source/blender/src/editfont.c
+++ b/source/blender/src/editfont.c
@@ -241,7 +241,7 @@ void update_string(Curve *cu)
 	wcs2utf8s(cu->str, textbuf);
 }
 
-static int insert_into_textbuf(Curve *cu, unsigned long c)
+static int insert_into_textbuf(Curve *cu, uintptr_t c)
 {
 	if (cu->len<MAXTEXT-1) {
 		int x;
@@ -620,12 +620,12 @@ int mat_to_sel(void) {
 	return 0;
 }
 
-void do_textedit(unsigned short event, short val, unsigned long _ascii)
+void do_textedit(unsigned short event, short val, uintptr_t _ascii)
 {
 	Curve *cu;
 	static int accentcode= 0;
 	int x, doit=0, cursmove=0;
-	unsigned long ascii = _ascii;
+	uintptr_t ascii = _ascii;
 	short kern;
 
 	cu= G.obedit->data;
diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c
index 690b4481ec97991089128498d0223bc15883ffee..0fb072c1af41d7ac3d7efbc1d4316c5a46d86ce2 100644
--- a/source/blender/src/editmesh_tools.c
+++ b/source/blender/src/editmesh_tools.c
@@ -2520,11 +2520,13 @@ void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
 								}
 							}
 						}
-						sort[hold]->f &= ~SELECT;
-						sort[hold]->f2 |= EDGENEW;
-						length[hold] = -1;
-					}							
-				} 
+						if (hold > -1) {
+							sort[hold]->f &= ~SELECT;
+							sort[hold]->f2 |= EDGENEW;
+							length[hold] = -1;
+						}
+					}
+				}
 				
 				// Beauty Long Edges
 				else {
@@ -2541,13 +2543,15 @@ void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
 								}
 							}
 						}
-						sort[hold]->f &= ~SELECT;
-						sort[hold]->f2 |= EDGENEW;
-						length[hold] = -1;
-					}							
-				}   
+						if (hold > -1) {
+							sort[hold]->f &= ~SELECT;
+							sort[hold]->f2 |= EDGENEW;
+							length[hold] = -1;
+						}
+					}
+				}
 			}
-		}	
+		}
 	}
 
 	gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); 
@@ -5620,6 +5624,8 @@ void mesh_rip(void)
 	float projectMat[4][4], viewMat[4][4], vec[3], dist, mindist;
 	short doit= 1, mval[2],propmode,prop;
 	
+	if(multires_test()) return;
+	
 	propmode = G.scene->prop_mode;
 	G.scene->prop_mode = 0;
 	prop = G.scene->proportional;
diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c
index 179ea41d5ad5e27939ff775530b6e714af47ae74..3127f0e5072ce14bc7c45ba0095e2f86db965d36 100644
--- a/source/blender/src/editnla.c
+++ b/source/blender/src/editnla.c
@@ -927,7 +927,11 @@ void deselect_nlachannel_keys (int test)
 	
 	/* Determine if this is selection or deselection */
 	if (test){
-		for (base=G.scene->base.first; base && sel; base=base->next){		
+		for (base=G.scene->base.first; base && sel; base=base->next){	
+			/* only consider if visible */
+			if (nla_filter(base) == 0)
+				continue;
+			
 			/* Test object ipos */
 			if (is_ipo_key_selected(base->object->ipo)){
 				sel = 0;
@@ -986,7 +990,11 @@ void deselect_nlachannel_keys (int test)
 	
 	
 	/* Set the flags */
-	for (base=G.scene->base.first; base; base=base->next){		
+	for (base=G.scene->base.first; base; base=base->next){	
+		/* only consider if visible */
+		if (nla_filter(base) == 0)
+			continue;
+		
 		/* Set the object ipos */
 		set_ipo_key_selection(base->object->ipo, sel);
 		
@@ -1068,6 +1076,10 @@ void delete_nlachannel_keys(void)
 	bActionStrip *strip, *nextstrip;
 		
 	for (base = G.scene->base.first; base; base=base->next){
+		/* only consider if visible */
+		if (nla_filter(base) == 0)
+			continue;
+		
 		/* Delete object ipos */
 		delete_ipo_keys(base->object->ipo);
 		
@@ -1122,7 +1134,11 @@ void duplicate_nlachannel_keys(void)
 	bActionStrip *strip, *laststrip;
 	
 	/* Find selected items */
-	for (base = G.scene->base.first; base; base=base->next){	
+	for (base = G.scene->base.first; base; base=base->next){
+		/* only consider if visible */
+		if (nla_filter(base) == 0)
+			continue;
+			
 		/* Duplicate object keys */
 		duplicate_ipo_keys(base->object->ipo);
 		
diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c
index f5de20891b4d2ebd97a455962ca9375b76efe0c8..f0046a960e941d995b2e207b373d55bdac8ef973 100644
--- a/source/blender/src/editnode.c
+++ b/source/blender/src/editnode.c
@@ -35,6 +35,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_action_types.h"
+#include "DNA_brush_types.h"
 #include "DNA_color_types.h"
 #include "DNA_image_types.h"
 #include "DNA_ipo_types.h"
@@ -583,13 +584,41 @@ void snode_set_context(SpaceNode *snode)
 		snode->nodetree= G.scene->nodetree;
 	}
 	else if(snode->treetype==NTREE_TEXTURE) {
-		if(ob) {
-			Tex *tx= give_current_texture(ob, ob->actcol);
-			if(tx) {
-				snode->from= (ID*)ob; /* please check this; i have no idea what 'from' is. */
-				snode->id= &tx->id;
-				snode->nodetree= tx->nodetree;
+		Tex *tx= NULL;
+
+		if(snode->texfrom==SNODE_TEX_OBJECT) {
+			if(ob) {
+				tx= give_current_texture(ob, ob->actcol);
+				snode->from= (ID *)ob;
+			}
+		}
+		else if(snode->texfrom==SNODE_TEX_WORLD) {
+			tx= give_current_world_texture();
+			snode->from= (ID *)G.scene->world;
+		}
+		else {
+			MTex *mtex= NULL;
+			
+			if(G.f & G_SCULPTMODE) {
+				SculptData *sd= &G.scene->sculptdata;
+				if(sd->texact != -1)
+					mtex= sd->mtex[sd->texact];
 			}
+			else {
+				Brush *br= G.scene->toolsettings->imapaint.brush;
+				if(br) 
+					mtex= br->mtex[br->texact];
+			}
+			
+			if(mtex) {
+				snode->from= (ID *)G.scene;
+				tx= mtex->tex;
+			}
+		}
+		
+		if(tx) {
+			snode->id= &tx->id;
+			snode->nodetree= tx->nodetree;
 		}
 	}
 	
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index bb9be49c347446b11aba5d5ccac66f09b1b8df90..b6b6c3c8df9110e80d9846558afcf34ad0d0dced 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -216,6 +216,7 @@ void add_object_draw(int type)	/* for toolbox or menus, only non-editmode stuff
 		else if(type==OB_LAMP) {
 			BIF_undo_push("Add Lamp");
 			reshadeall_displist();	/* only frees */
+			BIF_preview_changed(ID_LA);
 		}
 		else if(type==OB_LATTICE) BIF_undo_push("Add Lattice");
 		else if(type==OB_CAMERA) BIF_undo_push("Add Camera");
@@ -3205,14 +3206,12 @@ static void copymenu_properties(Object *ob)
 		prop= prop->next;
 	}
 	
-	if(tot==0) {
-		error("No properties in the active object to copy");
-		return;
-	}
-	
 	str= MEM_callocN(50 + 33*tot, "copymenu prop");
 	
-	strcpy(str, "Copy Property %t|Replace All|Merge All|%l");
+	if (tot)
+		strcpy(str, "Copy Property %t|Replace All|Merge All|%l");
+	else
+		strcpy(str, "Copy Property %t|Clear All (no properties on active)");
 	
 	tot= 0;	
 	prop= ob->prop.first;
@@ -3526,7 +3525,8 @@ void copy_attr(short event)
 					base->object->formfactor = ob->formfactor;
 					base->object->damping= ob->damping;
 					base->object->rdamping= ob->rdamping;
-					base->object->mass= ob->mass;
+					base->object->min_vel= ob->min_vel;
+					base->object->max_vel= ob->max_vel;
 					if (ob->gameflag & OB_BOUNDS) {
 						base->object->boundtype = ob->boundtype;
 					}
diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c
index 76e44e5c24fa7dba3a58ec82358e21ad815179a9..5dcfae30960c11d62e51a5763ffa9c20e10db301 100644
--- a/source/blender/src/editseq.c
+++ b/source/blender/src/editseq.c
@@ -174,7 +174,7 @@ void clear_last_seq()
 	_last_seq_init = 0;
 }
 
-Sequence *get_forground_frame_seq(int frame)
+Sequence *get_foreground_frame_seq(int frame)
 {
 	Editing *ed;
 	Sequence *seq, *best_seq=NULL;
@@ -1183,6 +1183,10 @@ static Sequence *sfile_to_ramsnd_sequence(SpaceFile *sfile,
 	strncpy(str, sfile->dir, FILE_MAXDIR-1);
 	strncat(str, sfile->file, FILE_MAXFILE-1);
 
+	if(sfile->flag & FILE_STRINGCODE) {
+		BLI_makestringcode(G.sce, str);
+	}
+	
 	sound= sound_new_sound(str);
 	if (!sound || sound->sample->type == SAMPLE_INVALID) {
 		error("Unsupported audio format");
diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c
index 9800c80b57d15637f63e04386481ef3b6634b6b9..36427fce36b35f7f4fb2a768422d0e1d624e4b6a 100644
--- a/source/blender/src/filesel.c
+++ b/source/blender/src/filesel.c
@@ -196,7 +196,7 @@ static int compare_name(const void *a1, const void *a2)
 	if( strcmp(entry2->relname, ".")==0 ) return (1);
 	if( strcmp(entry1->relname, "..")==0 ) return (-1);
 	
-	return (BLI_strcasecmp(entry1->relname,entry2->relname));
+	return (BLI_natstrcmp(entry1->relname,entry2->relname));
 }
 
 static int compare_date(const void *a1, const void *a2)	
diff --git a/source/blender/src/ghostwinlay.c b/source/blender/src/ghostwinlay.c
index 9388ac93543f2666614235505ca1658a93727cc5..794ba0cf6e0c7734b8da69c5d40903d736a1f364 100644
--- a/source/blender/src/ghostwinlay.c
+++ b/source/blender/src/ghostwinlay.c
@@ -212,7 +212,12 @@ static GHOST_TStandardCursor convert_cursor(int curs) {
 	case CURSOR_FACESEL:		return GHOST_kStandardCursorRightArrow;
 	case CURSOR_WAIT:		return GHOST_kStandardCursorWait;
 	case CURSOR_EDIT:		return GHOST_kStandardCursorCrosshair;
-	case CURSOR_HELP:		return GHOST_kStandardCursorHelp;
+	case CURSOR_HELP:		
+#ifdef __APPLE__
+		return GHOST_kStandardCursorLeftRight;
+#else
+		return GHOST_kStandardCursorHelp;
+#endif
 	case CURSOR_X_MOVE:		return GHOST_kStandardCursorLeftRight;
 	case CURSOR_Y_MOVE:		return GHOST_kStandardCursorUpDown;
 	case CURSOR_PENCIL:		return GHOST_kStandardCursorPencil;
diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c
index c7e453c416c30e09656a2eb772614c0a8843a6aa..4f50a83a3f237c1c037defa5b5ccdb2fc9026a00 100644
--- a/source/blender/src/gpencil.c
+++ b/source/blender/src/gpencil.c
@@ -484,7 +484,7 @@ ScrArea *gpencil_data_findowner (bGPdata *gpd)
 /* -------- GP-Frame API ---------- */
 
 /* delete the last stroke of the given frame */
-void gpencil_frame_delete_laststroke (bGPDframe *gpf, bGPDlayer *gpl)
+void gpencil_frame_delete_laststroke (bGPDlayer *gpl, bGPDframe *gpf)
 {
 	bGPDstroke *gps= (gpf) ? gpf->strokes.last : NULL;
 	
@@ -704,7 +704,7 @@ void gpencil_delete_laststroke (bGPdata *gpd)
 	
 	if (gpf->framenum != CFRA) return;
 
-	gpencil_frame_delete_laststroke(gpf, gpl);
+	gpencil_frame_delete_laststroke(gpl, gpf);
 }
 
 /* delete the active frame */
diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c
index 6e43b6073ebb2871b000275df7ef5ec5886a86c1..71abed0d80676d3374079ea0372fc7b9d80c46ca 100644
--- a/source/blender/src/header_info.c
+++ b/source/blender/src/header_info.c
@@ -1720,15 +1720,15 @@ static uiBlock *info_gamemenu(void *arg_unused)
 		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Enable All Frames",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_ENABLE_ALL_FRAMES, "");
 	}
 	
-	if(G.fileflags & G_FILE_GAME_TO_IPO) {
-		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Record Game Physics to IPO",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, "");
-	} else {
-
 	if(G.fileflags & G_FILE_DISPLAY_LISTS) {
 		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Generate Display Lists",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DISPLAY_LISTS, "");
 	} else {
 		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Generate Display Lists",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DISPLAY_LISTS, "");
 	}	
+
+	if(G.fileflags & G_FILE_GAME_TO_IPO) {
+		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Record Game Physics to IPO",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, "");
+	} else {
 		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Record Game Physics to IPO",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, "");
 	}
 	
@@ -1929,7 +1929,7 @@ static uiBlock *info_timelinemenu(void *arg_unused)
 void do_info_render_bakemenu(void *arg, int event)
 {
 	switch (event) {
-	case 6:
+	case (R_BAKE_TO_ACTIVE|R_BAKE_OSA):
 		G.scene->r.bake_flag ^= event;
 		break;
 	default:
@@ -1948,9 +1948,9 @@ static uiBlock *info_render_bakemenu(void *arg_unused)
 	uiBlockSetButmFunc(block, do_info_render_bakemenu, NULL);
 	
 	if(G.scene->r.bake_flag & R_BAKE_TO_ACTIVE) {
-		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Selected to Active",		 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Selected to Active",		 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, (R_BAKE_TO_ACTIVE|R_BAKE_OSA), "");
 	} else {
-		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Selected to Active",		 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Selected to Active",		 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, (R_BAKE_TO_ACTIVE|R_BAKE_OSA), "");
 	}
 	
 	uiDefBut(block, SEPR, 0, "",				0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
diff --git a/source/blender/src/header_node.c b/source/blender/src/header_node.c
index 2bd028766d1da30bb449aa9c3656a8353481c0cd..c23913bb97cec450d917c3a41de6b3b26f1ff373 100644
--- a/source/blender/src/header_node.c
+++ b/source/blender/src/header_node.c
@@ -756,8 +756,26 @@ void node_buttons(ScrArea *sa)
 	uiDefIconButI(block, ROW, B_REDR, ICON_TEXTURE_DEHLT, xco,2,XIC,YIC-2,
 				  &(snode->treetype), 2, 2, 0, 0, "Texture Nodes");
 	xco+= 2*XIC;
+	
 	uiBlockEndAlign(block);
 	
+	if(snode->treetype==NTREE_TEXTURE) {
+		
+		uiBlockBeginAlign(block);
+		uiDefIconButS(block, ROW, B_REDR, ICON_OBJECT, xco,2,XIC,YIC-2,
+					  &(snode->texfrom), 3, SNODE_TEX_OBJECT, 0, 0, "Texture Nodes from Object");
+		xco+= XIC;
+		uiDefIconButS(block, ROW, B_REDR, ICON_WORLD_DEHLT, xco,2,XIC,YIC-2,
+					  &(snode->texfrom), 3, SNODE_TEX_WORLD, 0, 0, "Texture Nodes from World");
+		xco+= XIC;
+		uiDefIconButS(block, ROW, B_REDR, ICON_TPAINT_DEHLT, xco,2,XIC,YIC-2,
+					  &(snode->texfrom), 3, SNODE_TEX_BRUSH, 0, 0, "Texture Nodes from Active Brush or Sculpt Data");
+		xco+= 2*XIC;
+		
+		uiBlockEndAlign(block);
+		
+	}
+	
 	/* find and set the context */
 	snode_set_context(snode);
 	
@@ -785,8 +803,9 @@ void node_buttons(ScrArea *sa)
 	else if(snode->treetype==NTREE_TEXTURE) {
 		if(snode->from) {
 			
+			/* can't use unlink etc here, code requires buttons context */
 			xco= std_libbuttons(block, xco, 0, 0, NULL, B_TEXBROWSE, ID_TE, 1, snode->id, snode->from, &(snode->menunr), 
-					   B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME, B_KEEPDATA);
+					   0, 0, 0, B_AUTOTEXNAME, B_KEEPDATA);
 			
 			if(snode->id) {
 				Tex *tx= (Tex *)snode->id;
diff --git a/source/blender/src/header_text.c b/source/blender/src/header_text.c
index 9268642db2f722c4c28e3b021624a4fd3ffa53e4..850b7d6cab11378ab09cb9b0ee03085e6eb17e97 100644
--- a/source/blender/src/header_text.c
+++ b/source/blender/src/header_text.c
@@ -74,6 +74,7 @@
 #include "BIF_toolbox.h"
 
 #include "BKE_global.h"
+#include "BKE_scene.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_sca.h"
@@ -173,6 +174,7 @@ void do_text_buttons(unsigned short event)
 			BPY_clear_bad_scriptlinks(text);
 			BPY_free_pyconstraint_links(text);
 			free_text_controllers(text);
+			free_dome_warp_text(text);
 #endif
 			unlink_text(text);
 			free_libblock(&G.main->text, text);
diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c
index 8171fe2e527e1ad89691050115c1f95731036b1f..6d72e434e67fe691cd16b484a7316bff24e25e5b 100644
--- a/source/blender/src/header_view3d.c
+++ b/source/blender/src/header_view3d.c
@@ -4123,8 +4123,6 @@ static uiBlock *view3d_edit_armaturemenu(void *arg_unused)
 
 static void do_view3d_pose_armature_transformmenu(void *arg, int event)
 {
-	Object *ob= OBACT;
-	
 	switch(event) {
 	case 0: /*	clear origin */
 		clear_object('o');
@@ -4139,9 +4137,7 @@ static void do_view3d_pose_armature_transformmenu(void *arg, int event)
 		clear_object('g');
 		break;
 	case 4: /* clear user transform */
-		rest_pose(ob->pose);
-		DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
-		BIF_undo_push("Pose, Clear User Transform");
+		pose_clear_user_transforms();
 		break;
 	}
 	allqueue(REDRAWVIEW3D, 0);
diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c
index 09666f4819d3e3c5b19000643a116acba9c19c18..86534438ba08d2e2a562904b2e6eac3ad339bde7 100644
--- a/source/blender/src/imagepaint.c
+++ b/source/blender/src/imagepaint.c
@@ -186,7 +186,7 @@ typedef struct ImagePaintPartialRedraw {
 // #define PROJ_BUCKET_CLONE_INIT	1<<1
 
 /* used for testing doubles, if a point is on a line etc */
-#define PROJ_GEOM_TOLERANCE 0.0002f
+#define PROJ_GEOM_TOLERANCE 0.00075f
 
 /* vert flags */
 #define PROJ_VERT_CULL 1
@@ -334,7 +334,7 @@ typedef struct UndoTile {
 typedef struct UndoElem {
 	struct UndoElem *next, *prev;
 	char name[MAXUNDONAME];
-	unsigned long undosize;
+	uintptr_t undosize;
 
 	ImBuf *ibuf;
 	ListBase tiles;
@@ -478,12 +478,12 @@ static void undo_imagepaint_push_begin(char *name)
 static void undo_imagepaint_push_end()
 {
 	UndoElem *uel;
-	unsigned long totmem, maxmem;
+	uintptr_t totmem, maxmem;
 
 	if(U.undomemory != 0) {
 		/* limit to maximum memory (afterwards, we can't know in advance) */
 		totmem= 0;
-		maxmem= ((unsigned long)U.undomemory)*1024*1024;
+		maxmem= ((uintptr_t)U.undomemory)*1024*1024;
 
 		uel= undobase.last;
 		while(uel) {
@@ -672,8 +672,8 @@ static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w
 static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
 {
 	/* use */
-	*x = (float)fmod(uv[0], 1.0f);
-	*y = (float)fmod(uv[1], 1.0f);
+	*x = (float)fmodf(uv[0], 1.0f);
+	*y = (float)fmodf(uv[1], 1.0f);
 	
 	if (*x < 0.0f) *x += 1.0f;
 	if (*y < 0.0f) *y += 1.0f;
@@ -707,9 +707,8 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float
 		Vec2Weightf(uv, tf->uv[0], tf->uv[2], tf->uv[3], w);
 	}
 	
-	ibuf = BKE_image_get_ibuf((Image *)tf->tpage, NULL); /* TODO - this may be slow, the only way around it is to have an ibuf index per face */
-	
-
+	ibuf = tf->tpage->ibufs.first; /* we must have got the imbuf before getting here */
+	if (!ibuf) return 0;
 	
 	if (interp) {
 		float x, y;
@@ -896,7 +895,7 @@ static int line_isect_y(const float p1[2], const float p2[2], const float y_leve
 		return ISECT_TRUE_P2;
 	}
 	
-	y_diff= fabs(p1[1]-p2[1]); /* yuck, horizontal line, we cant do much here */
+	y_diff= fabsf(p1[1]-p2[1]); /* yuck, horizontal line, we cant do much here */
 	
 	if (y_diff < 0.000001f) {
 		*x_isect = (p1[0]+p2[0]) * 0.5f;
@@ -929,7 +928,7 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve
 		return ISECT_TRUE_P2;
 	}
 	
-	x_diff= fabs(p1[0]-p2[0]); /* yuck, horizontal line, we cant do much here */
+	x_diff= fabsf(p1[0]-p2[0]); /* yuck, horizontal line, we cant do much here */
 	
 	if (x_diff < 0.000001) { /* yuck, vertical line, we cant do much here */
 		*y_isect = (p1[0]+p2[0]) * 0.5f;
@@ -956,11 +955,11 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve
 static int cmp_uv(const float vec2a[2], const float vec2b[2])
 {
 	/* if the UV's are not between 0.0 and 1.0 */
-	float xa = (float)fmod(vec2a[0], 1.0f);
-	float ya = (float)fmod(vec2a[1], 1.0f);
+	float xa = (float)fmodf(vec2a[0], 1.0f);
+	float ya = (float)fmodf(vec2a[1], 1.0f);
 	
-	float xb = (float)fmod(vec2b[0], 1.0f);
-	float yb = (float)fmod(vec2b[1], 1.0f);	
+	float xb = (float)fmodf(vec2b[0], 1.0f);
+	float yb = (float)fmodf(vec2b[1], 1.0f);	
 	
 	if (xa < 0.0f) xa += 1.0f;
 	if (ya < 0.0f) ya += 1.0f;
@@ -968,7 +967,7 @@ static int cmp_uv(const float vec2a[2], const float vec2b[2])
 	if (xb < 0.0f) xb += 1.0f;
 	if (yb < 0.0f) yb += 1.0f;
 	
-	return ((fabs(xa-xb) < PROJ_GEOM_TOLERANCE) && (fabs(ya-yb) < PROJ_GEOM_TOLERANCE)) ? 1:0;
+	return ((fabsf(xa-xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya-yb) < PROJ_GEOM_TOLERANCE)) ? 1:0;
 }
 
 
@@ -1107,7 +1106,7 @@ static float angleToLength(float angle)
 		return 1.0f;
 	}
 	else {
-		return fabs(1.0f / cos(angle * (M_PI/180.0f)));
+		return fabsf(1.0f / cosf(angle * (M_PI/180.0f)));
 	}
 }
 
@@ -1363,7 +1362,7 @@ float project_paint_uvpixel_mask(
 		ImBuf *ibuf_other;
 		const MTFace *tf_other = ps->dm_mtface_mask + face_index;
 		
-		if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) {
+		if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf(tf_other->tpage, NULL))) {
 			/* BKE_image_get_ibuf - TODO - this may be slow */
 			unsigned char rgba_ub[4];
 			float rgba_f[4];
@@ -1519,7 +1518,7 @@ static ProjPixel *project_paint_uvpixel_init(
 			ImBuf *ibuf_other;
 			const MTFace *tf_other = ps->dm_mtface_clone + face_index;
 			
-			if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) {
+			if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf(tf_other->tpage, NULL))) {
 				/* BKE_image_get_ibuf - TODO - this may be slow */
 				
 				if (ibuf->rect_float) {
@@ -1588,7 +1587,7 @@ static int line_clip_rect2f(
 {
 	/* first account for horizontal, then vertical lines */
 	/* horiz */
-	if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) {
+	if (fabsf(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) {
 		/* is the line out of range on its Y axis? */
 		if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
 			return 0;
@@ -1599,7 +1598,7 @@ static int line_clip_rect2f(
 		}
 		
 		
-		if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point  (or close to)*/
+		if (fabsf(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point  (or close to)*/
 			if (BLI_in_rctf(rect, l1[0], l1[1])) {
 				VECCOPY2D(l1_clip, l1);
 				VECCOPY2D(l2_clip, l2);
@@ -1616,7 +1615,7 @@ static int line_clip_rect2f(
 		CLAMP(l2_clip[0], rect->xmin, rect->xmax);
 		return 1;
 	}
-	else if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) {
+	else if (fabsf(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) {
 		/* is the line out of range on its X axis? */
 		if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
 			return 0;
@@ -1627,7 +1626,7 @@ static int line_clip_rect2f(
 			return 0;
 		}
 		
-		if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point  (or close to)*/
+		if (fabsf(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point  (or close to)*/
 			if (BLI_in_rctf(rect, l1[0], l1[1])) {
 				VECCOPY2D(l1_clip, l1);
 				VECCOPY2D(l2_clip, l2);
@@ -1921,7 +1920,7 @@ static void rect_to_uvspace_persp(
 }
 
 /* This works as we need it to but we can save a few steps and not use it */
-
+#if 0
 static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2])
 {
 	float v1[2], v2[2];
@@ -1931,6 +1930,7 @@ static float angle_2d_clockwise(const float p1[2], const float p2[2], const floa
 	
 	return -atan2(v1[0]*v2[1] - v1[1]*v2[0], v1[0]*v2[0]+v1[1]*v2[1]);
 }
+#endif
 
 #define ISECT_1 (1)
 #define ISECT_2 (1<<1)
@@ -1969,7 +1969,6 @@ static void project_bucket_clip_face(
 	const int flip = ((SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) > 0.0f) != (SIDE_OF_LINE(uv1co, uv2co, uv3co) > 0.0f));
 	
 	float bucket_bounds_ss[4][2];
-	float w[3];
 
 	/* get the UV space bounding box */
 	inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v1coSS[0], v1coSS[1]);
@@ -2040,6 +2039,7 @@ static void project_bucket_clip_face(
 		/* Maximum possible 6 intersections when using a rectangle and triangle */
 		float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
 		float v1_clipSS[2], v2_clipSS[2];
+		float w[3];
 		
 		/* calc center*/
 		float cent[2] = {0.0f, 0.0f};
@@ -2082,6 +2082,7 @@ static void project_bucket_clip_face(
 		
 		if ((*tot) < 3) { /* no intersections to speak of */
 			*tot = 0;
+			return;
 		}
 	
 		/* now we have all points we need, collect their angles and sort them clockwise */
@@ -2110,16 +2111,15 @@ static void project_bucket_clip_face(
 		for(i=0; i<(*tot); i++) {
 			v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
 			v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
-			isectVCosSS[i][2] = atan2(v1_clipSS[0]*v2_clipSS[1] - v1_clipSS[1]*v2_clipSS[0], v1_clipSS[0]*v2_clipSS[0]+v1_clipSS[1]*v2_clipSS[1]); 
+			isectVCosSS[i][2] = atan2f(v1_clipSS[0]*v2_clipSS[1] - v1_clipSS[1]*v2_clipSS[0], v1_clipSS[0]*v2_clipSS[0]+v1_clipSS[1]*v2_clipSS[1]); 
 		}
 		
 		if (flip)	qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort_flip);
 		else		qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort);
 		
-		
 		/* remove doubles */
 		/* first/last check */
-		if (fabs(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < PROJ_GEOM_TOLERANCE &&  fabs(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < PROJ_GEOM_TOLERANCE) {
+		if (fabsf(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < PROJ_GEOM_TOLERANCE &&  fabsf(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < PROJ_GEOM_TOLERANCE) {
 			(*tot)--;
 		}
 		
@@ -2134,8 +2134,8 @@ static void project_bucket_clip_face(
 		while (doubles==TRUE) {
 			doubles = FALSE;
 			for(i=1; i<(*tot); i++) {
-				if (fabs(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE &&
-					fabs(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE)
+				if (fabsf(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE &&
+					fabsf(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE)
 				{
 					int j;
 					for(j=i+1; j<(*tot); j++) {
@@ -2263,6 +2263,19 @@ int IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
 	
 	return 1;
 }
+static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot)
+{
+	int i;
+	int side = (SIDE_OF_LINE(uv[tot-1], uv[0], pt) > 0.0f);
+	
+	for (i=1; i<tot; i++) {
+		if ((SIDE_OF_LINE(uv[i-1], uv[i], pt) > 0.0f) != side)
+			return 0;
+		
+	}
+	
+	return 1;
+}
 
 /* One of the most important function for projectiopn painting, since it selects the pixels to be added into each bucket.
  * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
@@ -2306,6 +2319,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
 	float uv_clip[8][2];
 	int uv_clip_tot;
 	const short is_ortho = ps->is_ortho;
+	const short do_backfacecull = ps->do_backfacecull;
 	
 	vCo[0] = ps->dm_mvert[mf->v1].co;
 	vCo[1] = ps->dm_mvert[mf->v2].co;
@@ -2315,9 +2329,20 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
 	/* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
 	 * this is done so we can avoid offseting all the pixels by 0.5 which causes
 	 * problems when wrapping negative coords */
-	xhalfpx = 0.5f / ibuf_xf;
-	yhalfpx = 0.5f / ibuf_yf;
-	
+	xhalfpx = (0.5f+   (PROJ_GEOM_TOLERANCE/3.0f)   ) / ibuf_xf;
+	yhalfpx = (0.5f+   (PROJ_GEOM_TOLERANCE/4.0f)   ) / ibuf_yf;
+	
+	/* Note about (PROJ_GEOM_TOLERANCE/x) above...
+	  Needed to add this offset since UV coords are often quads aligned to pixels.
+	  In this case pixels can be exactly between 2 triangles causing nasty
+	  artifacts.
+	  
+	  This workaround can be removed and painting will still work on most cases
+	  but since the first thing most people try is painting onto a quad- better make it work.
+	 */
+
+
+
 	tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx;
 	tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx;
 
@@ -2353,8 +2378,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
 		v1coSS = ps->screenCoords[ (*(&mf->v1 + i1)) ];
 		v2coSS = ps->screenCoords[ (*(&mf->v1 + i2)) ];
 		v3coSS = ps->screenCoords[ (*(&mf->v1 + i3)) ];
-
-
+		
 		/* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
 		project_bucket_clip_face(
 				is_ortho, bucket_bounds,
@@ -2362,8 +2386,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
 				uv1co, uv2co, uv3co,
 				uv_clip, &uv_clip_tot
 		);
-		
-		
+
 		/* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
 		/*
 		if (uv_clip_tot>6) {
@@ -2385,7 +2408,10 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
 					//uv[0] = (((float)x) + 0.5f) / ibuf->x;
 					uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */
 					
-					if (IsectPoly2Df(uv, uv_clip, uv_clip_tot)) {
+					/* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesnt work,
+					 * could check the poly direction but better to do this */
+					if(	(do_backfacecull		&& IsectPoly2Df(uv, uv_clip, uv_clip_tot)) ||
+						(do_backfacecull==0		&& IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot))) {
 						
 						has_x_isect = has_isect = 1;
 						
@@ -3030,7 +3056,7 @@ static void project_paint_begin(ProjPaintState *ps, short mval[2])
 	ps->buckets_x = (int)(ps->screen_width / (((float)ps->brush->size) / PROJ_BUCKET_BRUSH_DIV));
 	ps->buckets_y = (int)(ps->screen_height / (((float)ps->brush->size) / PROJ_BUCKET_BRUSH_DIV));
 	
-	printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y);
+	/* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
 	
 	/* really high values could cause problems since it has to allocate a few
 	 * (ps->buckets_x*ps->buckets_y) sized arrays  */
@@ -3203,7 +3229,7 @@ static void project_paint_begin(ProjPaintState *ps, short mval[2])
 				
 				image_index = BLI_linklist_index(image_LinkList, tf->tpage);
 				
-				if (image_index==-1 && BKE_image_get_ibuf((Image *)tf->tpage, NULL)) { /* MemArena dosnt have an append func */
+				if (image_index==-1 && BKE_image_get_ibuf(tf->tpage, NULL)) { /* MemArena dosnt have an append func */
 					BLI_linklist_append(&image_LinkList, tf->tpage);
 					image_index = ps->image_tot;
 					ps->image_tot++;
@@ -3225,10 +3251,10 @@ static void project_paint_begin(ProjPaintState *ps, short mval[2])
 	
 	for (node= image_LinkList, i=0; node; node= node->next, i++, projIma++) {
 		projIma->ima = node->link;
-		// calloced - projIma->touch = 0;
+		projIma->touch = 0;
 		projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL);
 		projIma->partRedrawRect =  BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
-		// calloced - memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+		memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
 	}
 	
 	/* we have built the array, discard the linked list */
@@ -3378,7 +3404,7 @@ static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
 
 static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot)
 {
-	int touch;
+	int touch= 0;
 	while (tot--) {
 		pr->x1 = MIN2(pr->x1, pr_other->x1);
 		pr->y1 = MIN2(pr->y1, pr_other->y1);
@@ -3506,6 +3532,7 @@ static void blend_color_mix(unsigned char *cp, const unsigned char *cp1, const u
 	cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
 	cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
 	cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
+	cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
 }
 
 static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2, const float fac)
@@ -3514,6 +3541,7 @@ static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2,
 	cp[0]= mfac*cp1[0] + fac*cp2[0];
 	cp[1]= mfac*cp1[1] + fac*cp2[1];
 	cp[2]= mfac*cp1[2] + fac*cp2[2];
+	cp[3]= mfac*cp1[3] + fac*cp2[3];
 }
 
 static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask)
@@ -3550,8 +3578,8 @@ static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, floa
 	
 	if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0)
 		return; 
-	
-	((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend);
+	/* ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
+	blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha*mask*255));
 	BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
 } 
 
@@ -3564,7 +3592,8 @@ static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, fl
 		return;
 	
 	IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_smear, projPixel->pixel.f_pt);
-	((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend);
+	/* (ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
+	blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, rgba_smear, (rgba_ub), (int)(alpha*mask*255)); 
 	BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
 }
 
@@ -3675,12 +3704,12 @@ static void *do_projectpaint_thread(void *ph_v)
 			
 			projPixel = (ProjPixel *)node->link;
 			
-			/*dist = Vec2Lenf(projPixel->projCoSS, pos);*/ /* correct but uses a sqrt */
+			/*dist = Vec2Lenf(projPixel->projCoSS, pos);*/ /* correct but uses a sqrtf */
 			dist_nosqrt = Vec2Lenf_nosqrt(projPixel->projCoSS, pos);
 			
-			/*if (dist < s->brush->size) {*/ /* correct but uses a sqrt */
+			/*if (dist < s->brush->size) {*/ /* correct but uses a sqrtf */
 			if (dist_nosqrt < brush_size_sqared) {
-				falloff = brush_sample_falloff_noalpha(ps->brush, sqrt(dist_nosqrt));
+				falloff = brush_sample_falloff_noalpha(ps->brush, sqrtf(dist_nosqrt));
 				if (falloff > 0.0f) {
 					if (ps->is_texbrush) {
 						brush_sample_tex(ps->brush, projPixel->projCoSS, rgba);
@@ -3769,10 +3798,9 @@ static void *do_projectpaint_thread(void *ph_v)
 			*projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
 		}
 		
-		for (node= smearPixels_f; node; node= node->next) { /* this wont run for a float image */
+		for (node= smearPixels_f; node; node= node->next) {
 			projPixel = node->link;
 			IMAPAINT_CHAR_RGBA_TO_FLOAT(projPixel->pixel.f_pt,  ((ProjPixelClone *)projPixel)->clonepx.ch);
-			node = node->next;
 		}
 		
 		BLI_memarena_free(smearArena);
@@ -4325,7 +4353,7 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho
 		) {
 			ImBuf *ibuf;
 			
-			newimage = (Image*)((s->me->mtface+newfaceindex)->tpage);
+			newimage = (s->me->mtface+newfaceindex)->tpage;
 			ibuf= BKE_image_get_ibuf(newimage, G.sima?&G.sima->iuser:NULL);
 
 			if(ibuf && ibuf->rect)
diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c
index 66a484eb90392384951027a072509cb2e9d6b0ff..db77d5960259b9fae73f6d80f3bcf5c8ff51d41a 100644
--- a/source/blender/src/meshtools.c
+++ b/source/blender/src/meshtools.c
@@ -650,9 +650,9 @@ static void mesh_octree_add_nodes(MocNode **basetable, float *co, float *offs, f
 	float fx, fy, fz;
 	int vx, vy, vz;
 	
-	if (isnan(co[0]) || !finite(co[0]) ||
-		isnan(co[1]) || !finite(co[1]) ||
-		isnan(co[2]) || !finite(co[2])
+	if (!finite(co[0]) ||
+		!finite(co[1]) ||
+		!finite(co[2])
 	) {
 		return;
 	}
@@ -869,9 +869,9 @@ EditVert *editmesh_get_x_mirror_vert(Object *ob, float *co)
 	intptr_t poinval;
 	
 	/* ignore nan verts */
-	if (isnan(co[0]) || !finite(co[0]) ||
-		isnan(co[1]) || !finite(co[1]) ||
-		isnan(co[2]) || !finite(co[2])
+	if (!finite(co[0]) ||
+		!finite(co[1]) ||
+		!finite(co[2])
 	   )
 		return NULL;
 	
diff --git a/source/blender/src/parametrizer.c b/source/blender/src/parametrizer.c
index 1cf796d86bcc6b3f8c11f6eb36cb330a3ae69d31..feb774b604a9afa340e21072730e3bbc6f67d8d5 100644
--- a/source/blender/src/parametrizer.c
+++ b/source/blender/src/parametrizer.c
@@ -4125,8 +4125,8 @@ void param_smooth_area(ParamHandle *handle)
 	}
 }
  
-void param_pack(ParamHandle *handle)
-{
+void param_pack(ParamHandle *handle, float margin)
+{	
 	/* box packing variables */
 	boxPack *boxarray, *box;
 	float tot_width, tot_height, scale;
@@ -4134,6 +4134,7 @@ void param_pack(ParamHandle *handle)
 	PChart *chart;
 	int i, unpacked=0;
 	float trans[2];
+	double area= 0.0;
 	
 	PHandle *phandle = (PHandle*)handle;
 	
@@ -4146,6 +4147,7 @@ void param_pack(ParamHandle *handle)
 	/* we may not use all these boxes */
 	boxarray = MEM_mallocN( phandle->ncharts*sizeof(boxPack), "boxPack box");
 	
+	
 	for (i = 0; i < phandle->ncharts; i++) {
 		chart = phandle->charts[i];
 		
@@ -4166,6 +4168,32 @@ void param_pack(ParamHandle *handle)
 		box->w =  chart->u.pack.size[0] + trans[0];
 		box->h =  chart->u.pack.size[1] + trans[1];
 		box->index = i; /* warning this index skips PCHART_NOPACK boxes */
+		
+		if(margin>0.0f)
+			area += sqrt(box->w*box->h);
+	}	
+	
+	if(margin>0.0f) {
+		/* multiply the margin by the area to give pradictable results not dependant on UV scale,
+		 * ...Without using the area running pack multiple times also gives a bad feedback loop.
+		 * multiply by 0.1 so the margin value from the UI can be from 0.0 to 1.0 but not give a massive margin */
+		margin = (margin*(float)area) * 0.1;
+		unpacked= 0;
+		for (i = 0; i < phandle->ncharts; i++) {
+			chart = phandle->charts[i];
+			
+			if (chart->flag & PCHART_NOPACK) {
+				unpacked++;
+				continue;
+			}
+			
+			box = boxarray+(i-unpacked);
+			trans[0] = margin * area;
+			trans[1] = margin * area;
+			p_chart_uv_translate(chart, trans);
+			box->w += (margin * area) *2;
+			box->h += (margin * area) *2;
+		}
 	}
 	
 	boxPack2D(boxarray, phandle->ncharts-unpacked, &tot_width, &tot_height);
diff --git a/source/blender/src/parametrizer.h b/source/blender/src/parametrizer.h
index c468b8d62c557511db5c53e1bcb6416959be562a..f1454ee3865ce2043b298cefe03bdbed42c90936 100644
--- a/source/blender/src/parametrizer.h
+++ b/source/blender/src/parametrizer.h
@@ -73,7 +73,7 @@ void param_smooth_area(ParamHandle *handle);
 
 /* Packing */
 
-void param_pack(ParamHandle *handle);
+void param_pack(ParamHandle *handle, float margin);
 
 /* Average area for all charts */
 
diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c
index c2a2be80e89ce98e206207e394cf47e4f763975c..551aca0cc91f0c7b6a69c3876c3e5f0226dc7c81 100644
--- a/source/blender/src/poseobject.c
+++ b/source/blender/src/poseobject.c
@@ -568,9 +568,7 @@ void pose_special_editmenu(void)
 		pose_clear_paths(ob);
 	}
 	else if(nr==5) {
-		rest_pose(ob->pose);
-		DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
-		BIF_undo_push("Clear User Transform Pose");
+		pose_clear_user_transforms();
 	}
 	else if(nr==6) {
 		pose_relax();
@@ -1740,4 +1738,37 @@ void pose_flipquats(void)
 	autokeyframe_pose_cb_func(ob, TFM_ROTATION, 0);
 }
 
+/* Restore selected pose-bones to 'action'-defined pose */
+void pose_clear_user_transforms (void) 
+{
+	Object *ob = OBACT;
+	bArmature *arm= ob->data;
+	bPoseChannel *pchan;
+	
+	if (ob->pose == NULL)
+		return;
+	
+	/* if the object has an action, restore pose to the pose defined by the action by clearing pose on selected bones */
+	if (ob->action) {
+		/* find selected bones */
+		for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+			if (pchan->bone && (pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
+				/* just clear the BONE_UNKEYED flag, allowing this bone to get overwritten by actions again */
+				pchan->bone->flag &= ~BONE_UNKEYED;
+			}
+		}
+		
+		/* clear pose locking flag 
+		 *	- this will only clear the user-defined pose in the selected bones, where BONE_UNKEYED has been cleared
+		 */
+		ob->pose->flag |= POSE_DO_UNLOCK;
+	}
+	else {
+		/* no action, so restore entire pose to rest pose (cannot restore only selected bones) */
+		rest_pose(ob->pose);
+	}
+	
+	DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+	BIF_undo_push("Clear User Transform");
+}
 
diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c
index 8dfa32d48c8049feaabbab414732d098579eed43..21be4b2cf494101f1278f8a6b30d6a75df5fb4c1 100644
--- a/source/blender/src/previewrender.c
+++ b/source/blender/src/previewrender.c
@@ -243,6 +243,13 @@ void BIF_preview_changed(short id_code)
 					allqueue(REDRAWVIEW3D, 0);
 				}
 			}
+
+			for(ma=G.main->mat.first; ma; ma=ma->id.next) {
+				if(ma->gpumaterial.first) {
+					GPU_material_free(ma);
+					allqueue(REDRAWVIEW3D, 0);
+				}
+			}
 		} else if(OBACT) {
 			Object *ob = OBACT;
 
diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c
index 67cfce55907e67bc031d9f2ac961d4621e7379d4..f49071be63c8c1139c4d1bb526cdb4c47cd7dc4c 100644
--- a/source/blender/src/reeb.c
+++ b/source/blender/src/reeb.c
@@ -2695,7 +2695,7 @@ static float cotan_weight(float *v1, float *v2, float *v3)
 	return Inpf(a, b)/clen;
 }
 
-void addTriangle(EditVert *v1, EditVert *v2, EditVert *v3, long e1, long e2, long e3)
+void addTriangle(EditVert *v1, EditVert *v2, EditVert *v3, int e1, int e2, int e3)
 {
 	/* Angle opposite e1 */
 	float t1= cotan_weight(v1->co, v2->co, v3->co) / e2;
diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c
index ca4cf4df61439c2cab6d0c24d0e7ef508c734a30..cd42c3d40851961342b7782eaaf3e78e7a3a8a77 100644
--- a/source/blender/src/sequence.c
+++ b/source/blender/src/sequence.c
@@ -1672,6 +1672,41 @@ static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown)
 	
 }
 
+static void check_limiter_refcount(const char * func, TStripElem *se)
+{
+	if (se && se->ibuf) {
+		int refcount = IMB_cache_limiter_get_refcount(se->ibuf);
+		if (refcount != 1) {
+			/* can happen on complex pipelines */
+			if (refcount > 1 && (G.f & G_DEBUG) == 0) {
+				return;
+			}
+
+			fprintf(stderr, 
+				"sequencer: (ibuf) %s: "
+				"suspicious memcache "
+				"limiter refcount: %d\n", func,	refcount);
+		}
+	}
+}
+
+static void check_limiter_refcount_comp(const char * func, TStripElem *se)
+{
+	if (se && se->ibuf_comp) {
+		int refcount = IMB_cache_limiter_get_refcount(se->ibuf_comp);
+		if (refcount != 1) {
+			/* can happen on complex pipelines */
+			if (refcount > 1 && (G.f & G_DEBUG) == 0) {
+				return;
+			}
+			fprintf(stderr, 
+				"sequencer: (ibuf comp) %s: "
+				"suspicious memcache "
+				"limiter refcount: %d\n", func,	refcount);
+		}
+	}
+}
+
 static TStripElem* do_build_seq_array_recursively(
 	ListBase *seqbasep, int cfra, int chanshown);
 
@@ -1686,18 +1721,23 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra,
 
 	if(seq->type == SEQ_META) {
 		TStripElem * meta_se = 0;
+		int use_preprocess = FALSE;
 		use_limiter = FALSE;
 
 		if (!build_proxy_run && se->ibuf == 0) {
 			se->ibuf = seq_proxy_fetch(seq, cfra);
 			if (se->ibuf) {
 				use_limiter = TRUE;
+				use_preprocess = TRUE;
 			}
 		}
 
 		if(!se->ibuf && seq->seqbase.first) {
 			meta_se = do_build_seq_array_recursively(
 				&seq->seqbase, seq->start + se->nr, 0);
+
+			check_limiter_refcount("do_build_seq_ibuf: for META",
+					       meta_se);
 		}
 
 		se->ok = STRIPELEM_OK;
@@ -1719,14 +1759,17 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra,
 				se->ibuf = i;
 
 				use_limiter = TRUE;
+				use_preprocess = TRUE;
 			}
+		} else if (se->ibuf) {
+			use_limiter = TRUE;
 		}
 		if (meta_se) {
 			free_metastrip_imbufs(
 				&seq->seqbase, seq->start + se->nr, 0);
 		}
 
-		if (use_limiter) {
+		if (use_preprocess) {
 			input_preprocess(seq, se, cfra);
 		}
 	} else if(seq->type & SEQ_EFFECT) {
@@ -1761,6 +1804,12 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra,
 			if (!se->ibuf) {
 				se->ibuf= IMB_loadiffname(
 					name, IB_rect);
+				/* we don't need both (speed reasons)! */
+				if (se->ibuf &&
+				    se->ibuf->rect_float && se->ibuf->rect) {
+					imb_freerectImBuf(se->ibuf);
+				}
+
 				copy_to_ibuf_still(seq, se);
 			}
 			
@@ -1791,6 +1840,13 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra,
 				if(seq->anim) {
 					IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
 					se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs);
+					/* we don't need both (speed reasons)! */
+					if (se->ibuf 
+					    && se->ibuf->rect_float 
+					    && se->ibuf->rect) {
+						imb_freerectImBuf(se->ibuf);
+					}
+
 				}
 				copy_to_ibuf_still(seq, se);
 			}
@@ -1961,6 +2017,7 @@ static void do_effect_seq_recursively(Sequence * seq, TStripElem *se, int cfra)
 	if (se->se3 && se->se3->ibuf) {
 		IMB_cache_limiter_unref(se->se3->ibuf);
 	}
+	check_limiter_refcount("do_effect_seq_recursively", se);
 }
 
 static TStripElem* do_build_seq_recursively_impl(Sequence * seq, int cfra)
@@ -1976,6 +2033,7 @@ static TStripElem* do_build_seq_recursively_impl(Sequence * seq, int cfra)
 			do_build_seq_ibuf(seq, se, cfra, FALSE);
 		}
 	}
+	check_limiter_refcount("do_build_seq_recursively_impl", se);
 	return se;
 }
 
@@ -2087,6 +2145,8 @@ static TStripElem* do_handle_speed_effect(Sequence * seq, int cfra)
 	if (se2 && se2->ibuf)
 		IMB_cache_limiter_unref(se2->ibuf);
 
+	check_limiter_refcount("do_handle_speed_effect", se);
+
 	return se;
 }
 
@@ -2104,20 +2164,17 @@ static TStripElem* do_handle_speed_effect(Sequence * seq, int cfra)
 
 static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra)
 {
+	TStripElem* se;
 	if (seq->type == SEQ_SPEED) {
-		return do_handle_speed_effect(seq, cfra);
+		se = do_handle_speed_effect(seq, cfra);
 	} else {
-		return do_build_seq_recursively_impl(seq, cfra);
+		se = do_build_seq_recursively_impl(seq, cfra);
 	}
-}
 
-/* Bug: 18209
- * when dragging the mouse over a metastrip, on mouse-up for some unknown
- * reason in some cases the metastrips TStripElem->ibuf->rect is NULL,
- * This should be fixed but I had a look and couldnt work out why its
- * happening so for now workaround with a NULL check - campbell */
+	check_limiter_refcount("do_build_seq_recursively", se);
 
-#define SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND
+	return se;
+}
 
 static TStripElem* do_build_seq_array_recursively(
 	ListBase *seqbasep, int cfra, int chanshown)
@@ -2180,6 +2237,9 @@ static TStripElem* do_build_seq_array_recursively(
 				se->ibuf_comp = IMB_allocImBuf(
 					(short)seqrectx, (short)seqrecty, 
 					32, IB_rect, 0);
+				IMB_cache_limiter_insert(se->ibuf_comp);
+				IMB_cache_limiter_ref(se->ibuf_comp);
+				IMB_cache_limiter_touch(se->ibuf_comp);
 			}
 			break;
 		}
@@ -2210,6 +2270,9 @@ static TStripElem* do_build_seq_array_recursively(
 				se->ibuf_comp = IMB_allocImBuf(
 					(short)seqrectx, (short)seqrecty, 
 					32, IB_rect, 0);
+				IMB_cache_limiter_insert(se->ibuf_comp);
+				IMB_cache_limiter_ref(se->ibuf_comp);
+				IMB_cache_limiter_touch(se->ibuf_comp);
 			}
 			break;
 		case 1:
@@ -2228,6 +2291,9 @@ static TStripElem* do_build_seq_array_recursively(
 				se->ibuf = IMB_allocImBuf(
 					(short)seqrectx, (short)seqrecty, 
 					32, IB_rect, 0);
+				IMB_cache_limiter_insert(se->ibuf);
+				IMB_cache_limiter_ref(se->ibuf);
+				IMB_cache_limiter_touch(se->ibuf);
 			}
 			if (i == 0) {
 				se->ibuf_comp = se->ibuf;
@@ -2286,13 +2352,6 @@ static TStripElem* do_build_seq_array_recursively(
 				IMB_rect_from_float(se2->ibuf);
 			}
 			
-#ifdef SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND
-			if (se2->ibuf->rect==NULL && se2->ibuf->rect_float==NULL) {
-				printf("ERROR: sequencer se2->ibuf missing buffer\n");
-			} else if (se1->ibuf && se1->ibuf->rect==NULL && se1->ibuf->rect_float==NULL) {
-				printf("ERROR: sequencer se1->ibuf missing buffer\n");
-			} else {
-#endif
 			/* bad hack, to fix crazy input ordering of 
 			   those two effects */
 
@@ -2314,10 +2373,6 @@ static TStripElem* do_build_seq_array_recursively(
 					   se2->ibuf_comp);
 			}
 			
-#ifdef SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND
-			}
-#endif
-			
 			IMB_cache_limiter_insert(se2->ibuf_comp);
 			IMB_cache_limiter_ref(se2->ibuf_comp);
 			IMB_cache_limiter_touch(se2->ibuf_comp);
@@ -2372,6 +2427,8 @@ static ImBuf *give_ibuf_seq_impl(int rectx, int recty, int cfra, int chanshown)
 		return 0;
 	}
 
+	check_limiter_refcount_comp("give_ibuf_seq_impl", se);
+
 	return se->ibuf_comp;
 }
 
@@ -2389,6 +2446,8 @@ ImBuf *give_ibuf_seq_direct(int rectx, int recty, int cfra,
 		return 0;
 	}
 
+	check_limiter_refcount("give_ibuf_seq_direct", se);
+
 	if (se->ibuf) {
 		IMB_cache_limiter_unref(se->ibuf);
 	}
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index c6510b780d8725490f45306cda4b7aa6e720a5ae..8ff2b526ae8878837ecb5cff7e7a57e3b12c2f90 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -5023,7 +5023,7 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 		
 		switch(event) {
 		case LEFTMOUSE:
-			if(sseq->mainb==0 && view2dmove(event)==0) {
+			if(sseq->mainb==0 || view2dmove(event)==0) {
 				
 				first= 1;		
 				set_special_seq_update(1);
diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c
index 76f315cde04e405eae092f2979e8eee3cb3de883..2eab0bc973056614381a42389b1afd698320d40c 100644
--- a/source/blender/src/transform_conversions.c
+++ b/source/blender/src/transform_conversions.c
@@ -120,6 +120,7 @@
 
 #include "BSE_view.h"
 #include "BSE_drawipo.h"
+#include "BSE_drawnla.h"		// nla_filter()
 #include "BSE_edit.h"
 #include "BSE_editipo.h"
 #include "BSE_editipo_types.h"
@@ -3132,6 +3133,10 @@ static void createTransNlaData(TransInfo *t)
 	
 	/* Ensure that partial selections result in beztriple selections */
 	for (base=G.scene->base.first; base; base=base->next) {
+		/* only consider if visible */
+		if (nla_filter(base) == 0)
+			continue;
+		
 		/* Check object ipos */
 		i= count_ipo_keys(base->object->ipo, side, (float)CFRA);
 		if (i) base->flag |= BA_HAS_RECALC_OB;
@@ -3197,6 +3202,10 @@ static void createTransNlaData(TransInfo *t)
 	/* build the transdata structure */
 	td= t->data;
 	for (base=G.scene->base.first; base; base=base->next) {
+		/* only consider if visible */
+		if (nla_filter(base) == 0)
+			continue;
+		
 		/* Manipulate object ipos */
 		/* 	- no scaling of keyframe times is allowed here  */
 		td= IpoToTransData(td, base->object->ipo, NULL, side, (float)CFRA);
diff --git a/source/blender/src/unwrapper.c b/source/blender/src/unwrapper.c
index 612e068c6cade9f80c78fd6bbd26b56e7e642ddf..fadc087df656be245feff9b68ebd171d0df7f676 100644
--- a/source/blender/src/unwrapper.c
+++ b/source/blender/src/unwrapper.c
@@ -327,7 +327,7 @@ void unwrap_lscm(short seamcut)
 	param_lscm_solve(handle);
 	param_lscm_end(handle);
 	
-	param_pack(handle);
+	param_pack(handle, G.scene->toolsettings->uvcalc_margin);
 
 	param_flush(handle);
 
@@ -442,7 +442,7 @@ void pack_charts_tface_uv(void)
 	if(!EM_texFaceCheck()) return;
 
 	handle = construct_param_handle(em, 1, 0, 1);
-	param_pack(handle);
+	param_pack(handle, G.scene->toolsettings->uvcalc_margin);
 	param_flush(handle);
 	param_delete(handle);
 
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index a20913bc714439869d3886fa69f9d593c567b78a..f31a68365fb3f0b11f73060b3d3e089b144329de 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -173,14 +173,14 @@ IF(WIN32)
     ADD_CUSTOM_COMMAND(TARGET blender
       POST_BUILD
       MAIN_DEPENDENCY blender
-      COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avcodec-51.dll\" \"${TARGETDIR}\\\"
+      COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avcodec-52.dll\" \"${TARGETDIR}\\\"
       COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avformat-52.dll\" \"${TARGETDIR}\\\"
       COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avdevice-52.dll\" \"${TARGETDIR}\\\"
-      COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avutil-49.dll\" \"${TARGETDIR}\\\"
+      COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avutil-50.dll\" \"${TARGETDIR}\\\"
       COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libfaac-0.dll\" \"${TARGETDIR}\\\"
-      COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libfaad-0.dll\" \"${TARGETDIR}\\\"
+      COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libfaad-2.dll\" \"${TARGETDIR}\\\"
       COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libmp3lame-0.dll\" \"${TARGETDIR}\\\"
-      COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libx264-59.dll\" \"${TARGETDIR}\\\"
+      COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libx264-67.dll\" \"${TARGETDIR}\\\"
       COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\swscale-0.dll\" \"${TARGETDIR}\\\"
       COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\xvidcore.dll\" \"${TARGETDIR}\\\"
     )
diff --git a/source/creator/SConscript b/source/creator/SConscript
index 505b69b8e6da5f454a54824aab4db0de8d4aee5b..1aed0de370ec6cd0ea8bb6fdd282bcdab428ca1f 100644
--- a/source/creator/SConscript
+++ b/source/creator/SConscript
@@ -12,22 +12,24 @@ incs += ' ' + env['BF_OPENGL_INC']
 
 defs = []
 if env['WITH_BF_QUICKTIME']:
-    incs += ' ' + env['BF_QUICKTIME_INC']
-    defs.append('WITH_QUICKTIME')
+	incs += ' ' + env['BF_QUICKTIME_INC']
+	defs.append('WITH_QUICKTIME')
 
 if env['WITH_BF_BINRELOC']:
-    incs += ' ../../extern/binreloc/include'
-    defs.append('WITH_BINRELOC')
+	incs += ' ../../extern/binreloc/include'
+	defs.append('WITH_BINRELOC')
 
 if env['WITH_BF_OPENEXR']:
-    defs.append('WITH_OPENEXR')
+	defs.append('WITH_OPENEXR')
 
 if not env['WITH_BF_SDL']:
 	defs.append('DISABLE_SDL')
 
 if env['WITH_BF_PYTHON']:
-    incs += ' ../blender/python'
+	incs += ' ../blender/python'
+	if env['BF_DEBUG']:
+		defs.append('_DEBUG')
 else:
-    defs.append('DISABLE_PYTHON')
+	defs.append('DISABLE_PYTHON')
 
 env.BlenderLib ( libname = 'blender_creator', sources = Split(sources), includes = Split(incs), defines = defs, libtype='core', priority = 1 )
diff --git a/source/creator/buildinfo.c b/source/creator/buildinfo.c
index e25caa34f461be4716114fcd96425e7a2ecac19c..cef98915d795931806f7be0cddf7b3957d3aa8c0 100644
--- a/source/creator/buildinfo.c
+++ b/source/creator/buildinfo.c
@@ -33,11 +33,11 @@
 
 #ifdef BUILD_DATE
 #ifndef WIN32
-char * build_date=BUILD_DATE;
-char * build_time=BUILD_TIME;
-char * build_rev=BUILD_REV;
-char * build_platform=BUILD_PLATFORM;
-char * build_type=BUILD_TYPE;
+const char * build_date=BUILD_DATE;
+const char * build_time=BUILD_TIME;
+const char * build_rev=BUILD_REV;
+const char * build_platform=BUILD_PLATFORM;
+const char * build_type=BUILD_TYPE;
 #else
 #include "winbuildinfo.h"
 #endif
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 5c0ca9e07ff77a3a960f912a6611dace7b62ff21..2b542b13c9781e3c38d947061a2d0c800ea2c5cb 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -538,6 +538,15 @@ int main(int argc, char **argv)
 		BLI_where_is_temp( btempdir, 1 ); /* call after loading the .B.blend so we can read U.tempdir */
 
 #ifndef DISABLE_SDL
+#if (defined(WIN32) || defined(WIN64))
+#if defined(FREE_WINDOWS)
+		putenv("SDL_VIDEODRIVER=dummy");
+#else
+		_putenv_s("SDL_VIDEODRIVER", "dummy");
+#endif
+#else
+		setenv("SDL_VIDEODRIVER", "dummy", 1); /* initializing the video driver can cause crashes on some systems - Campbell */
+#endif
 #ifdef __linux__
 		/* On linux the default SDL driver dma often would not play
 		 * use alsa if none is set */
diff --git a/source/darwin/Makefile b/source/darwin/Makefile
index f7b513fc2146200ff26765a61d0829786790bfc8..e2c6f75483112c8340b17cd6ab995e26fb038044 100644
--- a/source/darwin/Makefile
+++ b/source/darwin/Makefile
@@ -50,7 +50,7 @@ ifeq ($(APPLICATION), blender)
 	@cp -R $(NANBLENDERHOME)/bin/.blender $(DIR)/bin/$(APPLICATION).app/Contents/MacOS
 	@cp -R $(NANBLENDERHOME)/release/scripts $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/
 endif
-	@echo "---> removing CVS directories and Mac hidden files from distribution"
+	@echo "---> removing SVN directories and Mac hidden files from distribution"
 	@find $(DIR)/bin/$(APPLICATION).app -name CVS -prune -exec rm -rf {} \;
 	@find $(DIR)/bin/$(APPLICATION).app -name .DS_Store -exec rm -f {} \;
-	@find $(DIR)/bin/$(APPLICATION).app -name .svn -exec rm -rf {} \;
+	@find $(DIR)/bin/$(APPLICATION).app -name .svn -prune -exec rm -rf {} \;
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 0cc574d762d1444b2a5d549257569a5c6f6ee3e8..641938253b77cebd529364bd89279b1cfabc4d20 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -280,6 +280,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
 				if(blenderdata) {
 					BLI_strncpy(G.sce, blenderdata->name, sizeof(G.sce));
 					BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
+					setGamePythonPath(G.sce);
 				}
 			}
 			// else forget it, we can't find it
@@ -309,12 +310,11 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
 		{
 			int startFrame = blscene->r.cfra;
 			ketsjiengine->SetGame2IpoMode(game2ipo,startFrame);
+			
+			// Quad buffered needs a special window.
+			if (blscene->r.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
+				rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) blscene->r.stereomode);
 		}
-
-
-		// Quad buffered needs a special window.
-		if (blscene->r.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
-			rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) blscene->r.stereomode);
 		
 		if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
 		{
@@ -357,7 +357,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
 				blscene);
 			
 			// some python things
-			PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest);
+			PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest, blenderdata);
 			ketsjiengine->SetPythonDictionary(dictionaryobject);
 			initRasterizer(rasterizer, canvas);
 			PyObject *gameLogic = initGameLogic(ketsjiengine, startscene);
@@ -368,6 +368,8 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
 			initGameKeys();
 			initPythonConstraintBinding();
 			initMathutils();
+			initGeometry();
+			initBGL();
 #ifdef WITH_FFMPEG
 			initVideoTexture();
 #endif
@@ -531,7 +533,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
 		SND_DeviceManager::Unsubscribe();
 	
 	} while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
-
+	
+	Py_DECREF(pyGlobalDict);
+	
 	if (bfd) BLO_blendfiledata_free(bfd);
 
 	BLI_strncpy(G.sce, oldsce, sizeof(G.sce));
@@ -660,7 +664,7 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
 				blscene);
 
 			// some python things
-			PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest);
+			PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest, blenderdata);
 			ketsjiengine->SetPythonDictionary(dictionaryobject);
 			initRasterizer(rasterizer, canvas);
 			PyObject *gameLogic = initGameLogic(ketsjiengine, startscene);
@@ -668,6 +672,8 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
 			initGameKeys();
 			initPythonConstraintBinding();
 			initMathutils();
+			initGeometry();
+			initBGL();
 #ifdef WITH_FFMPEG
 			initVideoTexture();
 #endif
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp
index 4b79438061086fb2b2ca97da270ec61c43131ab1..877a0d39acfebe2e7046d4fff823c5f52f68c6dd 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp
@@ -74,7 +74,7 @@ void	KX_BlenderKeyboardDevice::NextFrame()
 	
 	// now convert justpressed keyevents into regular (active) keyevents
 	int previousTable = 1-m_currentTable;
-	for (int keyevent= KX_BEGINKEY; keyevent< KX_ENDKEY;keyevent++)
+	for (int keyevent= KX_BEGINKEY; keyevent<= KX_ENDKEY;keyevent++)
 	{
 		SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][keyevent];
 		if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
@@ -100,7 +100,7 @@ bool	KX_BlenderKeyboardDevice::ConvertBlenderEvent(unsigned short incode,short v
 	KX_EnumInputs kxevent = this->ToNative(incode);
 
 	// only process it, if it's a key
-	if (kxevent >= KX_BEGINKEY && kxevent < KX_ENDKEY)
+	if (kxevent >= KX_BEGINKEY && kxevent <= KX_ENDKEY)
 	{
 		int previousTable = 1-m_currentTable;
 
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
index 9dbda3f195bc2f77d55960409bbd435341e4c684..17d1bf65ca4499dd62989cd6a9f1cd778f918fc2 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
@@ -68,8 +68,8 @@ void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty)
 {
 	m_clientobject = NULL;
 	m_lastlightlayer = -1;
-	m_lastlighting = false;
 	m_lastauxinfo = NULL;
+	m_lastlighting = true; /* force disable in DisableOpenGLLights() */
 	DisableOpenGLLights();
 }
 
@@ -295,7 +295,7 @@ void KX_BlenderRenderTools::RenderText(
 	RAS_IPolyMaterial* polymat,
 	float v1[3], float v2[3], float v3[3], float v4[3], int glattrib)
 {
-	STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
+	const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
 	
 	const unsigned int flag = polymat->GetFlag();
 	struct MTFace* tface = 0;
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index 943bb68f6f28c16c298cf306671ee3d58644a0bf..145cb1f22dec797762b98e9f894e709d29d69010 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -66,9 +66,9 @@ BL_ActionActuator::~BL_ActionActuator()
 		game_free_pose(m_blendpose);
 }
 
-void BL_ActionActuator::ProcessReplica(){
-//	bPose *oldpose = m_pose;
-//	bPose *oldbpose = m_blendpose;
+void BL_ActionActuator::ProcessReplica()
+{
+	SCA_IActuator::ProcessReplica();
 	
 	m_pose = NULL;
 	m_blendpose = NULL;
@@ -84,9 +84,6 @@ void BL_ActionActuator::SetBlendTime (float newtime){
 CValue* BL_ActionActuator::GetReplica() {
 	BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName());
 	replica->ProcessReplica();
-	
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
 	return replica;
 }
 
@@ -159,16 +156,9 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
 	// maybe there are events for us in the queue !
 	if (frame)
 	{
-		for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++)
-		{
-			if ((*i)->GetNumber() == 0.0f)
-				bNegativeEvent = true;
-			else
-				bPositiveEvent= true;
-			(*i)->Release();
-		
-		}
-		m_events.clear();
+		bNegativeEvent = m_negevent;
+		bPositiveEvent = m_posevent;
+		RemoveAllEvents();
 		
 		if (bPositiveEvent)
 			m_flag |= ACT_FLAG_ACTIVE;
@@ -423,8 +413,7 @@ const char BL_ActionActuator::GetAction_doc[] =
 "getAction()\n"
 "\tReturns a string containing the name of the current action.\n";
 
-PyObject* BL_ActionActuator::PyGetAction(PyObject* self, 
-										 PyObject* args, 
+PyObject* BL_ActionActuator::PyGetAction(PyObject* args, 
 										 PyObject* kwds) {
 	ShowDeprecationWarning("getAction()", "the action property");
 
@@ -439,8 +428,7 @@ const char BL_ActionActuator::GetProperty_doc[] =
 "getProperty()\n"
 "\tReturns the name of the property to be used in FromProp mode.\n";
 
-PyObject* BL_ActionActuator::PyGetProperty(PyObject* self, 
-										   PyObject* args, 
+PyObject* BL_ActionActuator::PyGetProperty(PyObject* args, 
 										   PyObject* kwds) {
 	ShowDeprecationWarning("getProperty()", "the property property");
 
@@ -456,8 +444,7 @@ const char BL_ActionActuator::GetFrameProperty_doc[] =
 "getFrameProperty()\n"
 "\tReturns the name of the property, that is set to the current frame number.\n";
 
-PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* self, 
-										   PyObject* args, 
+PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* args, 
 										   PyObject* kwds) {
 	ShowDeprecationWarning("getFrameProperty()", "the frameProperty property");
 
@@ -473,8 +460,7 @@ const char BL_ActionActuator::GetFrame_doc[] =
 "getFrame()\n"
 "\tReturns the current frame number.\n";
 
-PyObject* BL_ActionActuator::PyGetFrame(PyObject* self, 
-										PyObject* args, 
+PyObject* BL_ActionActuator::PyGetFrame(PyObject* args, 
 										PyObject* kwds) {
 	ShowDeprecationWarning("getFrame()", "the frame property");
 
@@ -490,8 +476,7 @@ const char BL_ActionActuator::GetEnd_doc[] =
 "getEnd()\n"
 "\tReturns the last frame of the action.\n";
 
-PyObject* BL_ActionActuator::PyGetEnd(PyObject* self, 
-									  PyObject* args, 
+PyObject* BL_ActionActuator::PyGetEnd(PyObject* args, 
 									  PyObject* kwds) {
 	ShowDeprecationWarning("getEnd()", "the end property");
 
@@ -507,8 +492,7 @@ const char BL_ActionActuator::GetStart_doc[] =
 "getStart()\n"
 "\tReturns the starting frame of the action.\n";
 
-PyObject* BL_ActionActuator::PyGetStart(PyObject* self, 
-										PyObject* args, 
+PyObject* BL_ActionActuator::PyGetStart(PyObject* args, 
 										PyObject* kwds) {
 	ShowDeprecationWarning("getStart()", "the start property");
 
@@ -525,8 +509,7 @@ const char BL_ActionActuator::GetBlendin_doc[] =
 "\tReturns the number of interpolation animation frames to be\n"
 "\tgenerated when this actuator is triggered.\n";
 
-PyObject* BL_ActionActuator::PyGetBlendin(PyObject* self, 
-										  PyObject* args, 
+PyObject* BL_ActionActuator::PyGetBlendin(PyObject* args, 
 										  PyObject* kwds) {
 	ShowDeprecationWarning("getBlendin()", "the blendin property");
 
@@ -543,8 +526,7 @@ const char BL_ActionActuator::GetPriority_doc[] =
 "\tReturns the priority for this actuator.  Actuators with lower\n"
 "\tPriority numbers will override actuators with higher numbers.\n";
 
-PyObject* BL_ActionActuator::PyGetPriority(PyObject* self, 
-										   PyObject* args, 
+PyObject* BL_ActionActuator::PyGetPriority(PyObject* args, 
 										   PyObject* kwds) {
 	ShowDeprecationWarning("getPriority()", "the priority property");
 
@@ -565,15 +547,14 @@ const char BL_ActionActuator::SetAction_doc[] =
 "\t               unchanged.  If reset is not specified, the timer will"
 "\t	              be reset.\n";
 
-PyObject* BL_ActionActuator::PySetAction(PyObject* self, 
-										 PyObject* args, 
+PyObject* BL_ActionActuator::PySetAction(PyObject* args, 
 										 PyObject* kwds) {
 	ShowDeprecationWarning("setAction()", "the action property");
 
 	char *string;
 	int	reset = 1;
 
-	if (PyArg_ParseTuple(args,"s|i",&string, &reset))
+	if (PyArg_ParseTuple(args,"s|i:setAction",&string, &reset))
 	{
 		bAction *action;
 		
@@ -601,14 +582,13 @@ const char BL_ActionActuator::SetStart_doc[] =
 "setStart(start)\n"
 "\t - start     : Specifies the starting frame of the animation.\n";
 
-PyObject* BL_ActionActuator::PySetStart(PyObject* self, 
-										PyObject* args, 
+PyObject* BL_ActionActuator::PySetStart(PyObject* args, 
 										PyObject* kwds) {
 	ShowDeprecationWarning("setStart()", "the start property");
 
 	float start;
 	
-	if (PyArg_ParseTuple(args,"f",&start))
+	if (PyArg_ParseTuple(args,"f:setStart",&start))
 	{
 		m_startframe = start;
 	}
@@ -624,14 +604,13 @@ const char BL_ActionActuator::SetEnd_doc[] =
 "setEnd(end)\n"
 "\t - end       : Specifies the ending frame of the animation.\n";
 
-PyObject* BL_ActionActuator::PySetEnd(PyObject* self, 
-									  PyObject* args, 
+PyObject* BL_ActionActuator::PySetEnd(PyObject* args, 
 									  PyObject* kwds) {
 	ShowDeprecationWarning("setEnd()", "the end property");
 
 	float end;
 	
-	if (PyArg_ParseTuple(args,"f",&end))
+	if (PyArg_ParseTuple(args,"f:setEnd",&end))
 	{
 		m_endframe = end;
 	}
@@ -648,14 +627,13 @@ const char BL_ActionActuator::SetBlendin_doc[] =
 "\t - blendin   : Specifies the number of frames of animation to generate\n"
 "\t               when making transitions between actions.\n";
 
-PyObject* BL_ActionActuator::PySetBlendin(PyObject* self, 
-										  PyObject* args, 
+PyObject* BL_ActionActuator::PySetBlendin(PyObject* args, 
 										  PyObject* kwds) {
 	ShowDeprecationWarning("setBlendin()", "the blendin property");
 
 	float blendin;
 	
-	if (PyArg_ParseTuple(args,"f",&blendin))
+	if (PyArg_ParseTuple(args,"f:setBlendin",&blendin))
 	{
 		m_blendin = blendin;
 	}
@@ -673,14 +651,13 @@ const char BL_ActionActuator::SetBlendtime_doc[] =
 "\t               used when generating transitions between actions.  This\n"
 "\t               parameter must be in the range from 0.0 to 1.0.\n";
 
-PyObject* BL_ActionActuator::PySetBlendtime(PyObject* self, 
-										  PyObject* args, 
+PyObject* BL_ActionActuator::PySetBlendtime(PyObject* args, 
 										  PyObject* kwds) {
 	ShowDeprecationWarning("setBlendtime()", "the blendtime property");
 
 	float blendframe;
 	
-	if (PyArg_ParseTuple(args,"f",&blendframe))
+	if (PyArg_ParseTuple(args,"f:setBlendtime",&blendframe))
 	{
 		m_blendframe = blendframe * m_blendin;
 		if (m_blendframe<0)
@@ -702,14 +679,13 @@ const char BL_ActionActuator::SetPriority_doc[] =
 "\t               priority numbers will override actuators with higher\n"
 "\t               numbers.\n";
 
-PyObject* BL_ActionActuator::PySetPriority(PyObject* self, 
-										   PyObject* args, 
+PyObject* BL_ActionActuator::PySetPriority(PyObject* args, 
 										   PyObject* kwds) {
 	ShowDeprecationWarning("setPriority()", "the priority property");
 
 	int priority;
 	
-	if (PyArg_ParseTuple(args,"i",&priority))
+	if (PyArg_ParseTuple(args,"i:setPriority",&priority))
 	{
 		m_priority = priority;
 	}
@@ -725,14 +701,13 @@ const char BL_ActionActuator::SetFrame_doc[] =
 "setFrame(frame)\n"
 "\t - frame     : Specifies the new current frame for the animation\n";
 
-PyObject* BL_ActionActuator::PySetFrame(PyObject* self, 
-										PyObject* args, 
+PyObject* BL_ActionActuator::PySetFrame(PyObject* args, 
 										PyObject* kwds) {
 	ShowDeprecationWarning("setFrame()", "the frame property");
 
 	float frame;
 	
-	if (PyArg_ParseTuple(args,"f",&frame))
+	if (PyArg_ParseTuple(args,"f:setFrame",&frame))
 	{
 		m_localtime = frame;
 		if (m_localtime<m_startframe)
@@ -753,14 +728,13 @@ const char BL_ActionActuator::SetProperty_doc[] =
 "\t - prop      : A string specifying the property name to be used in\n"
 "\t               FromProp playback mode.\n";
 
-PyObject* BL_ActionActuator::PySetProperty(PyObject* self, 
-										   PyObject* args, 
+PyObject* BL_ActionActuator::PySetProperty(PyObject* args, 
 										   PyObject* kwds) {
 	ShowDeprecationWarning("setProperty()", "the property property");
 
 	char *string;
 	
-	if (PyArg_ParseTuple(args,"s",&string))
+	if (PyArg_ParseTuple(args,"s:setProperty",&string))
 	{
 		m_propname = string;
 	}
@@ -776,14 +750,13 @@ const char BL_ActionActuator::SetFrameProperty_doc[] =
 "setFrameProperty(prop)\n"
 "\t - prop      : A string specifying the property of the frame set up update.\n";
 
-PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* self, 
-										   PyObject* args, 
+PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* args, 
 										   PyObject* kwds) {
 	ShowDeprecationWarning("setFrameProperty()", "the frameProperty property");
 
 	char *string;
 	
-	if (PyArg_ParseTuple(args,"s",&string))
+	if (PyArg_ParseTuple(args,"s:setFrameProperty",&string))
 	{
 		m_framepropname = string;
 	}
@@ -795,12 +768,11 @@ PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* self,
 }
 
 /*
-PyObject* BL_ActionActuator::PyGetChannel(PyObject* self, 
-										   PyObject* args, 
+PyObject* BL_ActionActuator::PyGetChannel(PyObject* args, 
 										   PyObject* kwds) {
 	char *string;
 	
-	if (PyArg_ParseTuple(args,"s",&string))
+	if (PyArg_ParseTuple(args,"s:getChannel",&string))
 	{
 		m_propname = string;
 	}
@@ -816,8 +788,7 @@ PyObject* BL_ActionActuator::PyGetChannel(PyObject* self,
 const char BL_ActionActuator::GetType_doc[] =
 "getType()\n"
 "\tReturns the operation mode of the actuator.\n";
-PyObject* BL_ActionActuator::PyGetType(PyObject* self,
-                                       PyObject* args, 
+PyObject* BL_ActionActuator::PyGetType(PyObject* args, 
                                        PyObject* kwds) {
 	ShowDeprecationWarning("getType()", "the type property");
 
@@ -829,14 +800,13 @@ const char BL_ActionActuator::SetType_doc[] =
 "setType(mode)\n"
 "\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
 "\tSet the operation mode of the actuator.\n";
-PyObject* BL_ActionActuator::PySetType(PyObject* self,
-                                       PyObject* args,
+PyObject* BL_ActionActuator::PySetType(PyObject* args,
                                        PyObject* kwds) {
 	ShowDeprecationWarning("setType()", "the type property");
 
 	short typeArg;
                                                                                                              
-    if (!PyArg_ParseTuple(args, "h", &typeArg)) {
+    if (!PyArg_ParseTuple(args, "h:setType", &typeArg)) {
         return NULL;
     }
 
@@ -854,13 +824,13 @@ PyObject* BL_ActionActuator::PySetType(PyObject* self,
 	Py_RETURN_NONE;
 }
 
-PyObject* BL_ActionActuator::PyGetContinue(PyObject* self) {
+PyObject* BL_ActionActuator::PyGetContinue() {
 	ShowDeprecationWarning("getContinue()", "the continue property");
 
     return PyInt_FromLong((long)(m_end_reset==0));
 }
 
-PyObject* BL_ActionActuator::PySetContinue(PyObject* self, PyObject* value) {
+PyObject* BL_ActionActuator::PySetContinue(PyObject* value) {
 	ShowDeprecationWarning("setContinue()", "the continue property");
 
 	int param = PyObject_IsTrue( value );
@@ -894,7 +864,7 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
 	int row,col;
 	int	mode = 0;	/* 0 for bone space, 1 for armature/world space */
 	
-	if (!PyArg_ParseTuple(args,"sO|i", &string, &pylist, &mode))
+	if (!PyArg_ParseTuple(args,"sO|i:setChannel", &string, &pylist, &mode))
 		return NULL;
 	
 	if (pylist->ob_type == &CListValue::Type)
@@ -965,12 +935,17 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
 /* ------------------------------------------------------------------------- */
 
 PyTypeObject BL_ActionActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"BL_ActionActuator",
-		sizeof(BL_ActionActuator),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -1025,61 +1000,60 @@ PyAttributeDef BL_ActionActuator::Attributes[] = {
 	KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ActionActuator, m_startframe),
 	KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ActionActuator, m_endframe),
 	KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ActionActuator, m_blendin),
+	KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ActionActuator, pyattr_get_action, pyattr_set_action),
 	KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority),
 	KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame),
 	KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ActionActuator, m_propname),
 	KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ActionActuator, m_framepropname),
-	KX_PYATTRIBUTE_BOOL_RW("continue", BL_ActionActuator, m_end_reset),
+	KX_PYATTRIBUTE_BOOL_RW("useContinue", BL_ActionActuator, m_end_reset),
 	KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime),
 	KX_PYATTRIBUTE_SHORT_RW_CHECK("type",0,100,false,BL_ActionActuator,m_playtype,CheckType),
 	{ NULL }	//Sentinel
 };
 
 PyObject* BL_ActionActuator::py_getattro(PyObject *attr) {
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "action"))
-		return PyString_FromString(m_action->id.name+2);
-
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* BL_ActionActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int BL_ActionActuator::py_setattro(PyObject *attr, PyObject* value) {
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "action"))
-	{
-		if (!PyString_Check(value))
-		{
-			PyErr_SetString(PyExc_ValueError, "expected a string");
-			return 1;
-		}
+	py_setattro_up(SCA_IActuator);
+}
 
-		STR_String val = PyString_AsString(value);
-		
-		if (val == "")
-		{
-			m_action = NULL;
-			return 0;
-		}
 
-		bAction *action;
-		
-		action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val);
-		
+PyObject* BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
+	return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
+}
+
+int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
+	
+	if (!PyString_Check(value))
+	{
+		PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, expected the string name of the action");
+		return -1;
+	}
 
+	bAction *action= NULL;
+	STR_String val = PyString_AsString(value);
+	
+	if (val != "")
+	{
+		action= (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val);
 		if (!action)
 		{
-			PyErr_SetString(PyExc_ValueError, "action not found!");
+			PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, action not found!");
 			return 1;
 		}
-
-		m_action = action;
-		return 0;
 	}
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
-}
\ No newline at end of file
+	
+	self->SetAction(action);
+	return 0;
+
+}
diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h
index 7160dd4dad0a9cc82acb56a823ab9cead0bcfe3d..b3c15c08f506cc62a607c0105df67b952e78e9bc 100644
--- a/source/gameengine/Converter/BL_ActionActuator.h
+++ b/source/gameengine/Converter/BL_ActionActuator.h
@@ -81,6 +81,9 @@ public:
 	virtual void ProcessReplica();
 	
 	void SetBlendTime (float newtime);
+	
+	bAction*	GetAction() { return m_action; }
+	void		SetAction(bAction* act) { m_action= act; }
 
 	//Deprecated ----->
 	KX_PYMETHOD_DOC(BL_ActionActuator,SetAction);
@@ -111,8 +114,12 @@ public:
 	KX_PYMETHOD_DOC(BL_ActionActuator,setChannel);
 
 	virtual PyObject* py_getattro(PyObject* attr);
+	virtual PyObject*		py_getattro_dict();
 	virtual int py_setattro(PyObject* attr, PyObject* value);
 
+	static PyObject*	pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
 	/* attribute check */
 	static int CheckFrame(void *self, const PyAttributeDef*)
 	{
@@ -148,11 +155,11 @@ public:
 			case ACT_ACTION_FROM_PROP:
 				return 0;
 			default:
-				PyErr_SetString(PyExc_ValueError, "invalid type supplied");
+				PyErr_SetString(PyExc_ValueError, "Action Actuator, invalid play type supplied");
 				return 1;
 		}
-
 	}
+	
 protected:
 
 	void SetStartTime(float curtime);
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index d2001212f7d63a9ffbf14a00e3a081e27fb3fdf8..b00b493193ddad0e185b507fb0b4e42035876819 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -70,20 +70,17 @@ BL_ArmatureObject::BL_ArmatureObject(
 CValue* BL_ArmatureObject::GetReplica()
 {
 	BL_ArmatureObject* replica = new BL_ArmatureObject(*this);
-	
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-
-	ProcessReplica(replica);
+	replica->ProcessReplica();
 	return replica;
 }
 
-void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica)
+void BL_ArmatureObject::ProcessReplica()
 {
-	KX_GameObject::ProcessReplica(replica);
+	bPose *pose= m_pose;
+	KX_GameObject::ProcessReplica();
 
-	replica->m_pose = NULL;
-	game_copy_pose(&replica->m_pose, m_pose);
+	m_pose = NULL;
+	game_copy_pose(&m_pose, pose);
 }
 
 BL_ArmatureObject::~BL_ArmatureObject()
diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h
index d68e37d9e37dd13ca0638a14836a951d7262ec1e..d5402cfd12671f7b25e965a35215e69ff4c186fd 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.h
+++ b/source/gameengine/Converter/BL_ArmatureObject.h
@@ -45,7 +45,7 @@ class BL_ArmatureObject : public KX_GameObject
 public:
 	double GetLastFrame ();
 	short GetActivePriority();
-	virtual void ProcessReplica(BL_ArmatureObject *replica);
+	virtual void ProcessReplica();
 	class BL_ActionActuator * GetActiveAction();
 	
 	BL_ArmatureObject(
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index d74243b0eb09cbb9cf9a08dfefe36421463d1c0e..7d0bbbe107c54466d70644346fb47b8cb450392c 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -90,6 +90,7 @@
 #include "BKE_object.h"
 #include "BKE_scene.h"
 #include "BL_SkinMeshObject.h"
+#include "BL_ModifierDeformer.h"
 #include "BL_ShapeDeformer.h"
 #include "BL_SkinDeformer.h"
 #include "BL_MeshDeformer.h"
@@ -164,7 +165,11 @@ extern "C" {
 
 // defines USE_ODE to choose physics engine
 #include "KX_ConvertPhysicsObject.h"
-
+#ifdef USE_BULLET
+#include "CcdPhysicsEnvironment.h"
+#include "CcdGraphicController.h"
+#endif
+#include "KX_MotionState.h"
 
 // This file defines relationships between parents and children
 // in the game engine.
@@ -313,7 +318,8 @@ typedef struct MTF_localLayer
 }MTF_localLayer;
 
 // ------------------------------------
-BL_Material* ConvertMaterial(
+bool ConvertMaterial(
+	BL_Material *material,
 	Material *mat, 
 	MTFace* tface,  
 	const char *tfaceName,
@@ -324,9 +330,7 @@ BL_Material* ConvertMaterial(
 	MTF_localLayer *layers,
 	bool glslmat)
 {
-	//this needs some type of manager
-	BL_Material *material = new BL_Material();
-
+	material->Initialize();
 	int numchan =	-1, texalpha = 0;
 	bool validmat	= (mat!=0);
 	bool validface	= (tface!=0);
@@ -337,6 +341,7 @@ BL_Material* ConvertMaterial(
 	
 	material->IdMode = DEFAULT_BLENDER;
 	material->glslmat = (validmat)? glslmat: false;
+	material->materialindex = mface->mat_nr;
 
 	// --------------------------------
 	if(validmat) {
@@ -598,10 +603,7 @@ BL_Material* ConvertMaterial(
 
 	if( validface ) {
 
-		material->ras_mode |= !( 
-			(mface->flag & ME_HIDE)	||
-			(tface->mode & TF_INVISIBLE)
-			)?POLY_VIS:0;
+		material->ras_mode |= (tface->mode & TF_INVISIBLE)?0:POLY_VIS;
 
 		material->transp = tface->transp;
 		material->tile	= tface->tile;
@@ -717,7 +719,7 @@ BL_Material* ConvertMaterial(
 
 	material->tface		= tface;
 	material->material	= mat;
-	return material;
+	return true;
 }
 
 
@@ -746,7 +748,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 	}
 
 	// Determine if we need to make a skinned mesh
-	if (mesh->dvert || mesh->key || ((blenderobj->gameflag & OB_SOFT_BODY) != 0)) 
+	if (mesh->dvert || mesh->key || ((blenderobj->gameflag & OB_SOFT_BODY) != 0) || BL_ModifierDeformer::HasCompatibleDeformer(blenderobj))
 	{
 		meshobj = new BL_SkinMeshObject(mesh, lightlayer);
 		skinMesh = true;
@@ -778,6 +780,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 
 	meshobj->SetName(mesh->id.name);
 	meshobj->m_sharedvertex_map.resize(totvert);
+	RAS_IPolyMaterial* polymat = NULL;
+	STR_String imastr;
+	// These pointers will hold persistent material structure during the conversion
+	// to avoid countless allocation/deallocation of memory.
+	BL_Material* bl_mat = NULL;
+	KX_BlenderMaterial* kx_blmat = NULL;
+	KX_PolygonMaterial* kx_polymat = NULL;
 
 	for (int f=0;f<totface;f++,mface++)
 	{
@@ -839,8 +848,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 	
 		{
 			bool visible = true;
-			RAS_IPolyMaterial* polymat = NULL;
-			BL_Material *bl_mat = NULL;
+			bool twoside = false;
 
 			if(converter->GetMaterials()) {
 				/* do Blender Multitexture and Blender GLSL materials */
@@ -848,13 +856,14 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 				MT_Point2 uv[4];
 
 				/* first is the BL_Material */
-				bl_mat = ConvertMaterial(ma, tface, tfaceName, mface, mcol,
+				if (!bl_mat)
+					bl_mat = new BL_Material();
+				ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol,
 					lightlayer, blenderobj, layers, converter->GetGLSLMaterials());
 
-				bl_mat->material_index =  (int)mface->mat_nr;
-
 				visible = ((bl_mat->ras_mode & POLY_VIS)!=0);
 				collider = ((bl_mat->ras_mode & COLLIDER)!=0);
+				twoside = ((bl_mat->mode & TF_TWOSIDE)!=0);
 
 				/* vertex colors and uv's were stored in bl_mat temporarily */
 				bl_mat->GetConversionRGB(rgb);
@@ -870,12 +879,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 				uv22 = uv[2]; uv23 = uv[3];
 				
 				/* then the KX_BlenderMaterial */
-				polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer);
+				if (kx_blmat == NULL)
+					kx_blmat = new KX_BlenderMaterial();
+
+				kx_blmat->Initialize(scene, bl_mat, skinMesh, lightlayer);
+				polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat);
 			}
 			else {
 				/* do Texture Face materials */
 				Image* bima = (tface)? (Image*)tface->tpage: NULL;
-				STR_String imastr =  (tface)? (bima? (bima)->id.name : "" ) : "";
+				imastr =  (tface)? (bima? (bima)->id.name : "" ) : "";
 		
 				char transp=0;
 				short mode=0, tile=0;
@@ -894,7 +907,8 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 					tile = tface->tile;
 					mode = tface->mode;
 					
-					visible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE));
+					visible = !(tface->mode & TF_INVISIBLE);
+					twoside = ((tface->mode & TF_TWOSIDE)!=0);
 					
 					uv0.setValue(tface->uv[0]);
 					uv1.setValue(tface->uv[1]);
@@ -952,9 +966,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 				bool alpha = (transp == TF_ALPHA || transp == TF_ADD);
 				bool zsort = (mode & TF_ALPHASORT)? alpha: 0;
 
-				polymat = new KX_PolygonMaterial(imastr, ma,
+				if (kx_polymat == NULL)
+					kx_polymat = new KX_PolygonMaterial();
+				kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr,
 					tile, tilexrep, tileyrep, 
 					mode, transp, alpha, zsort, lightlayer, tface, (unsigned int*)mcol);
+				polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat);
 	
 				if (ma) {
 					polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec;
@@ -979,15 +996,17 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 				converter->RegisterPolyMaterial(polymat);
 				if(converter->GetMaterials()) {
 					converter->RegisterBlenderMaterial(bl_mat);
+					// the poly material has been stored in the bucket, next time we must create a new one
+					bl_mat = NULL;
+					kx_blmat = NULL;
+				} else {
+					// the poly material has been stored in the bucket, next time we must create a new one
+					kx_polymat = NULL;
 				}
 			} else {
-				// delete the material objects since they are no longer needed
 				// from now on, use the polygon material from the material bucket
-				delete polymat;
-				if(converter->GetMaterials()) {
-					delete bl_mat;
-				}
 				polymat = bucket->GetPolyMaterial();
+				// keep the material pointers, they will be reused for next face
 			}
 						 
 			int nverts = (mface->v4)? 4: 3;
@@ -995,6 +1014,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 
 			poly->SetVisible(visible);
 			poly->SetCollider(collider);
+			poly->SetTwoside(twoside);
 			//poly->SetEdgeCode(mface->edcode);
 
 			meshobj->AddVertex(poly,0,pt0,uv0,uv20,tan0,rgb0,no0,flat,mface->v1);
@@ -1030,7 +1050,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
 		delete []layers;
 	
 	dm->release(dm);
-
+	// cleanup material
+	if (bl_mat)
+		delete bl_mat;
+	if (kx_blmat)
+		delete kx_blmat;
+	if (kx_polymat)
+		delete kx_polymat;
 	return meshobj;
 }
 
@@ -1099,6 +1125,10 @@ static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blendero
 	shapeProps->m_do_fh     = (blenderobject->gameflag & OB_DO_FH) != 0; 
 	shapeProps->m_do_rot_fh = (blenderobject->gameflag & OB_ROT_FH) != 0;
 	
+//	velocity clamping XXX
+	shapeProps->m_clamp_vel_min = blenderobject->min_vel;
+	shapeProps->m_clamp_vel_max = blenderobject->max_vel;
+	
 	return shapeProps;
 }
 
@@ -1116,6 +1146,7 @@ static float my_boundbox_mesh(Mesh *me, float *loc, float *size)
 	BoundBox *bb;
 	MT_Point3 min, max;
 	float mloc[3], msize[3];
+	float radius=0.0f, vert_radius, *co;
 	int a;
 	
 	if(me->bb==0) me->bb= (struct BoundBox *)MEM_callocN(sizeof(BoundBox), "boundbox");
@@ -1128,7 +1159,15 @@ static float my_boundbox_mesh(Mesh *me, float *loc, float *size)
 	
 	mvert= me->mvert;
 	for(a=0; a<me->totvert; a++, mvert++) {
-		DO_MINMAX(mvert->co, min, max);
+		co= mvert->co;
+		
+		/* bounds */
+		DO_MINMAX(co, min, max);
+		
+		/* radius */
+		vert_radius= co[0]*co[0] + co[1]*co[1] + co[2]*co[2];
+		if (vert_radius > radius)
+			radius= vert_radius;
 	}
 		
 	if(me->totvert) {
@@ -1154,13 +1193,6 @@ static float my_boundbox_mesh(Mesh *me, float *loc, float *size)
 	bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
 	bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
 
-	float radius = 0;
-	for (a=0, mvert = me->mvert; a < me->totvert; a++, mvert++)
-	{
-		float vert_radius = MT_Vector3(mvert->co).length2();
-		if (vert_radius > radius)
-			radius = vert_radius;
-	} 
 	return sqrt(radius);
 }
 		
@@ -1265,8 +1297,43 @@ static void my_get_local_bounds(Object *ob, float *center, float *size)
 //////////////////////////////////////////////////////
 
 
-
-
+void BL_CreateGraphicObjectNew(KX_GameObject* gameobj,
+							   const MT_Point3& localAabbMin,
+							   const MT_Point3& localAabbMax,
+							   KX_Scene* kxscene,
+							   bool isActive,
+							   e_PhysicsEngine physics_engine)
+{
+	if (gameobj->GetMeshCount() > 0) 
+	{
+		switch (physics_engine)
+		{
+#ifdef USE_BULLET
+		case UseBullet:
+			{
+				CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
+				assert(env);
+				PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+				CcdGraphicController* ctrl = new CcdGraphicController(env, motionstate);
+				gameobj->SetGraphicController(ctrl);
+				ctrl->setNewClientInfo(gameobj->getClientInfo());
+				ctrl->setLocalAabb(localAabbMin, localAabbMax);
+				if (isActive) {
+					// add first, this will create the proxy handle
+					env->addCcdGraphicController(ctrl);
+					// update the mesh if there is a deformer, this will also update the bounding box for modifiers
+					RAS_Deformer* deformer = gameobj->GetDeformer();
+					if (deformer)
+						deformer->UpdateBuckets();
+				}
+			}
+			break;
+#endif
+		default:
+			break;
+		}
+	}
+}
 
 void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
 						 struct Object* blenderobject,
@@ -1371,6 +1438,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
 			objprop.m_soft_kAHR= blenderobject->bsoft->kAHR;			/* Anchors hardness [0,1] */
 			objprop.m_soft_collisionflags= blenderobject->bsoft->collisionflags;	/* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */
 			objprop.m_soft_numclusteriterations= blenderobject->bsoft->numclusteriterations;	/* number of iterations to refine collision clusters*/
+			objprop.m_soft_welding = blenderobject->bsoft->welding;		/* welding */
 		
 		} else
 		{
@@ -1410,6 +1478,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
 			objprop.m_soft_kAHR= 0.7f;
 			objprop.m_soft_collisionflags= OB_BSB_COL_SDF_RS + OB_BSB_COL_VF_SS;
 			objprop.m_soft_numclusteriterations= 16;
+			objprop.m_soft_welding = 0.f;
 		}
 	}
 
@@ -1487,6 +1556,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
 		objprop.m_dynamic_parent = parentgameobject;
 		//cannot be dynamic:
 		objprop.m_dyna = false;
+		objprop.m_softbody = false;
 		shapeprops->m_mass = 0.f;
 	}
 
@@ -1572,7 +1642,7 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l
 
 static KX_Camera *gamecamera_from_bcamera(Object *ob, KX_Scene *kxscene, KX_BlenderSceneConverter *converter) {
 	Camera* ca = static_cast<Camera*>(ob->data);
-	RAS_CameraData camdata(ca->lens, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, dof_camera(ob));
+	RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, dof_camera(ob));
 	KX_Camera *gamecamera;
 	
 	gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata);
@@ -1642,14 +1712,22 @@ static KX_GameObject *gameobject_from_blenderobject(
 		bool ignoreActivityCulling =  
 			((ob->gameflag2 & OB_NEVER_DO_ACTIVITY_CULLING)!=0);
 		gameobj->SetIgnoreActivityCulling(ignoreActivityCulling);
+		gameobj->SetOccluder((ob->gameflag & OB_OCCLUDER) != 0, false);
 	
 		// two options exists for deform: shape keys and armature
 		// only support relative shape key
 		bool bHasShapeKey = mesh->key != NULL && mesh->key->type==KEY_RELATIVE;
 		bool bHasDvert = mesh->dvert != NULL && ob->defbase.first;
 		bool bHasArmature = (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && bHasDvert);
+		bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(ob);
 
-		if (bHasShapeKey) {
+		if (bHasModifier) {
+			BL_ModifierDeformer *dcont = new BL_ModifierDeformer((BL_DeformableGameObject *)gameobj,
+																ob,	(BL_SkinMeshObject *)meshobj);
+			((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
+			if (bHasShapeKey && bHasArmature)
+				dcont->LoadShapeDrivers(ob->parent);
+		} else if (bHasShapeKey) {
 			// not that we can have shape keys without dvert! 
 			BL_ShapeDeformer *dcont = new BL_ShapeDeformer((BL_DeformableGameObject*)gameobj, 
 															ob, (BL_SkinMeshObject*)meshobj);
@@ -1859,10 +1937,14 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 	if (blenderscene->world) {
 		kxscene->SetActivityCulling( (blenderscene->world->mode & WO_ACTIVITY_CULLING) != 0);
 		kxscene->SetActivityCullingRadius(blenderscene->world->activityBoxRadius);
+		kxscene->SetDbvtCulling((blenderscene->world->mode & WO_DBVT_CULLING) != 0);
 	} else {
 		kxscene->SetActivityCulling(false);
+		kxscene->SetDbvtCulling(false);
 	}
-	
+	// no occlusion culling by default
+	kxscene->SetDbvtOcclusionRes(0);
+
 	int activeLayerBitInfo = blenderscene->lay;
 	
 	// templist to find Root Parents (object with no parents)
@@ -1954,7 +2036,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 			gameobj->NodeSetLocalPosition(pos);
 			gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
 			gameobj->NodeSetLocalScale(scale);
-			gameobj->NodeUpdateGS(0,true);
+			gameobj->NodeUpdateGS(0);
 			
 			BL_ConvertIpos(blenderobject,gameobj,converter);
 			BL_ConvertMaterialIpos(blenderobject, gameobj, converter);
@@ -1973,7 +2055,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 			if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame))
 			{
 				// blender has an additional 'parentinverse' offset in each object
-				SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks());
+				SG_Callbacks callback(NULL,NULL,NULL,KX_Scene::KX_ScenegraphUpdateFunc,KX_Scene::KX_ScenegraphRescheduleFunc);
+				SG_Node* parentinversenode = new SG_Node(NULL,kxscene,callback);
 			
 				// define a normal parent relationship for this node.
 				KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New();
@@ -2037,8 +2120,9 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 				objectlist->Add(gameobj->AddRef());
 				//tf.Add(gameobj->GetSGNode());
 				
-				gameobj->NodeUpdateGS(0,true);
-				gameobj->AddMeshUser();
+				gameobj->NodeUpdateGS(0);
+				//move to after finishing everything so that soft body deformer is included
+				//gameobj->AddMeshUser();
 		
 			}
 			else
@@ -2148,7 +2232,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 							gameobj->NodeSetLocalPosition(pos);
 							gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
 							gameobj->NodeSetLocalScale(scale);
-							gameobj->NodeUpdateGS(0,true);
+							gameobj->NodeUpdateGS(0);
 							
 							BL_ConvertIpos(blenderobject,gameobj,converter);
 							BL_ConvertMaterialIpos(blenderobject,gameobj, converter);	
@@ -2167,7 +2251,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 							if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame))
 							{
 								// blender has an additional 'parentinverse' offset in each object
-								SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks());
+								SG_Callbacks callback(NULL,NULL,NULL,KX_Scene::KX_ScenegraphUpdateFunc,KX_Scene::KX_ScenegraphRescheduleFunc);
+								SG_Node* parentinversenode = new SG_Node(NULL,kxscene,callback);
 							
 								// define a normal parent relationship for this node.
 								KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New();
@@ -2226,8 +2311,9 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 								objectlist->Add(gameobj->AddRef());
 								//tf.Add(gameobj->GetSGNode());
 								
-								gameobj->NodeUpdateGS(0,true);
-								gameobj->AddMeshUser();
+								gameobj->NodeUpdateGS(0);
+								//move to after finishing everything so that soft body deformer is included
+								//gameobj->AddMeshUser();
 							}
 							else
 							{
@@ -2309,7 +2395,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 			// Remove the child reference in the local list!
 			// Note: there may be descendents already if the children of the child were processed
 			//       by this loop before the child. In that case, we must remove the children also
-			CListValue* childrenlist = (CListValue*)childobj->PyGetChildrenRecursive(childobj);
+			CListValue* childrenlist = childobj->GetChildrenRecursive();
 			childrenlist->Add(childobj->AddRef());
 			for ( i=0;i<childrenlist->GetCount();i++)
 			{
@@ -2377,7 +2463,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 		if (gameobj->GetSGNode()->GetSGParent() == 0)
 		{
 			parentlist->Add(gameobj->AddRef());
-			gameobj->NodeUpdateGS(0,true);
+			gameobj->NodeUpdateGS(0);
 		}
 	}
 	
@@ -2414,6 +2500,27 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 		BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren);
 	}
 	
+	// create graphic controller for culling
+	if (kxscene->GetDbvtCulling())
+	{
+		bool occlusion = false;
+		for (i=0; i<sumolist->GetCount();i++)
+		{
+			KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
+			if (gameobj->GetMeshCount() > 0) 
+			{
+				MT_Point3 box[2];
+				gameobj->GetSGNode()->BBox().getmm(box, MT_Transform::Identity());
+				// box[0] is the min, box[1] is the max
+				bool isactive = objectlist->SearchValue(gameobj);
+				BL_CreateGraphicObjectNew(gameobj,box[0],box[1],kxscene,isactive,physics_engine);
+				if (gameobj->GetOccluder())
+					occlusion = true;
+			}
+		}
+		if (occlusion)
+			kxscene->SetDbvtOcclusionRes(blenderscene->world->occlusionRes);
+	}
 	
 	//set ini linearVel and int angularVel //rcruiz
 	if (converter->addInitFromFrame)
@@ -2503,8 +2610,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 	templist->Release();
 	sumolist->Release();	
 
-	int executePriority=0; /* incremented by converter routines */
-	
 	// convert global sound stuff
 
 	/* XXX, glob is the very very wrong place for this
@@ -2535,7 +2640,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 		struct Object* blenderobj = converter->FindBlenderObject(gameobj);
 		int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
 		bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
-		BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,executePriority, layerMask,isInActiveLayer,rendertools,converter);
+		BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,layerMask,isInActiveLayer,rendertools,converter);
 	}
 	for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
 	{
@@ -2543,7 +2648,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 		struct Object* blenderobj = converter->FindBlenderObject(gameobj);
 		int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
 		bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
-		BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,executePriority,layerMask,isInActiveLayer,converter);
+		BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,layerMask,isInActiveLayer,converter);
 	}
 	for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
 	{
@@ -2551,7 +2656,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 		struct Object* blenderobj = converter->FindBlenderObject(gameobj);
 		int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
 		bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
-		BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter);
+		BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,keydev,layerMask,isInActiveLayer,canvas,converter);
 		// set the init state to all objects
 		gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state);
 	}
@@ -2560,6 +2665,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 	{
 		KX_GameObject* gameobj = static_cast<KX_GameObject*>(objectlist->GetValue(i));
 		gameobj->ResetState();
+		gameobj->AddMeshUser();
 	}
 
 #endif //CONVERT_LOGIC
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp
index e2610d2b405f989fb278444492299cdf2cfc3eaa..a9d5b643fd4957468c3e489eb1f5ab22db369463 100644
--- a/source/gameengine/Converter/BL_DeformableGameObject.cpp
+++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp
@@ -41,27 +41,19 @@ BL_DeformableGameObject::~BL_DeformableGameObject()
 		delete m_pDeformer;		//	__NLA : Temporary until we decide where to put this
 }
 
-void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica)
+void BL_DeformableGameObject::ProcessReplica()
 {
-	BL_MeshDeformer *deformer;
-	KX_GameObject::ProcessReplica(replica);
-
-	if (m_pDeformer) {
-		deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(replica);
-		((BL_DeformableGameObject*)replica)->m_pDeformer = deformer;
-	}
+	KX_GameObject::ProcessReplica();
 
+	if (m_pDeformer)
+		m_pDeformer= (BL_MeshDeformer*)m_pDeformer->GetReplica();
 }
 
 CValue*		BL_DeformableGameObject::GetReplica()
 {
 
 	BL_DeformableGameObject* replica = new BL_DeformableGameObject(*this);//m_float,GetName());
-	
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-
-	ProcessReplica(replica);
+	replica->ProcessReplica();
 	return replica;
 }
 
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h
index 126a1fcb1e70857c0162094211b8933877c017ee..dbc89bd2a208dd01eceb3709427aff586a5c8e2c 100644
--- a/source/gameengine/Converter/BL_DeformableGameObject.h
+++ b/source/gameengine/Converter/BL_DeformableGameObject.h
@@ -62,7 +62,7 @@ public:
 			m_pDeformer->Relink (map);
 		KX_GameObject::Relink(map);
 	};
-	void ProcessReplica(KX_GameObject* replica);
+	void ProcessReplica();
 
 	BL_DeformableGameObject(Object* blendobj, void* sgReplicationInfo, SG_Callbacks callbacks) :
 		KX_GameObject(sgReplicationInfo,callbacks),
diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp
index 80112346c728be3a178fa0062ef8cfd0ec50d111..b6a59774636b24df6df623f58f7c241d2c2e1e9b 100644
--- a/source/gameengine/Converter/BL_MeshDeformer.cpp
+++ b/source/gameengine/Converter/BL_MeshDeformer.cpp
@@ -47,6 +47,7 @@
 
 #include "GEN_Map.h"
 #include "STR_HashedString.h"
+#include "BLI_arithb.h"
 
 bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*)
 {
@@ -166,6 +167,7 @@ void BL_MeshDeformer::RecalcNormals()
 				fnor[0]= n1[1]*n2[2] - n1[2]*n2[1];
 				fnor[1]= n1[2]*n2[0] - n1[0]*n2[2];
 				fnor[2]= n1[0]*n2[1] - n1[1]*n2[0];
+				Normalize(fnor);
 
 				/* add to vertices for smooth normals */
 				float *vn1 = m_transnors[v1.getOrigIndex()];
diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h
index 8de59c1cdf3331e58bafd5d05f22520166d39d97..d1754618df29f5851801bf1c970e50d5a35d2e49 100644
--- a/source/gameengine/Converter/BL_MeshDeformer.h
+++ b/source/gameengine/Converter/BL_MeshDeformer.h
@@ -64,7 +64,9 @@ public:
 	virtual void SetSimulatedTime(double time){};
 	virtual bool Apply(class RAS_IPolyMaterial *mat);
 	virtual bool Update(void){ return false; };
-	virtual	RAS_Deformer*	GetReplica(class KX_GameObject* replica){return NULL;};
+	virtual bool UpdateBuckets(void){ return false; };
+	virtual	RAS_Deformer*	GetReplica(){return NULL;};
+	virtual void ProcessReplica() { };
 	struct Mesh* GetMesh() { return m_bmesh; };
 	//	virtual void InitDeform(double time){};
 
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3c4c0c5caadd5f8cf4f3707e453fa1682e3e5487
--- /dev/null
+++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp
@@ -0,0 +1,165 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif //WIN32
+
+#include "MEM_guardedalloc.h"
+#include "BL_ModifierDeformer.h"
+#include "GEN_Map.h"
+#include "STR_HashedString.h"
+#include "RAS_IPolygonMaterial.h"
+#include "BL_SkinMeshObject.h"
+#include "PHY_IGraphicController.h"
+
+//#include "BL_ArmatureController.h"
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_modifier_types.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_key.h"
+#include "BKE_ipo.h"
+#include "MT_Point3.h"
+
+extern "C"{
+	#include "BKE_customdata.h"
+	#include "BKE_DerivedMesh.h"
+	#include "BKE_lattice.h"
+	#include "BKE_modifier.h"
+}
+ #include "BKE_utildefines.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#define __NLA_DEFNORMALS
+//#undef __NLA_DEFNORMALS
+
+
+BL_ModifierDeformer::~BL_ModifierDeformer()
+{
+	if (m_dm) {
+		m_dm->needsFree = 1;
+		m_dm->release(m_dm);
+	}
+};
+
+RAS_Deformer *BL_ModifierDeformer::GetReplica()
+{
+	BL_ModifierDeformer *result;
+
+	result = new BL_ModifierDeformer(*this);
+	result->ProcessReplica();
+	return result;
+}
+
+void BL_ModifierDeformer::ProcessReplica()
+{
+	/* Note! - This is not inherited from PyObjectPlus */
+	BL_ShapeDeformer::ProcessReplica();
+	m_dm = NULL;
+	m_lastModifierUpdate = -1;
+}
+
+bool BL_ModifierDeformer::HasCompatibleDeformer(Object *ob)
+{
+	if (!ob->modifiers.first)
+		return false;
+	// soft body cannot use mesh modifiers
+	if ((ob->gameflag & OB_SOFT_BODY) != 0)
+		return false;
+	ModifierData* md;
+	for (md = (ModifierData*)ob->modifiers.first; md; md = (ModifierData*)md->next) {
+		if (modifier_dependsOnTime(md))
+			continue;
+		if (!(md->mode & eModifierMode_Realtime))
+			continue;
+		return true;
+	}
+	return false;
+}
+
+bool BL_ModifierDeformer::Update(void)
+{
+	bool bShapeUpdate = BL_ShapeDeformer::Update();
+
+	if (bShapeUpdate || m_lastModifierUpdate != m_gameobj->GetLastFrame()) {
+		/* execute the modifiers */
+		Object* blendobj = m_gameobj->GetBlendObject();
+		/* hack: the modifiers require that the mesh is attached to the object
+		   It may not be the case here because of replace mesh actuator */
+		Mesh *oldmesh = (Mesh*)blendobj->data;
+		blendobj->data = m_bmesh;
+		/* execute the modifiers */		
+		DerivedMesh *dm = mesh_create_derived_no_virtual(blendobj, m_transverts, CD_MASK_MESH);
+		/* restore object data */
+		blendobj->data = oldmesh;
+		/* free the current derived mesh and replace, (dm should never be NULL) */
+		if (m_dm != NULL) {
+			m_dm->needsFree = 1;
+			m_dm->release(m_dm);
+		}
+		m_dm = dm;
+		/* update the graphic controller */
+		PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController();
+		if (ctrl) {
+			float min_r[3], max_r[3];
+			INIT_MINMAX(min_r, max_r);
+			m_dm->getMinMax(m_dm, min_r, max_r);
+			ctrl->setLocalAabb(min_r, max_r);
+		}
+		m_lastModifierUpdate=m_gameobj->GetLastFrame();
+		bShapeUpdate = true;
+	}
+	return bShapeUpdate;
+}
+
+bool BL_ModifierDeformer::Apply(RAS_IPolyMaterial *mat)
+{
+	if (!Update())
+		return false;
+
+	// drawing is based on derived mesh, must set it in the mesh slots
+	int nmat = m_pMeshObject->NumMaterials();
+	for (int imat=0; imat<nmat; imat++) {
+		RAS_MeshMaterial *mmat = m_pMeshObject->GetMeshMaterial(imat);
+		RAS_MeshSlot *slot = *mmat->m_slots[(void*)m_gameobj];
+		if(!slot)
+			continue;
+		slot->m_pDerivedMesh = m_dm;
+	}
+	return true;
+}
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.h b/source/gameengine/Converter/BL_ModifierDeformer.h
new file mode 100644
index 0000000000000000000000000000000000000000..465c287a88bcc1a4fe59f7f62ffb17b4f65095c2
--- /dev/null
+++ b/source/gameengine/Converter/BL_ModifierDeformer.h
@@ -0,0 +1,97 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BL_MODIFIERDEFORMER
+#define BL_MODIFIERDEFORMER
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "BL_ShapeDeformer.h"
+#include "BL_DeformableGameObject.h"
+#include <vector>
+
+struct DerivedMesh;
+struct Object;
+
+class BL_ModifierDeformer : public BL_ShapeDeformer  
+{
+public:
+	static bool HasCompatibleDeformer(Object *ob);
+
+
+	BL_ModifierDeformer(BL_DeformableGameObject *gameobj,
+						Object *bmeshobj,
+						BL_SkinMeshObject *mesh)
+						:	
+						BL_ShapeDeformer(gameobj,bmeshobj, mesh),
+						m_lastModifierUpdate(-1),
+						m_dm(NULL)
+	{
+		m_recalcNormal = false;
+	};
+
+	/* this second constructor is needed for making a mesh deformable on the fly. */
+	BL_ModifierDeformer(BL_DeformableGameObject *gameobj,
+						struct Object *bmeshobj_old,
+						struct Object *bmeshobj_new,
+						class BL_SkinMeshObject *mesh,
+						bool release_object,
+						BL_ArmatureObject* arma = NULL)
+						:
+						BL_ShapeDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, false, arma),
+						m_lastModifierUpdate(-1),
+						m_dm(NULL)
+	{
+	};
+
+	virtual void ProcessReplica();
+	virtual RAS_Deformer *GetReplica();
+	virtual ~BL_ModifierDeformer();
+	virtual bool UseVertexArray()
+	{
+		return false;
+	}
+
+	bool Update (void);
+	bool Apply(RAS_IPolyMaterial *mat);
+	void ForceUpdate()
+	{
+		m_lastModifierUpdate = -1.0;
+	};
+
+protected:
+	double					 m_lastModifierUpdate;
+	DerivedMesh				*m_dm;
+
+};
+
+#endif
+
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
index c53be4653ca1ef0f96d060b6559b3f2fcce9e486..29bbe9b3d7de4828f7c0906ca10f9f30c536e25d 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
@@ -61,6 +61,7 @@ BL_ShapeActionActuator::~BL_ShapeActionActuator()
 
 void BL_ShapeActionActuator::ProcessReplica()
 {
+	SCA_IActuator::ProcessReplica();
 	m_localtime=m_startframe;
 	m_lastUpdate=-1;
 }
@@ -74,9 +75,6 @@ CValue* BL_ShapeActionActuator::GetReplica()
 {
 	BL_ShapeActionActuator* replica = new BL_ShapeActionActuator(*this);//m_float,GetName());
 	replica->ProcessReplica();
-	
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
 	return replica;
 }
 
@@ -162,16 +160,9 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame)
 	// maybe there are events for us in the queue !
 	if (frame)
 	{
-		for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++)
-		{
-			if ((*i)->GetNumber() == 0.0f)
-				bNegativeEvent = true;
-			else
-				bPositiveEvent= true;
-			(*i)->Release();
-		
-		}
-		m_events.clear();
+		bNegativeEvent = m_negevent;
+		bPositiveEvent = m_posevent;
+		RemoveAllEvents();
 		
 		if (bPositiveEvent)
 			m_flag |= ACT_FLAG_ACTIVE;
@@ -420,12 +411,17 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame)
 /* Integration hooks ------------------------------------------------------- */
 
 PyTypeObject BL_ShapeActionActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"BL_ShapeActionActuator",
-		sizeof(BL_ShapeActionActuator),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -474,6 +470,7 @@ PyAttributeDef BL_ShapeActionActuator::Attributes[] = {
 	KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ShapeActionActuator, m_startframe),
 	KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ShapeActionActuator, m_endframe),
 	KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendin),
+	KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ShapeActionActuator, pyattr_get_action, pyattr_set_action),
 	KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ShapeActionActuator, m_priority),
 	KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ShapeActionActuator, m_localtime, CheckFrame),
 	KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ShapeActionActuator, m_propname),
@@ -485,51 +482,15 @@ PyAttributeDef BL_ShapeActionActuator::Attributes[] = {
 
 
 PyObject* BL_ShapeActionActuator::py_getattro(PyObject* attr) {
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "action"))
-		return PyString_FromString(m_action->id.name+2);
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
-int BL_ShapeActionActuator::py_setattro(PyObject *attr, PyObject* value) {
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "action"))
-	{
-		if (!PyString_Check(value))
-		{
-			PyErr_SetString(PyExc_ValueError, "expected a string");
-			return 1;
-		}
-
-		STR_String val = PyString_AsString(value);
-		
-		if (val == "")
-		{
-			m_action = NULL;
-			return 0;
-		}
-
-		bAction *action;
-		
-		action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val);
-		
-
-		if (!action)
-		{
-			PyErr_SetString(PyExc_ValueError, "action not found!");
-			return 1;
-		}
+PyObject* BL_ShapeActionActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
 
-		m_action = action;
-		return 0;
-	}
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+int BL_ShapeActionActuator::py_setattro(PyObject *attr, PyObject* value) {
+	py_setattro_up(SCA_IActuator);
 }
 
 /*     setStart                                                              */
@@ -537,7 +498,7 @@ const char BL_ShapeActionActuator::GetAction_doc[] =
 "getAction()\n"
 "\tReturns a string containing the name of the current action.\n";
 
-PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetAction() {
 	ShowDeprecationWarning("getAction()", "the action property");
 	if (m_action){
 		return PyString_FromString(m_action->id.name+2);
@@ -550,7 +511,7 @@ const char BL_ShapeActionActuator::GetProperty_doc[] =
 "getProperty()\n"
 "\tReturns the name of the property to be used in FromProp mode.\n";
 
-PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetProperty() {
 	ShowDeprecationWarning("getProperty()", "the property property");
 	PyObject *result;
 	
@@ -564,7 +525,7 @@ const char BL_ShapeActionActuator::GetFrame_doc[] =
 "getFrame()\n"
 "\tReturns the current frame number.\n";
 
-PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetFrame() {
 	ShowDeprecationWarning("getFrame()", "the frame property");
 	PyObject *result;
 	
@@ -578,7 +539,7 @@ const char BL_ShapeActionActuator::GetEnd_doc[] =
 "getEnd()\n"
 "\tReturns the last frame of the action.\n";
 
-PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetEnd() {
 	ShowDeprecationWarning("getEnd()", "the end property");
 	PyObject *result;
 	
@@ -592,7 +553,7 @@ const char BL_ShapeActionActuator::GetStart_doc[] =
 "getStart()\n"
 "\tReturns the starting frame of the action.\n";
 
-PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetStart() {
 	ShowDeprecationWarning("getStart()", "the start property");
 	PyObject *result;
 	
@@ -607,7 +568,7 @@ const char BL_ShapeActionActuator::GetBlendin_doc[] =
 "\tReturns the number of interpolation animation frames to be\n"
 "\tgenerated when this actuator is triggered.\n";
 
-PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetBlendin() {
 	ShowDeprecationWarning("getBlendin()", "the blendin property");
 	PyObject *result;
 	
@@ -622,7 +583,7 @@ const char BL_ShapeActionActuator::GetPriority_doc[] =
 "\tReturns the priority for this actuator.  Actuators with lower\n"
 "\tPriority numbers will override actuators with higher numbers.\n";
 
-PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetPriority() {
 	ShowDeprecationWarning("getPriority()", "the priority property");
 	PyObject *result;
 	
@@ -642,14 +603,12 @@ const char BL_ShapeActionActuator::SetAction_doc[] =
 "\t               unchanged.  If reset is not specified, the timer will"
 "\t	              be reset.\n";
 
-PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self, 
-											  PyObject* args, 
-											  PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetAction(PyObject* args) {
 	ShowDeprecationWarning("setAction()", "the action property");
 	char *string;
 	int	reset = 1;
 
-	if (PyArg_ParseTuple(args,"s|i",&string, &reset))
+	if (PyArg_ParseTuple(args,"s|i:setAction",&string, &reset))
 	{
 		bAction *action;
 		
@@ -677,13 +636,11 @@ const char BL_ShapeActionActuator::SetStart_doc[] =
 "setStart(start)\n"
 "\t - start     : Specifies the starting frame of the animation.\n";
 
-PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self, 
-											 PyObject* args, 
-											 PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetStart(PyObject* args) {
 	ShowDeprecationWarning("setStart()", "the start property");
 	float start;
 	
-	if (PyArg_ParseTuple(args,"f",&start))
+	if (PyArg_ParseTuple(args,"f:setStart",&start))
 	{
 		m_startframe = start;
 	}
@@ -699,13 +656,11 @@ const char BL_ShapeActionActuator::SetEnd_doc[] =
 "setEnd(end)\n"
 "\t - end       : Specifies the ending frame of the animation.\n";
 
-PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self, 
-										   PyObject* args, 
-										   PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* args) {
 	ShowDeprecationWarning("setEnd()", "the end property");
 	float end;
 	
-	if (PyArg_ParseTuple(args,"f",&end))
+	if (PyArg_ParseTuple(args,"f:setEnd",&end))
 	{
 		m_endframe = end;
 	}
@@ -722,13 +677,11 @@ const char BL_ShapeActionActuator::SetBlendin_doc[] =
 "\t - blendin   : Specifies the number of frames of animation to generate\n"
 "\t               when making transitions between actions.\n";
 
-PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self, 
-											   PyObject* args, 
-											   PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* args) {
 	ShowDeprecationWarning("setBlendin()", "the blendin property");
 	float blendin;
 	
-	if (PyArg_ParseTuple(args,"f",&blendin))
+	if (PyArg_ParseTuple(args,"f:setBlendin",&blendin))
 	{
 		m_blendin = blendin;
 	}
@@ -746,13 +699,11 @@ const char BL_ShapeActionActuator::SetBlendtime_doc[] =
 "\t               used when generating transitions between actions.  This\n"
 "\t               parameter must be in the range from 0.0 to 1.0.\n";
 
-PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self, 
-												 PyObject* args, 
-												   PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* args) {
 	ShowDeprecationWarning("setBlendtime()", "the blendTime property");
 	float blendframe;
 	
-	if (PyArg_ParseTuple(args,"f",&blendframe))
+	if (PyArg_ParseTuple(args,"f:setBlendtime",&blendframe))
 	{
 		m_blendframe = blendframe * m_blendin;
 		if (m_blendframe<0.f)
@@ -774,13 +725,11 @@ const char BL_ShapeActionActuator::SetPriority_doc[] =
 "\t               priority numbers will override actuators with higher\n"
 "\t               numbers.\n";
 
-PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self, 
-												PyObject* args, 
-												PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* args) {
 	ShowDeprecationWarning("setPriority()", "the priority property");
 	int priority;
 	
-	if (PyArg_ParseTuple(args,"i",&priority))
+	if (PyArg_ParseTuple(args,"i:setPriority",&priority))
 	{
 		m_priority = priority;
 	}
@@ -796,7 +745,7 @@ const char BL_ShapeActionActuator::GetFrameProperty_doc[] =
 "getFrameProperty()\n"
 "\tReturns the name of the property, that is set to the current frame number.\n";
 
-PyObject* BL_ShapeActionActuator::PyGetFrameProperty(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetFrameProperty() {
 	ShowDeprecationWarning("getFrameProperty()", "the frameProperty property");
 	PyObject *result;
 	
@@ -811,13 +760,11 @@ const char BL_ShapeActionActuator::SetFrame_doc[] =
 "setFrame(frame)\n"
 "\t - frame     : Specifies the new current frame for the animation\n";
 
-PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self, 
-											 PyObject* args, 
-											 PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* args) {
 	ShowDeprecationWarning("setFrame()", "the frame property");
 	float frame;
 	
-	if (PyArg_ParseTuple(args,"f",&frame))
+	if (PyArg_ParseTuple(args,"f:setFrame",&frame))
 	{
 		m_localtime = frame;
 		if (m_localtime<m_startframe)
@@ -838,13 +785,11 @@ const char BL_ShapeActionActuator::SetProperty_doc[] =
 "\t - prop      : A string specifying the property name to be used in\n"
 "\t               FromProp playback mode.\n";
 
-PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, 
-												PyObject* args, 
-												PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* args) {
 	ShowDeprecationWarning("setProperty()", "the property property");
 	char *string;
 	
-	if (PyArg_ParseTuple(args,"s",&string))
+	if (PyArg_ParseTuple(args,"s:setProperty",&string))
 	{
 		m_propname = string;
 	}
@@ -860,13 +805,11 @@ const char BL_ShapeActionActuator::SetFrameProperty_doc[] =
 "setFrameProperty(prop)\n"
 "\t - prop      : A string specifying the property of the frame set up update.\n";
 
-PyObject* BL_ShapeActionActuator::PySetFrameProperty(PyObject* self, 
-										   PyObject* args, 
-										   PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetFrameProperty(PyObject* args) {
 	ShowDeprecationWarning("setFrameProperty()", "the frameProperty property");
 	char *string;
 	
-	if (PyArg_ParseTuple(args,"s",&string))
+	if (PyArg_ParseTuple(args,"s:setFrameProperty",&string))
 	{
 		m_framepropname = string;
 	}
@@ -881,7 +824,7 @@ PyObject* BL_ShapeActionActuator::PySetFrameProperty(PyObject* self,
 const char BL_ShapeActionActuator::GetType_doc[] =
 "getType()\n"
 "\tReturns the operation mode of the actuator.\n";
-PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) {
+PyObject* BL_ShapeActionActuator::PyGetType() {
 	ShowDeprecationWarning("getType()", "the type property");
     return Py_BuildValue("h", m_playtype);
 }
@@ -891,13 +834,11 @@ const char BL_ShapeActionActuator::SetType_doc[] =
 "setType(mode)\n"
 "\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
 "\tSet the operation mode of the actuator.\n";
-PyObject* BL_ShapeActionActuator::PySetType(PyObject* self,
-                                            PyObject* args,
-                                            PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PySetType(PyObject* args) {
 	ShowDeprecationWarning("setType()", "the type property");
 	short typeArg;
                                                                                                              
-    if (!PyArg_ParseTuple(args, "h", &typeArg)) {
+    if (!PyArg_ParseTuple(args, "h:setType", &typeArg)) {
         return NULL;
     }
 
@@ -916,3 +857,36 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* self,
     Py_RETURN_NONE;
 }
 
+PyObject* BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v);
+	return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
+}
+
+int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v);
+	/* exact copy of BL_ActionActuator's function from here down */
+	if (!PyString_Check(value))
+	{
+		PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, expected the string name of the action");
+		return -1;
+	}
+
+	bAction *action= NULL;
+	STR_String val = PyString_AsString(value);
+	
+	if (val != "")
+	{
+		action= (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val);
+		if (action==NULL)
+		{
+			PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, action not found!");
+			return 1;
+		}
+	}
+	
+	self->SetAction(action);
+	return 0;
+
+}
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h
index ea25d66e0503ae2b8a2e90b2ef2be9e1a2cb317c..d268eef6d23c73ae6372d2815a7fddf78daee007 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.h
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.h
@@ -79,17 +79,20 @@ public:
 	
 	void SetBlendTime (float newtime);
 	void BlendShape(struct Key* key, float weigth);
-
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetAction);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendin);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetPriority);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetStart);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetEnd);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetFrame);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetProperty);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetFrameProperty);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendtime);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetChannel);
+	
+	bAction*	GetAction() { return m_action; }
+	void		SetAction(bAction* act) { m_action= act; }
+
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetAction);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetBlendin);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetPriority);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetStart);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetEnd);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetFrame);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetProperty);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetFrameProperty);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetBlendtime);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetChannel);
 
 	KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetAction);
 	KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetBlendin);
@@ -101,11 +104,15 @@ public:
 	KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetFrameProperty);
 //	KX_PYMETHOD(BL_ActionActuator,GetChannel);
 	KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType);
-	KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType);
+	KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetType);
 
 	virtual PyObject* py_getattro(PyObject* attr);
+	virtual PyObject*		py_getattro_dict();
 	virtual int py_setattro(PyObject* attr, PyObject* value);
 
+	static PyObject*	pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
 	static int CheckBlendTime(void *self, const PyAttributeDef*)
 	{
 		BL_ShapeActionActuator* act = reinterpret_cast<BL_ShapeActionActuator*>(self);
@@ -138,7 +145,7 @@ public:
 			case ACT_ACTION_FROM_PROP:
 				return 0;
 			default:
-				PyErr_SetString(PyExc_ValueError, "invalid type supplied");
+				PyErr_SetString(PyExc_ValueError, "Shape Action Actuator, invalid play type supplied");
 				return 1;
 		}
 
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp
index fc6498579adda26816d3158cd62b40c0eff8479f..bf5eb5cbcb32755c5be47e9631700fb0c0ce99af 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.cpp
+++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp
@@ -68,7 +68,7 @@ BL_ShapeDeformer::~BL_ShapeDeformer()
 {
 };
 
-RAS_Deformer *BL_ShapeDeformer::GetReplica(class KX_GameObject* replica)
+RAS_Deformer *BL_ShapeDeformer::GetReplica()
 {
 	BL_ShapeDeformer *result;
 
@@ -77,17 +77,13 @@ RAS_Deformer *BL_ShapeDeformer::GetReplica(class KX_GameObject* replica)
 	return result;
 }
 
-void BL_ShapeDeformer::ProcessReplica()
-{
-}
-
 bool BL_ShapeDeformer::LoadShapeDrivers(Object* arma)
 {
 	IpoCurve *icu;
 
 	m_shapeDrivers.clear();
 	// check if this mesh has armature driven shape keys
-	if (m_bmesh->key->ipo) {
+	if (m_bmesh->key && m_bmesh->key->ipo) {
 		for(icu= (IpoCurve*)m_bmesh->key->ipo->curve.first; icu; icu= (IpoCurve*)icu->next) {
 			if(icu->driver && 
 				(icu->flag & IPO_MUTE) == 0 &&
@@ -147,7 +143,9 @@ bool BL_ShapeDeformer::Update(void)
 		m_pMeshObject->CheckWeightCache(blendobj);
 
 		/* we will blend the key directly in mvert array: it is used by armature as the start position */
-		do_rel_key(0, m_bmesh->totvert, m_bmesh->totvert, (char *)m_bmesh->mvert->co, m_bmesh->key, 0);
+		/* m_bmesh->key can be NULL in case of Modifier deformer */
+		if (m_bmesh->key)
+			do_rel_key(0, m_bmesh->totvert, m_bmesh->totvert, (char *)m_bmesh->mvert->co, m_bmesh->key, 0);
 
 		// Don't release the weight array as in Blender, it will most likely be reusable on next frame 
 		// The weight array are ultimately deleted when the skin mesh is destroyed
@@ -174,7 +172,8 @@ bool BL_ShapeDeformer::Update(void)
 			VECCOPY(m_transverts[v], m_bmesh->mvert[v].co);
 
 #ifdef __NLA_DEFNORMALS
-		RecalcNormals();
+		if (m_recalcNormal)
+			RecalcNormals();
 #endif
 		bSkinUpdate = true;
 	}
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h
index 90b9f5caea1ebec1a583e10f960bec4ee6c551c0..1ec7bfdf74a236de789b394ad7d81c1427eb9a05 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.h
+++ b/source/gameengine/Converter/BL_ShapeDeformer.h
@@ -58,15 +58,15 @@ public:
 					struct Object *bmeshobj_new,
 					class BL_SkinMeshObject *mesh,
 					bool release_object,
+					bool recalc_normal,
 					BL_ArmatureObject* arma = NULL)
 					:
-						BL_SkinDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, arma),
+						BL_SkinDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, recalc_normal, arma),
 						m_lastShapeUpdate(-1)
 	{
 	};
 
-	virtual void ProcessReplica();
-	virtual RAS_Deformer *GetReplica(class KX_GameObject* replica);
+	virtual RAS_Deformer *GetReplica();
 	virtual ~BL_ShapeDeformer();
 
 	bool Update (void);
diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp
index d856376395444523d419a7f964ee7a8e454679aa..d40776a645dbe4bf3c8a244ca50c7425367bf6fd 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.cpp
+++ b/source/gameengine/Converter/BL_SkinDeformer.cpp
@@ -65,9 +65,10 @@ BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj,
 							BL_MeshDeformer(gameobj, bmeshobj, mesh),
 							m_armobj(arma),
 							m_lastArmaUpdate(-1),
-							m_defbase(&bmeshobj->defbase),
+							//m_defbase(&bmeshobj->defbase),
 							m_releaseobject(false),
-							m_poseApplied(false)
+							m_poseApplied(false),
+							m_recalcNormal(true)
 {
 	Mat4CpyMat4(m_obmat, bmeshobj->obmat);
 };
@@ -78,12 +79,14 @@ BL_SkinDeformer::BL_SkinDeformer(
 	struct Object *bmeshobj_new,	// Blender object that owns the original mesh
 	class BL_SkinMeshObject *mesh,
 	bool release_object,
+	bool recalc_normal,
 	BL_ArmatureObject* arma)	:	
 		BL_MeshDeformer(gameobj, bmeshobj_old, mesh),
 		m_armobj(arma),
 		m_lastArmaUpdate(-1),
-		m_defbase(&bmeshobj_old->defbase),
-		m_releaseobject(release_object)
+		//m_defbase(&bmeshobj_old->defbase),
+		m_releaseobject(release_object),
+		m_recalcNormal(recalc_normal)
 	{
 		// this is needed to ensure correct deformation of mesh:
 		// the deformation is done with Blender's armature_deform_verts() function
@@ -105,7 +108,7 @@ void BL_SkinDeformer::Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
 		void **h_obj = (*map)[m_armobj];
 
 		if (h_obj)
-			SetArmature( (BL_ArmatureObject*)(*h_obj) );
+			m_armobj = (BL_ArmatureObject*)(*h_obj);
 		else
 			m_armobj=NULL;
 	}
@@ -118,47 +121,46 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
 	RAS_MeshSlot::iterator it;
 	RAS_MeshMaterial *mmat;
 	RAS_MeshSlot *slot;
-	size_t i;
+	size_t i, nmat, imat;
 
 	// update the vertex in m_transverts
-	Update();
-
-	// The vertex cache can only be updated for this deformer:
-	// Duplicated objects with more than one ploymaterial (=multiple mesh slot per object)
-	// share the same mesh (=the same cache). As the rendering is done per polymaterial
-	// cycling through the objects, the entire mesh cache cannot be updated in one shot.
-	mmat = m_pMeshObject->GetMeshMaterial(mat);
-	if(!mmat->m_slots[(void*)m_gameobj])
-		return true;
-
-	slot = *mmat->m_slots[(void*)m_gameobj];
-
-	// for each array
-	for(slot->begin(it); !slot->end(it); slot->next(it)) {
-		// for each vertex
-		// copy the untransformed data from the original mvert
-		for(i=it.startvertex; i<it.endvertex; i++) {
-			RAS_TexVert& v = it.vertex[i];
-			v.SetXYZ(m_transverts[v.getOrigIndex()]);
+	if (!Update())
+		return false;
+
+	// the vertex cache is unique to this deformer, no need to update it
+	// if it wasn't updated! We must update all the materials at once
+	// because we will not get here again for the other material
+	nmat = m_pMeshObject->NumMaterials();
+	for (imat=0; imat<nmat; imat++) {
+		mmat = m_pMeshObject->GetMeshMaterial(imat);
+		if(!mmat->m_slots[(void*)m_gameobj])
+			continue;
+
+		slot = *mmat->m_slots[(void*)m_gameobj];
+
+		// for each array
+		for(slot->begin(it); !slot->end(it); slot->next(it)) {
+			// for each vertex
+			// copy the untransformed data from the original mvert
+			for(i=it.startvertex; i<it.endvertex; i++) {
+				RAS_TexVert& v = it.vertex[i];
+				v.SetXYZ(m_transverts[v.getOrigIndex()]);
+			}
 		}
 	}
-
 	return true;
 }
 
-RAS_Deformer *BL_SkinDeformer::GetReplica(class KX_GameObject* replica)
+RAS_Deformer *BL_SkinDeformer::GetReplica()
 {
 	BL_SkinDeformer *result;
 
 	result = new BL_SkinDeformer(*this);
+	/* there is m_armobj that must be fixed but we cannot do it now, it will be done in Relink */
 	result->ProcessReplica();
 	return result;
 }
 
-void BL_SkinDeformer::ProcessReplica()
-{
-}
-
 //void where_is_pose (Object *ob);
 //void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag); 
 bool BL_SkinDeformer::Update(void)
@@ -191,7 +193,8 @@ bool BL_SkinDeformer::Update(void)
 		Mat4CpyMat4(m_objMesh->obmat, obmat);
 
 #ifdef __NLA_DEFNORMALS
-		RecalcNormals();
+		if (m_recalcNormal)
+			RecalcNormals();
 #endif
 
 		/* Update the current frame */
diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h
index f87860021c6e27484970dd7c18f7b88cad963329..0a7b60788f90499c1c3a507cb220c4277e740c50 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.h
+++ b/source/gameengine/Converter/BL_SkinDeformer.h
@@ -64,13 +64,18 @@ public:
 					struct Object *bmeshobj_new,
 					class BL_SkinMeshObject *mesh,
 					bool release_object,
+					bool recalc_normal,
 					BL_ArmatureObject* arma = NULL);
 
-	virtual void ProcessReplica();
-	virtual RAS_Deformer *GetReplica(class KX_GameObject* replica);
+	virtual RAS_Deformer *GetReplica();
 	virtual ~BL_SkinDeformer();
 	bool Update (void);
 	bool Apply (class RAS_IPolyMaterial *polymat);
+	bool UpdateBuckets(void) 
+	{
+		// update the deformer and all the mesh slots; Apply() does it well, so just call it.
+		return Apply(NULL);
+	}
 	bool PoseUpdated(void)
 		{ 
 			if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) {
@@ -88,10 +93,11 @@ protected:
 	BL_ArmatureObject*		m_armobj;	//	Our parent object
 	float					m_time;
 	double					m_lastArmaUpdate;
-	ListBase*				m_defbase;
+	//ListBase*				m_defbase;
 	float					m_obmat[4][4];	// the reference matrix for skeleton deform
 	bool					m_releaseobject;
 	bool					m_poseApplied;
+	bool					m_recalcNormal;
 
 };
 
diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp
index eb3f9d0588d033d6ed7741cf605cebffcd602d18..0a18296f2611bdb110f2a3607dc917c67fdf1e08 100644
--- a/source/gameengine/Converter/BL_SkinMeshObject.cpp
+++ b/source/gameengine/Converter/BL_SkinMeshObject.cpp
@@ -87,7 +87,7 @@ void BL_SkinMeshObject::UpdateBuckets(void* clientobj,double* oglmatrix,bool use
 			continue;
 
 		RAS_MeshSlot *slot = *it->m_slots[clientobj];
-		slot->m_pDeformer = ((BL_DeformableGameObject*)clientobj)->GetDeformer();
+		slot->SetDeformer(((BL_DeformableGameObject*)clientobj)->GetDeformer());
 	}
 
 	RAS_MeshObject::UpdateBuckets(clientobj, oglmatrix, useObjectColor, rgbavec, visible, culled);
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 97a0819147c8cf060e3e404936c7fa7df2cb7cad..190f9dbb472bb2fbc52e10e7e1225d718d0243fa 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -267,9 +267,11 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
 	Scene *blenderscene = GetBlenderSceneForName(scenename);
 
 	e_PhysicsEngine physics_engine = UseBullet;
+	bool useDbvtCulling = false;
 	// hook for registration function during conversion.
 	m_currentScene = destinationscene;
 	destinationscene->SetSceneConverter(this);
+	SG_SetActiveStage(SG_STAGE_CONVERTER);
 
 	if (blenderscene)
 	{
@@ -281,6 +283,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
 			case WOPHY_BULLET:
 				{
 					physics_engine = UseBullet;
+					useDbvtCulling = (blenderscene->world->mode & WO_DBVT_CULLING) != 0;
 					break;
 				}
                                 
@@ -313,7 +316,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
 #ifdef USE_BULLET
 		case UseBullet:
 			{
-				CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment();
+				CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment(useDbvtCulling);
 				ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
 				ccdPhysEnv->setDeactivationLinearTreshold(0.8f); // default, can be overridden by Python
 				ccdPhysEnv->setDeactivationAngularTreshold(1.0f); // default, can be overridden by Python
@@ -806,7 +809,7 @@ void	KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo(){
 					gameobj->NodeSetLocalPosition(pos);
 					gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
 					gameobj->NodeSetLocalScale(scale);
-					gameobj->NodeUpdateGS(0,true);
+					gameobj->NodeUpdateGS(0);
 				}
 			}
 		}
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index f7635856ad9cd836a0f5fe08a61eb11f5f9ffdbe..60d64621665caf8957b5901bbba4d077ab111ba6 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -38,7 +38,7 @@
 
 #include "KX_BlenderSceneConverter.h"
 #include "KX_ConvertActuators.h"
-
+#include "SND_Scene.h"
 // Actuators
 //SCA logiclibrary native logicbricks
 #include "SCA_PropertyActuator.h"
@@ -105,7 +105,6 @@ void BL_ConvertActuators(char* maggiename,
 						 SCA_LogicManager* logicmgr,
 						 KX_Scene* scene,
 						 KX_KetsjiEngine* ketsjiEngine,
-						 int & executePriority, 
 						 int activeLayerBitInfo,
 						 bool isInActiveLayer,
 						 RAS_IRenderTools* rendertools,
@@ -114,11 +113,20 @@ void BL_ConvertActuators(char* maggiename,
 {
 	
 	int uniqueint = 0;
+	int actcount = 0;
+	int executePriority = 0;
 	bActuator* bact = (bActuator*) blenderobject->actuators.first;
+	while (bact)
+	{
+		actcount++;
+		bact = bact->next;
+	}
+	gameobj->ReserveActuator(actcount);
+	bact = (bActuator*) blenderobject->actuators.first;
 	while(bact)
 	{
 		STR_String uniquename = bact->name;
-		STR_String objectname = gameobj->GetName();
+		STR_String& objectname = gameobj->GetName();
 		
 		SCA_IActuator* baseact = NULL;
 		switch (bact->type)
@@ -1008,9 +1016,10 @@ void BL_ConvertActuators(char* maggiename,
 			bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data;
 			KX_VisibilityActuator * tmp_vis_act = NULL;
 			bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0);
+			bool o = ((vis_act->flag & ACT_VISIBILITY_OCCLUSION) != 0);
 			bool recursive = ((vis_act->flag & ACT_VISIBILITY_RECURSIVE) != 0);
 
-			tmp_vis_act = new KX_VisibilityActuator(gameobj, !v, recursive);
+			tmp_vis_act = new KX_VisibilityActuator(gameobj, !v, o, recursive);
 			
 			baseact = tmp_vis_act;
 		}
@@ -1096,7 +1105,7 @@ void BL_ConvertActuators(char* maggiename,
 				buf = txt_to_buf(_2dfilter->text);
 				if (buf)
 				{
-					tmp->SetShaderText(STR_String(buf));
+					tmp->SetShaderText(buf);
 					MEM_freeN(buf);
 				}
 			}
@@ -1143,7 +1152,7 @@ void BL_ConvertActuators(char* maggiename,
 			CIntValue* uniqueval = new CIntValue(uniqueint);
 			uniquename += uniqueval->GetText();
 			uniqueval->Release();
-			baseact->SetName(STR_String(bact->name));
+			baseact->SetName(bact->name);
 			//gameobj->SetProperty(uniquename,baseact);
 			gameobj->AddActuator(baseact);
 			
diff --git a/source/gameengine/Converter/KX_ConvertActuators.h b/source/gameengine/Converter/KX_ConvertActuators.h
index 03ea0db99b95e000c31d9a9c75892fd33fa9bee4..e38a9c74efcd4316afff97c216e7fb15d23742a4 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.h
+++ b/source/gameengine/Converter/KX_ConvertActuators.h
@@ -35,7 +35,6 @@ void BL_ConvertActuators(char* maggiename,
 	 class SCA_LogicManager* logicmgr,
 	 class KX_Scene* scene,
 	 class KX_KetsjiEngine* ketsjiEngine,
-	 int & executePriority,
 	 int activeLayerBitInfo,
 	 bool isInActiveLayer,
 	 class RAS_IRenderTools* rendertools, 
diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp
index fb100b0a68bb45c0da1b654b0fbf3adccc8a54ba..9b0e27b573a422634bb2393bf13285fecacdc6c5 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.cpp
+++ b/source/gameengine/Converter/KX_ConvertControllers.cpp
@@ -76,6 +76,7 @@ LinkControllerToActuators(
 	// Iterate through the actuators of the game blender
 	// controller and find the corresponding ketsji actuator.
 
+	game_controller->ReserveActuator(bcontr->totlinks);
 	for (int i=0;i<bcontr->totlinks;i++)
 	{
 		bActuator* bact = (bActuator*) bcontr->links[i];
@@ -92,14 +93,22 @@ void BL_ConvertControllers(
 	class KX_GameObject* gameobj,
 	SCA_LogicManager* logicmgr, 
 	PyObject* pythondictionary,
-	int &executePriority,
 	int activeLayerBitInfo,
 	bool isInActiveLayer,
 	KX_BlenderSceneConverter* converter
 ) {
 	int uniqueint=0;
+	int count = 0;
+	int executePriority=0;
 	bController* bcontr = (bController*)blenderobject->controllers.first;
 	while (bcontr)
+	{
+		bcontr = bcontr->next;
+		count++;
+	}
+	gameobj->ReserveController(count);
+	bcontr = (bController*)blenderobject->controllers.first;
+	while (bcontr)
 	{
 		SCA_IController* gamecontroller = NULL;
 		switch(bcontr->type)
@@ -107,37 +116,31 @@ void BL_ConvertControllers(
 			case CONT_LOGIC_AND:
 			{
 				gamecontroller = new SCA_ANDController(gameobj);
-				LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
 				break;
 			}
 			case CONT_LOGIC_OR:
 			{
 				gamecontroller = new SCA_ORController(gameobj);
-				LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
 				break;
 			}
 			case CONT_LOGIC_NAND:
 			{
 				gamecontroller = new SCA_NANDController(gameobj);
-				LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
 				break;
 			}
 			case CONT_LOGIC_NOR:
 			{
 				gamecontroller = new SCA_NORController(gameobj);
-				LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
 				break;
 			}
 			case CONT_LOGIC_XOR:
 			{
 				gamecontroller = new SCA_XORController(gameobj);
-				LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
 				break;
 			}
 			case CONT_LOGIC_XNOR:
 			{
 				gamecontroller = new SCA_XNORController(gameobj);
-				LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
 				break;
 			}
 			case CONT_EXPRESSION:
@@ -147,37 +150,43 @@ void BL_ConvertControllers(
 				if (expressiontext.Length() > 0)
 				{
 					gamecontroller = new SCA_ExpressionController(gameobj,expressiontext);
-					LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
-
 				}
 				break;
 			}
 			case CONT_PYTHON:
 			{
-					
-				// we should create a Python controller here
-							
-				SCA_PythonController* pyctrl = new SCA_PythonController(gameobj);
-				gamecontroller = pyctrl;
-					
 				bPythonCont* pycont = (bPythonCont*) bcontr->data;
+				SCA_PythonController* pyctrl = new SCA_PythonController(gameobj, pycont->mode);
+				gamecontroller = pyctrl;
+				
 				pyctrl->SetDictionary(pythondictionary);
-					
-				if (pycont->text)
-				{
-					char *buf;
-					// this is some blender specific code
-					buf= txt_to_buf(pycont->text);
-					if (buf)
+				
+				if(pycont->mode==SCA_PythonController::SCA_PYEXEC_SCRIPT) {
+					if (pycont->text)
 					{
-						pyctrl->SetScriptText(STR_String(buf));
-						pyctrl->SetScriptName(pycont->text->id.name+2);
-						MEM_freeN(buf);
+						char *buf;
+						// this is some blender specific code
+						buf= txt_to_buf(pycont->text);
+						if (buf)
+						{
+							pyctrl->SetScriptText(STR_String(buf));
+							pyctrl->SetScriptName(pycont->text->id.name+2);
+							MEM_freeN(buf);
+						}
+						
 					}
-					
 				}
-					
-				LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
+				else {
+					/* let the controller print any warnings here when importing */
+					pyctrl->SetScriptText(STR_String(pycont->module)); 
+					pyctrl->SetScriptName(pycont->module); /* will be something like module.func so using it as the name is OK */
+				}
+
+				if(pycont->flag & CONT_PY_DEBUG) {
+					printf("\nDebuging \"%s\", module for object %s\n\texpect worse performance.\n", pycont->module, blenderobject->id.name+2);
+					pyctrl->SetDebug(true);
+				}
+				
 				break;
 			}
 			default:
@@ -188,6 +197,7 @@ void BL_ConvertControllers(
 
 		if (gamecontroller)
 		{
+			LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter);
 			gamecontroller->SetExecutePriority(executePriority++);
 			gamecontroller->SetState(bcontr->state_mask);
 			STR_String uniquename = bcontr->name;
@@ -202,9 +212,18 @@ void BL_ConvertControllers(
 			converter->RegisterGameController(gamecontroller, bcontr);
 			
 			if (bcontr->type==CONT_PYTHON) {
+				SCA_PythonController *pyctrl= static_cast<SCA_PythonController*>(gamecontroller);
 				/* not strictly needed but gives syntax errors early on and
 				 * gives more pradictable performance for larger scripts */
-				(static_cast<SCA_PythonController*>(gamecontroller))->Compile();
+				if(pyctrl->m_mode==SCA_PythonController::SCA_PYEXEC_SCRIPT)
+					pyctrl->Compile();
+				else {
+					/* We cant do this because importing runs the script which could end up accessing
+					 * internal BGE functions, this is unstable while we're converting the scene.
+					 * This is a pitty because its useful to see errors at startup but cant help it */
+					
+					// pyctrl->Import();
+				}
 			}
 			
 			//done with gamecontroller
diff --git a/source/gameengine/Converter/KX_ConvertControllers.h b/source/gameengine/Converter/KX_ConvertControllers.h
index 3e8a87fc90b524d8e785a58cf873a2c45f23b461..d340778290c67ad9e48b6cc5138fdeede458e1c1 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.h
+++ b/source/gameengine/Converter/KX_ConvertControllers.h
@@ -36,7 +36,6 @@ void BL_ConvertControllers(
 	class KX_GameObject* gameobj,
 	class SCA_LogicManager* logicmgr, 
 	PyObject* pythondictionary,
-	int & executePriority,
 	int activeLayerBitInfo,
 	bool isInActiveLayer, 
 	class KX_BlenderSceneConverter* converter
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index c9b51807767963ff2064414aca76c1c8b3b9e0de..07b0abae6df698cab698768877c75b32d04d8da0 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -94,168 +94,181 @@ void BL_ConvertSensors(struct Object* blenderobject,
 					   KX_Scene* kxscene,
 					   KX_KetsjiEngine* kxengine,
 					   SCA_IInputDevice* keydev,
-					   int & executePriority,
 					   int activeLayerBitInfo,
 					   bool isInActiveLayer,
 					   RAS_ICanvas* canvas,
 					   KX_BlenderSceneConverter* converter
 					   )
 {
+	static bool reverseTableConverted = false;	
 	
-	
-	
-	/* The reverse table. In order to not confuse ourselves, we      */
-	/* immediately convert all events that come in to KX codes.      */
-	gReverseKeyTranslateTable[LEFTMOUSE			] =	SCA_IInputDevice::KX_LEFTMOUSE;
-	gReverseKeyTranslateTable[MIDDLEMOUSE		] =	SCA_IInputDevice::KX_MIDDLEMOUSE;
-	gReverseKeyTranslateTable[RIGHTMOUSE		] =	SCA_IInputDevice::KX_RIGHTMOUSE;
-	gReverseKeyTranslateTable[WHEELUPMOUSE		] =	SCA_IInputDevice::KX_WHEELUPMOUSE;
-	gReverseKeyTranslateTable[WHEELDOWNMOUSE	] =	SCA_IInputDevice::KX_WHEELDOWNMOUSE;
-	gReverseKeyTranslateTable[MOUSEX			] = SCA_IInputDevice::KX_MOUSEX;
-	gReverseKeyTranslateTable[MOUSEY			] =	SCA_IInputDevice::KX_MOUSEY;
-	
-	// TIMERS                                                                                                  
-	
-	gReverseKeyTranslateTable[TIMER0			] = SCA_IInputDevice::KX_TIMER0;                  
-	gReverseKeyTranslateTable[TIMER1			] = SCA_IInputDevice::KX_TIMER1;                  
-	gReverseKeyTranslateTable[TIMER2			] = SCA_IInputDevice::KX_TIMER2;                  
-	gReverseKeyTranslateTable[TIMER3			] = SCA_IInputDevice::KX_TIMER3;                  
-	
-	// SYSTEM                                                                                                  
-	
-	gReverseKeyTranslateTable[KEYBD				] = SCA_IInputDevice::KX_KEYBD;                  
-	gReverseKeyTranslateTable[RAWKEYBD			] = SCA_IInputDevice::KX_RAWKEYBD;                  
-	gReverseKeyTranslateTable[REDRAW			] = SCA_IInputDevice::KX_REDRAW;                  
-	gReverseKeyTranslateTable[INPUTCHANGE		] = SCA_IInputDevice::KX_INPUTCHANGE;                  
-	gReverseKeyTranslateTable[QFULL				] = SCA_IInputDevice::KX_QFULL;                  
-	gReverseKeyTranslateTable[WINFREEZE			] = SCA_IInputDevice::KX_WINFREEZE;                  
-	gReverseKeyTranslateTable[WINTHAW			] = SCA_IInputDevice::KX_WINTHAW;                  
-	gReverseKeyTranslateTable[WINCLOSE			] = SCA_IInputDevice::KX_WINCLOSE;                  
-	gReverseKeyTranslateTable[WINQUIT			] = SCA_IInputDevice::KX_WINQUIT;                  
-	gReverseKeyTranslateTable[Q_FIRSTTIME		] = SCA_IInputDevice::KX_Q_FIRSTTIME;                  
-	
-	// standard keyboard                                                                                       
-	
-	gReverseKeyTranslateTable[AKEY				] = SCA_IInputDevice::KX_AKEY;                  
-	gReverseKeyTranslateTable[BKEY				] = SCA_IInputDevice::KX_BKEY;                  
-	gReverseKeyTranslateTable[CKEY				] = SCA_IInputDevice::KX_CKEY;                  
-	gReverseKeyTranslateTable[DKEY				] = SCA_IInputDevice::KX_DKEY;                  
-	gReverseKeyTranslateTable[EKEY				] = SCA_IInputDevice::KX_EKEY;                  
-	gReverseKeyTranslateTable[FKEY				] = SCA_IInputDevice::KX_FKEY;                  
-	gReverseKeyTranslateTable[GKEY				] = SCA_IInputDevice::KX_GKEY;                  
-	gReverseKeyTranslateTable[HKEY				] = SCA_IInputDevice::KX_HKEY;                  
-	gReverseKeyTranslateTable[IKEY				] = SCA_IInputDevice::KX_IKEY;                  
-	gReverseKeyTranslateTable[JKEY				] = SCA_IInputDevice::KX_JKEY;                  
-	gReverseKeyTranslateTable[KKEY				] = SCA_IInputDevice::KX_KKEY;                  
-	gReverseKeyTranslateTable[LKEY				] = SCA_IInputDevice::KX_LKEY;                  
-	gReverseKeyTranslateTable[MKEY				] = SCA_IInputDevice::KX_MKEY;                  
-	gReverseKeyTranslateTable[NKEY				] = SCA_IInputDevice::KX_NKEY;                  
-	gReverseKeyTranslateTable[OKEY				] = SCA_IInputDevice::KX_OKEY;                  
-	gReverseKeyTranslateTable[PKEY				] = SCA_IInputDevice::KX_PKEY;                  
-	gReverseKeyTranslateTable[QKEY				] = SCA_IInputDevice::KX_QKEY;                  
-	gReverseKeyTranslateTable[RKEY				] = SCA_IInputDevice::KX_RKEY;                  
-	gReverseKeyTranslateTable[SKEY				] = SCA_IInputDevice::KX_SKEY;                  
-	gReverseKeyTranslateTable[TKEY				] = SCA_IInputDevice::KX_TKEY;                  
-	gReverseKeyTranslateTable[UKEY				] = SCA_IInputDevice::KX_UKEY;                  
-	gReverseKeyTranslateTable[VKEY				] = SCA_IInputDevice::KX_VKEY;                  
-	gReverseKeyTranslateTable[WKEY				] = SCA_IInputDevice::KX_WKEY;                  
-	gReverseKeyTranslateTable[XKEY				] = SCA_IInputDevice::KX_XKEY;                  
-	gReverseKeyTranslateTable[YKEY				] = SCA_IInputDevice::KX_YKEY;                  
-	gReverseKeyTranslateTable[ZKEY				] = SCA_IInputDevice::KX_ZKEY;                  
-	
-	gReverseKeyTranslateTable[ZEROKEY			] = SCA_IInputDevice::KX_ZEROKEY;                  
-	gReverseKeyTranslateTable[ONEKEY			] = SCA_IInputDevice::KX_ONEKEY;                  
-	gReverseKeyTranslateTable[TWOKEY			] = SCA_IInputDevice::KX_TWOKEY;                  
-	gReverseKeyTranslateTable[THREEKEY			] = SCA_IInputDevice::KX_THREEKEY;                  
-	gReverseKeyTranslateTable[FOURKEY			] = SCA_IInputDevice::KX_FOURKEY;                  
-	gReverseKeyTranslateTable[FIVEKEY			] = SCA_IInputDevice::KX_FIVEKEY;                  
-	gReverseKeyTranslateTable[SIXKEY			] = SCA_IInputDevice::KX_SIXKEY;                  
-	gReverseKeyTranslateTable[SEVENKEY			] = SCA_IInputDevice::KX_SEVENKEY;                  
-	gReverseKeyTranslateTable[EIGHTKEY			] = SCA_IInputDevice::KX_EIGHTKEY;                  
-	gReverseKeyTranslateTable[NINEKEY			] = SCA_IInputDevice::KX_NINEKEY;                  
-	
-	gReverseKeyTranslateTable[CAPSLOCKKEY		] = SCA_IInputDevice::KX_CAPSLOCKKEY;                  
-	
-	gReverseKeyTranslateTable[LEFTCTRLKEY		] = SCA_IInputDevice::KX_LEFTCTRLKEY;                  
-	gReverseKeyTranslateTable[LEFTALTKEY		] = SCA_IInputDevice::KX_LEFTALTKEY;                  
-	gReverseKeyTranslateTable[RIGHTALTKEY		] = SCA_IInputDevice::KX_RIGHTALTKEY;                  
-	gReverseKeyTranslateTable[RIGHTCTRLKEY		] = SCA_IInputDevice::KX_RIGHTCTRLKEY;                  
-	gReverseKeyTranslateTable[RIGHTSHIFTKEY		] = SCA_IInputDevice::KX_RIGHTSHIFTKEY;                  
-	gReverseKeyTranslateTable[LEFTSHIFTKEY		] = SCA_IInputDevice::KX_LEFTSHIFTKEY;                  
-	
-	gReverseKeyTranslateTable[ESCKEY			] = SCA_IInputDevice::KX_ESCKEY;                  
-	gReverseKeyTranslateTable[TABKEY			] = SCA_IInputDevice::KX_TABKEY;                  
-	gReverseKeyTranslateTable[RETKEY			] = SCA_IInputDevice::KX_RETKEY;                  
-	gReverseKeyTranslateTable[SPACEKEY			] = SCA_IInputDevice::KX_SPACEKEY;                  
-	gReverseKeyTranslateTable[LINEFEEDKEY		] = SCA_IInputDevice::KX_LINEFEEDKEY;                  
-	gReverseKeyTranslateTable[BACKSPACEKEY		] = SCA_IInputDevice::KX_BACKSPACEKEY;                  
-	gReverseKeyTranslateTable[DELKEY			] = SCA_IInputDevice::KX_DELKEY;                  
-	gReverseKeyTranslateTable[SEMICOLONKEY		] = SCA_IInputDevice::KX_SEMICOLONKEY;                  
-	gReverseKeyTranslateTable[PERIODKEY			] = SCA_IInputDevice::KX_PERIODKEY;                  
-	gReverseKeyTranslateTable[COMMAKEY			] = SCA_IInputDevice::KX_COMMAKEY;                  
-	gReverseKeyTranslateTable[QUOTEKEY			] = SCA_IInputDevice::KX_QUOTEKEY;                  
-	gReverseKeyTranslateTable[ACCENTGRAVEKEY	] = SCA_IInputDevice::KX_ACCENTGRAVEKEY;                  
-	gReverseKeyTranslateTable[MINUSKEY			] = SCA_IInputDevice::KX_MINUSKEY;                  
-	gReverseKeyTranslateTable[SLASHKEY			] = SCA_IInputDevice::KX_SLASHKEY;                  
-	gReverseKeyTranslateTable[BACKSLASHKEY		] = SCA_IInputDevice::KX_BACKSLASHKEY;                  
-	gReverseKeyTranslateTable[EQUALKEY			] = SCA_IInputDevice::KX_EQUALKEY;                  
-	gReverseKeyTranslateTable[LEFTBRACKETKEY	] = SCA_IInputDevice::KX_LEFTBRACKETKEY;                  
-	gReverseKeyTranslateTable[RIGHTBRACKETKEY	] = SCA_IInputDevice::KX_RIGHTBRACKETKEY;                  
-	
-	gReverseKeyTranslateTable[LEFTARROWKEY		] = SCA_IInputDevice::KX_LEFTARROWKEY;                  
-	gReverseKeyTranslateTable[DOWNARROWKEY		] = SCA_IInputDevice::KX_DOWNARROWKEY;                  
-	gReverseKeyTranslateTable[RIGHTARROWKEY		] = SCA_IInputDevice::KX_RIGHTARROWKEY;                  
-	gReverseKeyTranslateTable[UPARROWKEY		] = SCA_IInputDevice::KX_UPARROWKEY;                  
-	
-	gReverseKeyTranslateTable[PAD2				] = SCA_IInputDevice::KX_PAD2;                  
-	gReverseKeyTranslateTable[PAD4				] = SCA_IInputDevice::KX_PAD4;                  
-	gReverseKeyTranslateTable[PAD6				] = SCA_IInputDevice::KX_PAD6;                  
-	gReverseKeyTranslateTable[PAD8				] = SCA_IInputDevice::KX_PAD8;                  
-	
-	gReverseKeyTranslateTable[PAD1				] = SCA_IInputDevice::KX_PAD1;                  
-	gReverseKeyTranslateTable[PAD3				] = SCA_IInputDevice::KX_PAD3;                  
-	gReverseKeyTranslateTable[PAD5				] = SCA_IInputDevice::KX_PAD5;                  
-	gReverseKeyTranslateTable[PAD7				] = SCA_IInputDevice::KX_PAD7;                  
-	gReverseKeyTranslateTable[PAD9				] = SCA_IInputDevice::KX_PAD9;                  
-	
-	gReverseKeyTranslateTable[PADPERIOD			] = SCA_IInputDevice::KX_PADPERIOD;                  
-	gReverseKeyTranslateTable[PADSLASHKEY		] = SCA_IInputDevice::KX_PADSLASHKEY;                  
-	gReverseKeyTranslateTable[PADASTERKEY		] = SCA_IInputDevice::KX_PADASTERKEY;                  
-	
-	gReverseKeyTranslateTable[PAD0				] = SCA_IInputDevice::KX_PAD0;                  
-	gReverseKeyTranslateTable[PADMINUS			] = SCA_IInputDevice::KX_PADMINUS;                  
-	gReverseKeyTranslateTable[PADENTER			] = SCA_IInputDevice::KX_PADENTER;                  
-	gReverseKeyTranslateTable[PADPLUSKEY		] = SCA_IInputDevice::KX_PADPLUSKEY;                  
-	
-	
-	gReverseKeyTranslateTable[F1KEY				] = SCA_IInputDevice::KX_F1KEY;                  
-	gReverseKeyTranslateTable[F2KEY				] = SCA_IInputDevice::KX_F2KEY;                  
-	gReverseKeyTranslateTable[F3KEY				] = SCA_IInputDevice::KX_F3KEY;                  
-	gReverseKeyTranslateTable[F4KEY				] = SCA_IInputDevice::KX_F4KEY;                  
-	gReverseKeyTranslateTable[F5KEY				] = SCA_IInputDevice::KX_F5KEY;                  
-	gReverseKeyTranslateTable[F6KEY				] = SCA_IInputDevice::KX_F6KEY;                  
-	gReverseKeyTranslateTable[F7KEY				] = SCA_IInputDevice::KX_F7KEY;                  
-	gReverseKeyTranslateTable[F8KEY				] = SCA_IInputDevice::KX_F8KEY;                  
-	gReverseKeyTranslateTable[F9KEY				] = SCA_IInputDevice::KX_F9KEY;                  
-	gReverseKeyTranslateTable[F10KEY			] = SCA_IInputDevice::KX_F10KEY;                  
-	gReverseKeyTranslateTable[F11KEY			] = SCA_IInputDevice::KX_F11KEY;                  
-	gReverseKeyTranslateTable[F12KEY			] = SCA_IInputDevice::KX_F12KEY;                  
-	
-	gReverseKeyTranslateTable[PAUSEKEY			] = SCA_IInputDevice::KX_PAUSEKEY;                  
-	gReverseKeyTranslateTable[INSERTKEY			] = SCA_IInputDevice::KX_INSERTKEY;                  
-	gReverseKeyTranslateTable[HOMEKEY			] = SCA_IInputDevice::KX_HOMEKEY;                  
-	gReverseKeyTranslateTable[PAGEUPKEY			] = SCA_IInputDevice::KX_PAGEUPKEY;                  
-	gReverseKeyTranslateTable[PAGEDOWNKEY		] = SCA_IInputDevice::KX_PAGEDOWNKEY;                  
-	gReverseKeyTranslateTable[ENDKEY			] = SCA_IInputDevice::KX_ENDKEY;
-	
+	if (!reverseTableConverted)
+	{
+		reverseTableConverted = true;
+		
+		/* The reverse table. In order to not confuse ourselves, we      */
+		/* immediately convert all events that come in to KX codes.      */
+		gReverseKeyTranslateTable[LEFTMOUSE			] =	SCA_IInputDevice::KX_LEFTMOUSE;
+		gReverseKeyTranslateTable[MIDDLEMOUSE		] =	SCA_IInputDevice::KX_MIDDLEMOUSE;
+		gReverseKeyTranslateTable[RIGHTMOUSE		] =	SCA_IInputDevice::KX_RIGHTMOUSE;
+		gReverseKeyTranslateTable[WHEELUPMOUSE		] =	SCA_IInputDevice::KX_WHEELUPMOUSE;
+		gReverseKeyTranslateTable[WHEELDOWNMOUSE	] =	SCA_IInputDevice::KX_WHEELDOWNMOUSE;
+		gReverseKeyTranslateTable[MOUSEX			] = SCA_IInputDevice::KX_MOUSEX;
+		gReverseKeyTranslateTable[MOUSEY			] =	SCA_IInputDevice::KX_MOUSEY;
+		
+		// TIMERS                                                                                                  
+		
+		gReverseKeyTranslateTable[TIMER0			] = SCA_IInputDevice::KX_TIMER0;                  
+		gReverseKeyTranslateTable[TIMER1			] = SCA_IInputDevice::KX_TIMER1;                  
+		gReverseKeyTranslateTable[TIMER2			] = SCA_IInputDevice::KX_TIMER2;                  
+		gReverseKeyTranslateTable[TIMER3			] = SCA_IInputDevice::KX_TIMER3;                  
+		
+		// SYSTEM                                                                                                  
+		
+		gReverseKeyTranslateTable[KEYBD				] = SCA_IInputDevice::KX_KEYBD;                  
+		gReverseKeyTranslateTable[RAWKEYBD			] = SCA_IInputDevice::KX_RAWKEYBD;                  
+		gReverseKeyTranslateTable[REDRAW			] = SCA_IInputDevice::KX_REDRAW;                  
+		gReverseKeyTranslateTable[INPUTCHANGE		] = SCA_IInputDevice::KX_INPUTCHANGE;                  
+		gReverseKeyTranslateTable[QFULL				] = SCA_IInputDevice::KX_QFULL;                  
+		gReverseKeyTranslateTable[WINFREEZE			] = SCA_IInputDevice::KX_WINFREEZE;                  
+		gReverseKeyTranslateTable[WINTHAW			] = SCA_IInputDevice::KX_WINTHAW;                  
+		gReverseKeyTranslateTable[WINCLOSE			] = SCA_IInputDevice::KX_WINCLOSE;                  
+		gReverseKeyTranslateTable[WINQUIT			] = SCA_IInputDevice::KX_WINQUIT;                  
+		gReverseKeyTranslateTable[Q_FIRSTTIME		] = SCA_IInputDevice::KX_Q_FIRSTTIME;                  
+		
+		// standard keyboard                                                                                       
+		
+		gReverseKeyTranslateTable[AKEY				] = SCA_IInputDevice::KX_AKEY;                  
+		gReverseKeyTranslateTable[BKEY				] = SCA_IInputDevice::KX_BKEY;                  
+		gReverseKeyTranslateTable[CKEY				] = SCA_IInputDevice::KX_CKEY;                  
+		gReverseKeyTranslateTable[DKEY				] = SCA_IInputDevice::KX_DKEY;                  
+		gReverseKeyTranslateTable[EKEY				] = SCA_IInputDevice::KX_EKEY;                  
+		gReverseKeyTranslateTable[FKEY				] = SCA_IInputDevice::KX_FKEY;                  
+		gReverseKeyTranslateTable[GKEY				] = SCA_IInputDevice::KX_GKEY;                  
+		gReverseKeyTranslateTable[HKEY				] = SCA_IInputDevice::KX_HKEY;                  
+		gReverseKeyTranslateTable[IKEY				] = SCA_IInputDevice::KX_IKEY;                  
+		gReverseKeyTranslateTable[JKEY				] = SCA_IInputDevice::KX_JKEY;                  
+		gReverseKeyTranslateTable[KKEY				] = SCA_IInputDevice::KX_KKEY;                  
+		gReverseKeyTranslateTable[LKEY				] = SCA_IInputDevice::KX_LKEY;                  
+		gReverseKeyTranslateTable[MKEY				] = SCA_IInputDevice::KX_MKEY;                  
+		gReverseKeyTranslateTable[NKEY				] = SCA_IInputDevice::KX_NKEY;                  
+		gReverseKeyTranslateTable[OKEY				] = SCA_IInputDevice::KX_OKEY;                  
+		gReverseKeyTranslateTable[PKEY				] = SCA_IInputDevice::KX_PKEY;                  
+		gReverseKeyTranslateTable[QKEY				] = SCA_IInputDevice::KX_QKEY;                  
+		gReverseKeyTranslateTable[RKEY				] = SCA_IInputDevice::KX_RKEY;                  
+		gReverseKeyTranslateTable[SKEY				] = SCA_IInputDevice::KX_SKEY;                  
+		gReverseKeyTranslateTable[TKEY				] = SCA_IInputDevice::KX_TKEY;                  
+		gReverseKeyTranslateTable[UKEY				] = SCA_IInputDevice::KX_UKEY;                  
+		gReverseKeyTranslateTable[VKEY				] = SCA_IInputDevice::KX_VKEY;                  
+		gReverseKeyTranslateTable[WKEY				] = SCA_IInputDevice::KX_WKEY;                  
+		gReverseKeyTranslateTable[XKEY				] = SCA_IInputDevice::KX_XKEY;                  
+		gReverseKeyTranslateTable[YKEY				] = SCA_IInputDevice::KX_YKEY;                  
+		gReverseKeyTranslateTable[ZKEY				] = SCA_IInputDevice::KX_ZKEY;                  
+		
+		gReverseKeyTranslateTable[ZEROKEY			] = SCA_IInputDevice::KX_ZEROKEY;                  
+		gReverseKeyTranslateTable[ONEKEY			] = SCA_IInputDevice::KX_ONEKEY;                  
+		gReverseKeyTranslateTable[TWOKEY			] = SCA_IInputDevice::KX_TWOKEY;                  
+		gReverseKeyTranslateTable[THREEKEY			] = SCA_IInputDevice::KX_THREEKEY;                  
+		gReverseKeyTranslateTable[FOURKEY			] = SCA_IInputDevice::KX_FOURKEY;                  
+		gReverseKeyTranslateTable[FIVEKEY			] = SCA_IInputDevice::KX_FIVEKEY;                  
+		gReverseKeyTranslateTable[SIXKEY			] = SCA_IInputDevice::KX_SIXKEY;                  
+		gReverseKeyTranslateTable[SEVENKEY			] = SCA_IInputDevice::KX_SEVENKEY;                  
+		gReverseKeyTranslateTable[EIGHTKEY			] = SCA_IInputDevice::KX_EIGHTKEY;                  
+		gReverseKeyTranslateTable[NINEKEY			] = SCA_IInputDevice::KX_NINEKEY;                  
+		
+		gReverseKeyTranslateTable[CAPSLOCKKEY		] = SCA_IInputDevice::KX_CAPSLOCKKEY;                  
+		
+		gReverseKeyTranslateTable[LEFTCTRLKEY		] = SCA_IInputDevice::KX_LEFTCTRLKEY;                  
+		gReverseKeyTranslateTable[LEFTALTKEY		] = SCA_IInputDevice::KX_LEFTALTKEY;                  
+		gReverseKeyTranslateTable[RIGHTALTKEY		] = SCA_IInputDevice::KX_RIGHTALTKEY;                  
+		gReverseKeyTranslateTable[RIGHTCTRLKEY		] = SCA_IInputDevice::KX_RIGHTCTRLKEY;                  
+		gReverseKeyTranslateTable[RIGHTSHIFTKEY		] = SCA_IInputDevice::KX_RIGHTSHIFTKEY;                  
+		gReverseKeyTranslateTable[LEFTSHIFTKEY		] = SCA_IInputDevice::KX_LEFTSHIFTKEY;                  
+		
+		gReverseKeyTranslateTable[ESCKEY			] = SCA_IInputDevice::KX_ESCKEY;                  
+		gReverseKeyTranslateTable[TABKEY			] = SCA_IInputDevice::KX_TABKEY;                  
+		gReverseKeyTranslateTable[RETKEY			] = SCA_IInputDevice::KX_RETKEY;                  
+		gReverseKeyTranslateTable[SPACEKEY			] = SCA_IInputDevice::KX_SPACEKEY;                  
+		gReverseKeyTranslateTable[LINEFEEDKEY		] = SCA_IInputDevice::KX_LINEFEEDKEY;                  
+		gReverseKeyTranslateTable[BACKSPACEKEY		] = SCA_IInputDevice::KX_BACKSPACEKEY;                  
+		gReverseKeyTranslateTable[DELKEY			] = SCA_IInputDevice::KX_DELKEY;                  
+		gReverseKeyTranslateTable[SEMICOLONKEY		] = SCA_IInputDevice::KX_SEMICOLONKEY;                  
+		gReverseKeyTranslateTable[PERIODKEY			] = SCA_IInputDevice::KX_PERIODKEY;                  
+		gReverseKeyTranslateTable[COMMAKEY			] = SCA_IInputDevice::KX_COMMAKEY;                  
+		gReverseKeyTranslateTable[QUOTEKEY			] = SCA_IInputDevice::KX_QUOTEKEY;                  
+		gReverseKeyTranslateTable[ACCENTGRAVEKEY	] = SCA_IInputDevice::KX_ACCENTGRAVEKEY;                  
+		gReverseKeyTranslateTable[MINUSKEY			] = SCA_IInputDevice::KX_MINUSKEY;                  
+		gReverseKeyTranslateTable[SLASHKEY			] = SCA_IInputDevice::KX_SLASHKEY;                  
+		gReverseKeyTranslateTable[BACKSLASHKEY		] = SCA_IInputDevice::KX_BACKSLASHKEY;                  
+		gReverseKeyTranslateTable[EQUALKEY			] = SCA_IInputDevice::KX_EQUALKEY;                  
+		gReverseKeyTranslateTable[LEFTBRACKETKEY	] = SCA_IInputDevice::KX_LEFTBRACKETKEY;                  
+		gReverseKeyTranslateTable[RIGHTBRACKETKEY	] = SCA_IInputDevice::KX_RIGHTBRACKETKEY;                  
+		
+		gReverseKeyTranslateTable[LEFTARROWKEY		] = SCA_IInputDevice::KX_LEFTARROWKEY;                  
+		gReverseKeyTranslateTable[DOWNARROWKEY		] = SCA_IInputDevice::KX_DOWNARROWKEY;                  
+		gReverseKeyTranslateTable[RIGHTARROWKEY		] = SCA_IInputDevice::KX_RIGHTARROWKEY;                  
+		gReverseKeyTranslateTable[UPARROWKEY		] = SCA_IInputDevice::KX_UPARROWKEY;                  
+		
+		gReverseKeyTranslateTable[PAD2				] = SCA_IInputDevice::KX_PAD2;                  
+		gReverseKeyTranslateTable[PAD4				] = SCA_IInputDevice::KX_PAD4;                  
+		gReverseKeyTranslateTable[PAD6				] = SCA_IInputDevice::KX_PAD6;                  
+		gReverseKeyTranslateTable[PAD8				] = SCA_IInputDevice::KX_PAD8;                  
+		
+		gReverseKeyTranslateTable[PAD1				] = SCA_IInputDevice::KX_PAD1;                  
+		gReverseKeyTranslateTable[PAD3				] = SCA_IInputDevice::KX_PAD3;                  
+		gReverseKeyTranslateTable[PAD5				] = SCA_IInputDevice::KX_PAD5;                  
+		gReverseKeyTranslateTable[PAD7				] = SCA_IInputDevice::KX_PAD7;                  
+		gReverseKeyTranslateTable[PAD9				] = SCA_IInputDevice::KX_PAD9;                  
+		
+		gReverseKeyTranslateTable[PADPERIOD			] = SCA_IInputDevice::KX_PADPERIOD;                  
+		gReverseKeyTranslateTable[PADSLASHKEY		] = SCA_IInputDevice::KX_PADSLASHKEY;                  
+		gReverseKeyTranslateTable[PADASTERKEY		] = SCA_IInputDevice::KX_PADASTERKEY;                  
+		
+		gReverseKeyTranslateTable[PAD0				] = SCA_IInputDevice::KX_PAD0;                  
+		gReverseKeyTranslateTable[PADMINUS			] = SCA_IInputDevice::KX_PADMINUS;                  
+		gReverseKeyTranslateTable[PADENTER			] = SCA_IInputDevice::KX_PADENTER;                  
+		gReverseKeyTranslateTable[PADPLUSKEY		] = SCA_IInputDevice::KX_PADPLUSKEY;                  
+		
+		
+		gReverseKeyTranslateTable[F1KEY				] = SCA_IInputDevice::KX_F1KEY;                  
+		gReverseKeyTranslateTable[F2KEY				] = SCA_IInputDevice::KX_F2KEY;                  
+		gReverseKeyTranslateTable[F3KEY				] = SCA_IInputDevice::KX_F3KEY;                  
+		gReverseKeyTranslateTable[F4KEY				] = SCA_IInputDevice::KX_F4KEY;                  
+		gReverseKeyTranslateTable[F5KEY				] = SCA_IInputDevice::KX_F5KEY;                  
+		gReverseKeyTranslateTable[F6KEY				] = SCA_IInputDevice::KX_F6KEY;                  
+		gReverseKeyTranslateTable[F7KEY				] = SCA_IInputDevice::KX_F7KEY;                  
+		gReverseKeyTranslateTable[F8KEY				] = SCA_IInputDevice::KX_F8KEY;                  
+		gReverseKeyTranslateTable[F9KEY				] = SCA_IInputDevice::KX_F9KEY;                  
+		gReverseKeyTranslateTable[F10KEY			] = SCA_IInputDevice::KX_F10KEY;                  
+		gReverseKeyTranslateTable[F11KEY			] = SCA_IInputDevice::KX_F11KEY;                  
+		gReverseKeyTranslateTable[F12KEY			] = SCA_IInputDevice::KX_F12KEY;                  
+		
+		gReverseKeyTranslateTable[PAUSEKEY			] = SCA_IInputDevice::KX_PAUSEKEY;                  
+		gReverseKeyTranslateTable[INSERTKEY			] = SCA_IInputDevice::KX_INSERTKEY;                  
+		gReverseKeyTranslateTable[HOMEKEY			] = SCA_IInputDevice::KX_HOMEKEY;                  
+		gReverseKeyTranslateTable[PAGEUPKEY			] = SCA_IInputDevice::KX_PAGEUPKEY;                  
+		gReverseKeyTranslateTable[PAGEDOWNKEY		] = SCA_IInputDevice::KX_PAGEDOWNKEY;                  
+		gReverseKeyTranslateTable[ENDKEY			] = SCA_IInputDevice::KX_ENDKEY;
+	}
+
+    int executePriority = 0;
 	int uniqueint = 0;
+	int count = 0;
 	bSensor* sens = (bSensor*)blenderobject->sensors.first;
 	bool pos_pulsemode = false;
 	bool neg_pulsemode = false;
 	int frequency = 0;
 	bool invert = false;
 	bool level = false;
+	bool tap = false;
 	
+	while (sens)
+	{
+		sens = sens->next;
+		count++;
+	}
+	gameobj->ReserveSensor(count);
+	sens = (bSensor*)blenderobject->sensors.first;
 	while(sens)
 	{
 		SCA_ISensor* gamesensor=NULL;
@@ -268,6 +281,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
 		frequency = sens->freq;
 		invert    = !(sens->invert == 0);
 		level     = !(sens->level == 0);
+		tap       = !(sens->tap == 0);
 
 		switch (sens->type)
 		{
@@ -509,7 +523,6 @@ void BL_ConvertSensors(struct Object* blenderobject,
 							starty,
 							keytype,
 							trackfocus,
-							canvas,
 							kxscene,
 							kxengine,
 							gameobj); 
@@ -708,6 +721,11 @@ void BL_ConvertSensors(struct Object* blenderobject,
 						hatf	= bjoy->hatf;
 						joysticktype  = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT;
 						break;
+					case SENS_JOY_AXIS_SINGLE:
+						axis	= bjoy->axis_single;
+						prec	= bjoy->precision;
+						joysticktype  = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE;
+						break;
 					default:
 						printf("Error: bad case statement\n");
 						break;
@@ -751,7 +769,8 @@ void BL_ConvertSensors(struct Object* blenderobject,
 									 frequency);
 			gamesensor->SetInvert(invert);
 			gamesensor->SetLevel(level);
-			gamesensor->SetName(STR_String(sens->name));			
+			gamesensor->SetTap(tap);
+			gamesensor->SetName(sens->name);			
 			
 			gameobj->AddSensor(gamesensor);
 			
@@ -760,7 +779,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
 			//if (isInActiveLayer)
 			//	gamesensor->RegisterToManager();
 			
-			
+			gamesensor->ReserveController(sens->totlinks);
 			for (int i=0;i<sens->totlinks;i++)
 			{
 				bController* linkedcont = (bController*) sens->links[i];
diff --git a/source/gameengine/Converter/KX_ConvertSensors.h b/source/gameengine/Converter/KX_ConvertSensors.h
index b18ffc10a2ab94555979b9d6553e22763fcec5aa..9162a866768468170ac6f548dd1768e3de4effa0 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.h
+++ b/source/gameengine/Converter/KX_ConvertSensors.h
@@ -35,7 +35,6 @@ void BL_ConvertSensors(struct Object* blenderobject,
 	   class KX_Scene* kxscene,
 	   class KX_KetsjiEngine* kxengine,
 	   class SCA_IInputDevice* keydev,
-	   int & executePriority ,
 	   int activeLayerBitInfo,
 	   bool isInActiveLayer,
 	   class RAS_ICanvas* canvas, 
diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp
index cadb34d7e8f26a3b4ef641d17d0a3b33dc8ccddc..d90da8b3a920ecd665de4480bfde5b342f353eb7 100644
--- a/source/gameengine/Expressions/BoolValue.cpp
+++ b/source/gameengine/Expressions/BoolValue.cpp
@@ -26,6 +26,9 @@
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
 
+const STR_String CBoolValue::sTrueString  = "TRUE";
+const STR_String CBoolValue::sFalseString = "FALSE";
+
 
 CBoolValue::CBoolValue()
 /*
@@ -45,7 +48,7 @@ CBoolValue::CBoolValue(bool inBool)
 
 
 
-CBoolValue::CBoolValue(bool innie,STR_String name,AllocationTYPE alloctype)
+CBoolValue::CBoolValue(bool innie,const char *name,AllocationTYPE alloctype)
 {
 	m_bool = innie;
 	SetName(name);
@@ -181,18 +184,15 @@ ret: the bool stored in the object
 
 
 
-float CBoolValue::GetNumber()
+double CBoolValue::GetNumber()
 {
-	return (float)m_bool;
+	return (double)m_bool;
 }
 
 
 
 const STR_String& CBoolValue::GetText()
 {
-	static STR_String sTrueString  = STR_String("TRUE");
-	static STR_String sFalseString = STR_String("FALSE");
-	
 	return m_bool ? sTrueString : sFalseString;
 }
 
@@ -201,7 +201,7 @@ const STR_String& CBoolValue::GetText()
 CValue* CBoolValue::GetReplica()
 {
 	CBoolValue* replica = new CBoolValue(*this);
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	
 	return replica;
 }
diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/BoolValue.h
index 6c4d964249f1594aba8d3c2d5449a385f5f44820..726619e7193bb01edfcea97a84c7b678cf7377b2 100644
--- a/source/gameengine/Expressions/BoolValue.h
+++ b/source/gameengine/Expressions/BoolValue.h
@@ -28,12 +28,15 @@ class CBoolValue : public CPropValue
 	//PLUGIN_DECLARE_SERIAL(CBoolValue,CValue)	
 
 public:
+	static const STR_String sTrueString;
+	static const STR_String sFalseString;
+
 	CBoolValue();
 	CBoolValue(bool inBool);
-	CBoolValue(bool innie, STR_String name, AllocationTYPE alloctype = CValue::HEAPVALUE);
+	CBoolValue(bool innie, const char *name, AllocationTYPE alloctype = CValue::HEAPVALUE);
 
 	virtual const STR_String& GetText();
-	virtual float		GetNumber();
+	virtual double		GetNumber();
 	bool				GetBool();
 	virtual void		SetValue(CValue* newval);
 	
diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt
index 6b2a835d64828f012319e1ce997fe0b1d1b733d0..eb87fdcee81ebd47f0c2f189b6c8bbb50f4dc6ad 100644
--- a/source/gameengine/Expressions/CMakeLists.txt
+++ b/source/gameengine/Expressions/CMakeLists.txt
@@ -31,6 +31,7 @@ SET(INC
   ../../../source/kernel/gen_system
   ../../../intern/string
   ../../../intern/moto/include
+  ../../../source/gameengine/Scenegraph
   ${PYTHON_INC}
 )
 
diff --git a/source/gameengine/Expressions/ConstExpr.cpp b/source/gameengine/Expressions/ConstExpr.cpp
index e33ba091ac407ebf29e6f6b6b83c5f1b7b526592..6b64be9c9a99c6e5e0d1661a39a2aff9ec1ed6bc 100644
--- a/source/gameengine/Expressions/ConstExpr.cpp
+++ b/source/gameengine/Expressions/ConstExpr.cpp
@@ -84,7 +84,7 @@ void CConstExpr::ClearModified()
 
 
 
-float CConstExpr::GetNumber()
+double CConstExpr::GetNumber()
 {
 	return -1;
 }
diff --git a/source/gameengine/Expressions/ConstExpr.h b/source/gameengine/Expressions/ConstExpr.h
index e27ece52a83a5e350397b1ccd379d6b404ae35ac..b117140fe70e1432996173757493b91bd3067260 100644
--- a/source/gameengine/Expressions/ConstExpr.h
+++ b/source/gameengine/Expressions/ConstExpr.h
@@ -32,7 +32,7 @@ public:
 	//bool IsInside(float x,float y,float z,bool bBorderInclude=true);
 	bool NeedsRecalculated();
 	void ClearModified();
-	virtual float GetNumber();
+	virtual double GetNumber();
 	virtual CValue* Calculate();
 	CConstExpr(CValue* constval);
 	CConstExpr();
diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/EmptyValue.cpp
index c2b60e590a4fec7cb30f5e3bbd0142d32b636e3d..5d1273b5301af6981925825acaa9988269a9f72d 100644
--- a/source/gameengine/Expressions/EmptyValue.cpp
+++ b/source/gameengine/Expressions/EmptyValue.cpp
@@ -76,7 +76,7 @@ this object
 
 
 
-float CEmptyValue::GetNumber()
+double CEmptyValue::GetNumber()
 {
 	return 0;
 }
@@ -121,7 +121,7 @@ const STR_String & CEmptyValue::GetText()
 CValue* CEmptyValue::GetReplica()
 { 
 	CEmptyValue* replica = new CEmptyValue(*this);
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	return replica;
 }
 
diff --git a/source/gameengine/Expressions/EmptyValue.h b/source/gameengine/Expressions/EmptyValue.h
index b9cca0e57e5138a5d6f0c4921af8a03f700315d4..fb6b4a477a6840175d38528042221c48e4e6c632 100644
--- a/source/gameengine/Expressions/EmptyValue.h
+++ b/source/gameengine/Expressions/EmptyValue.h
@@ -27,7 +27,7 @@ public:
 	virtual					~CEmptyValue();
 
 	virtual const STR_String &	GetText();
-	virtual float			GetNumber();
+	virtual double			GetNumber();
 	CListValue*				GetPolySoup();
 	virtual double*			GetVector3(bool bGetTransformedVec=false);
 	bool					IsInside(CValue* testpoint,bool bBorderInclude=true);
diff --git a/source/gameengine/Expressions/ErrorValue.cpp b/source/gameengine/Expressions/ErrorValue.cpp
index e52be4c8021b8e0dd266b14da17cf795837f5730..a44abf8b22ec9078b093a1efe93aeed8e5261801 100644
--- a/source/gameengine/Expressions/ErrorValue.cpp
+++ b/source/gameengine/Expressions/ErrorValue.cpp
@@ -34,13 +34,15 @@ effect: constructs a new CErrorValue containing errormessage "Error"
 
 
 
-CErrorValue::CErrorValue(STR_String errmsg)
+CErrorValue::CErrorValue(const char *errmsg)
 /*
 pre:
 effect: constructs a new CErrorValue containing errormessage errmsg
 */
 {
-  m_strErrorText = "[" + errmsg + "]";
+  m_strErrorText = "[";
+  m_strErrorText += errmsg;
+  m_strErrorText += "]";
   SetError(true);
 }
 
@@ -99,7 +101,7 @@ ret: a new object containing the result of applying operator op to val and
 
 
 
-float CErrorValue::GetNumber()
+double CErrorValue::GetNumber()
 {
 	return -1;
 }
diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/ErrorValue.h
index 16e608ca01aa48c5844b56a3e612ceb7e5a5bc19..b4b758feea740f3ce03a9d4a4362767f4c387339 100644
--- a/source/gameengine/Expressions/ErrorValue.h
+++ b/source/gameengine/Expressions/ErrorValue.h
@@ -23,9 +23,9 @@ class CErrorValue : public CPropValue
 
 public:
 	virtual const STR_String & GetText();
-	virtual float GetNumber();
+	virtual double GetNumber();
 	CErrorValue();
-	CErrorValue(STR_String errmsg);
+	CErrorValue(const char *errmsg);
 	virtual ~CErrorValue();
 	virtual CValue* Calc(VALUE_OPERATOR op, CValue* val);
 	virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp
index 460eaa73f356816b9aae3c193b806d681d11fe0a..4de685a82c19d07e13f7c943aab40b2e146105dc 100644
--- a/source/gameengine/Expressions/FloatValue.cpp
+++ b/source/gameengine/Expressions/FloatValue.cpp
@@ -50,7 +50,7 @@ effect: constructs a new CFloatValue containing value fl
 
 
 
-CFloatValue::CFloatValue(float fl,STR_String name,AllocationTYPE alloctype)
+CFloatValue::CFloatValue(float fl,const char *name,AllocationTYPE alloctype)
 /*
 pre:
 effect: constructs a new CFloatValue containing value fl
@@ -278,7 +278,7 @@ ret: the float stored in the object
 
 
 
-float CFloatValue::GetNumber()
+double CFloatValue::GetNumber()
 {
 	return m_float;
 }
@@ -287,7 +287,7 @@ float CFloatValue::GetNumber()
 
 void CFloatValue::SetValue(CValue* newval)
 { 	
-	m_float = newval->GetNumber(); 
+	m_float = (float)newval->GetNumber(); 
 	SetModified(true);
 }
 
@@ -307,8 +307,8 @@ const STR_String & CFloatValue::GetText()
 CValue* CFloatValue::GetReplica()
 { 
 	CFloatValue* replica = new CFloatValue(*this);
-	replica->m_pstrRep = NULL;
-	CValue::AddDataToReplica(replica);
+	replica->m_pstrRep = NULL; /* should be in CFloatValue::ProcessReplica() but its not defined, no matter */
+	replica->ProcessReplica();
 
 	return replica;
 }
diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/FloatValue.h
index 33f05f1d7f2103ac34bf01e923adb9c0010ade52..fb75b7c702baacfaf113c9e61b283cf53d7265fb 100644
--- a/source/gameengine/Expressions/FloatValue.h
+++ b/source/gameengine/Expressions/FloatValue.h
@@ -23,12 +23,12 @@ class CFloatValue : public CPropValue
 public:
 	CFloatValue();
 	CFloatValue(float fl);
-	CFloatValue(float fl,STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE);
+	CFloatValue(float fl,const char *name,AllocationTYPE alloctype=CValue::HEAPVALUE);
 
 	virtual const STR_String & GetText();
 
 	void Configure(CValue* menuvalue);
-	virtual float GetNumber();
+	virtual double GetNumber();
 	virtual void SetValue(CValue* newval);
 	float GetFloat();
 	void SetFloat(float fl);
diff --git a/source/gameengine/Expressions/IfExpr.cpp b/source/gameengine/Expressions/IfExpr.cpp
index 5d3eb3641ca3c1021a84759f1995528ae1e8b4bf..fcb37bff52da3129d4b939d74f6a652379d57a60 100644
--- a/source/gameengine/Expressions/IfExpr.cpp
+++ b/source/gameengine/Expressions/IfExpr.cpp
@@ -15,6 +15,7 @@
 #include "IfExpr.h"
 #include "EmptyValue.h"
 #include "ErrorValue.h"
+#include "BoolValue.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -72,14 +73,14 @@ ret: a new object containing the value of m_e1 if m_guard is a boolean TRUE
 {
 	CValue *guardval;
 	guardval = m_guard->Calculate();
-	STR_String text = guardval->GetText();
+	const STR_String& text = guardval->GetText();
 	guardval->Release();
 
-	if (text == STR_String("TRUE"))
+	if (&text == &CBoolValue::sTrueString)
 	{
 		return m_e1->Calculate();
 	}
-	else if (text == STR_String("FALSE"))
+	else if (&text == &CBoolValue::sFalseString)
 	{
 		return m_e2->Calculate();
 	}
diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp
index 94663c4a365b0bb71ae7cc845b3a2d39a4d3c26e..b15b206a38a05df2283b4b9d8fadfc15059d5dab 100644
--- a/source/gameengine/Expressions/InputParser.cpp
+++ b/source/gameengine/Expressions/InputParser.cpp
@@ -38,8 +38,13 @@
 // cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc...
 #include "IfExpr.h" 
 
-#if defined(WIN32) || defined(WIN64)
-#define strcasecmp _stricmp
+#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS)
+#define strcasecmp	_stricmp
+
+#ifndef strtoll
+#define strtoll		_strtoi64
+#endif
+
 #endif /* Def WIN32 or Def WIN64 */
 
 #define NUM_PRIORITY 6
@@ -61,7 +66,7 @@ CParser::~CParser()
 
 
 
-void CParser::ScanError(STR_String str)
+void CParser::ScanError(const char *str)
 {
 	// sets the global variable errmsg to an errormessage with
 	// contents str, appending if it already exists
@@ -76,7 +81,7 @@ void CParser::ScanError(STR_String str)
 
 
 
-CExpression* CParser::Error(STR_String str)
+CExpression* CParser::Error(const char *str)
 {
 	// makes and returns a new CConstExpr filled with an CErrorValue
 	// with string str
@@ -319,12 +324,14 @@ void CParser::NextSym()
 	}
 }
 
+#if 0
 int CParser::MakeInt() {
 	// returns the integer representation of the value in the global
 	// variable const_as_string
 	// pre: const_as_string contains only numercal chars
 	return atoi(const_as_string);
 }
+#endif
 
 STR_String CParser::Symbol2Str(int s) {
 	// returns a string representation of of symbol s,
@@ -436,8 +443,8 @@ CExpression *CParser::Ex(int i) {
 					break;
 				case inttype:
 					{
-						int temp;
-						temp = atoi(const_as_string);
+						cInt temp;
+						temp = strtoll(const_as_string, NULL, 10); /* atoi is for int only */
 						e1 = new CConstExpr(new CIntValue(temp));
 						break;
 					}
@@ -530,7 +537,7 @@ CExpression *CParser::Expr() {
 }
 
 CExpression* CParser::ProcessText
-(STR_String intext) {
+(const char *intext) {
 	
 	// and parses the string in intext and returns it.
 	
@@ -567,7 +574,7 @@ CExpression* CParser::ProcessText
 
 
 
-float CParser::GetFloat(STR_String txt)
+float CParser::GetFloat(STR_String& txt)
 {
 	// returns parsed text into a float
 	// empty string returns -1
@@ -580,7 +587,7 @@ float CParser::GetFloat(STR_String txt)
 	CExpression* expr = ProcessText(txt);
 	if (expr) {
 		val = expr->Calculate();
-		result=val->GetNumber();
+		result=(float)val->GetNumber();
 		
 		
 	
@@ -592,7 +599,7 @@ float CParser::GetFloat(STR_String txt)
 	return result;
 }
 
-CValue* CParser::GetValue(STR_String txt, bool bFallbackToText)
+CValue* CParser::GetValue(STR_String& txt, bool bFallbackToText)
 {
 	// returns parsed text into a value, 
 	// empty string returns NULL value !
@@ -642,7 +649,7 @@ PyObject*	CParserPyMake(PyObject* ignored,PyObject* args)
 	CExpression* expr = parser.ProcessText(txt);
 	CValue* val = expr->Calculate();
 	expr->Release();
-	return val;
+	return val->GetProxy();
 }
 
 static PyMethodDef	CParserMethods[] = 
@@ -651,10 +658,41 @@ static PyMethodDef	CParserMethods[] =
 	{ NULL,NULL}	// Sentinel
 };
 
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef Expression_module_def = {
+	{}, /* m_base */
+	"Expression",  /* m_name */
+	0,  /* m_doc */
+	0,  /* m_size */
+	CParserMethods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
+
 extern "C" {
 	void initExpressionModule(void)
 	{
-		Py_InitModule("Expression",CParserMethods);
+		PyObject *m;
+		/* Use existing module where possible
+		 * be careful not to init any runtime vars after this */
+		m = PyImport_ImportModule( "Expression" );
+		if(m) {
+			Py_DECREF(m);
+			//return m;
+		}
+		else {
+			PyErr_Clear();
+		
+#if (PY_VERSION_HEX >= 0x03000000)
+			PyModule_Create(&Expression_module_def);
+#else
+			Py_InitModule("Expression",CParserMethods);
+#endif
+		}
 	}
 }
 
diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h
index f51c473ba188c41cd153255441550714f6ea7d20..810bdc244a81edd1e75ed646051b82d3f1952e41 100644
--- a/source/gameengine/Expressions/InputParser.h
+++ b/source/gameengine/Expressions/InputParser.h
@@ -27,9 +27,9 @@ public:
 	CParser();
 	virtual				~CParser();
 
-	float				GetFloat(STR_String txt);
-	CValue*				GetValue(STR_String txt, bool bFallbackToText=false);
-	CExpression*		ProcessText(STR_String intext);
+	float				GetFloat(STR_String& txt);
+	CValue*				GetValue(STR_String& txt, bool bFallbackToText=false);
+	CExpression*		ProcessText(const char *intext);
 	void				SetContext(CValue* context);
 
 private:
@@ -86,15 +86,17 @@ private:
 	CValue*	m_identifierContext;// context in which identifiers are looked up
 	
 	
-	void ScanError(STR_String str);
-	CExpression* Error(STR_String str);
+	void ScanError(const char *str);
+	CExpression* Error(const char *str);
 	void NextCh();
 	void TermChar(char c);
 	void DigRep();
 	void CharRep();
 	void GrabString(int start);
 	void NextSym();
+#if 0	/* not used yet */
 	int MakeInt();
+#endif
 	STR_String Symbol2Str(int s);
 	void Term(int s);
 	int Priority(int optor);
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp
index fb586cb4979ff99fe6a2385bce194f6b69aa6f10..227518e9439af6f9d27d56959b122dc12efb6f36 100644
--- a/source/gameengine/Expressions/IntValue.cpp
+++ b/source/gameengine/Expressions/IntValue.cpp
@@ -42,10 +42,10 @@ effect: constructs a new CIntValue
 
 
 
-CIntValue::CIntValue(int innie)
+CIntValue::CIntValue(cInt innie)
 /*
 pre:
-effect: constructs a new CIntValue containing int innie
+effect: constructs a new CIntValue containing cInt innie
 */
 {
 	m_int = innie;
@@ -54,7 +54,7 @@ effect: constructs a new CIntValue containing int innie
 
 
 
-CIntValue::CIntValue(int innie,STR_String name,AllocationTYPE alloctype)
+CIntValue::CIntValue(cInt innie,const char *name,AllocationTYPE alloctype)
 {
 	m_int = innie;
 	SetName(name);
@@ -280,10 +280,10 @@ this object
 
 
 
-int CIntValue::GetInt()
+cInt CIntValue::GetInt()
 /*
 pre:
-ret: the int stored in the object
+ret: the cInt stored in the object
 */
 {
 	return m_int;
@@ -291,7 +291,7 @@ ret: the int stored in the object
 
 
 
-float CIntValue::GetNumber()
+double CIntValue::GetNumber()
 {
 	return (float) m_int;
 }
@@ -302,7 +302,7 @@ const STR_String & CIntValue::GetText()
 {
 	if (!m_pstrRep)
 		m_pstrRep=new STR_String();
-	m_pstrRep->Format("%d",m_int);
+	m_pstrRep->Format("%lld",m_int);
 	
 	return *m_pstrRep;
 }
@@ -311,7 +311,7 @@ const STR_String & CIntValue::GetText()
 
 CValue* CIntValue::GetReplica() { 
 	CIntValue* replica = new CIntValue(*this);
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	replica->m_pstrRep = NULL;
 	
 	return replica;
@@ -321,7 +321,7 @@ CValue* CIntValue::GetReplica() {
 
 void CIntValue::SetValue(CValue* newval)
 { 	
-	m_int = (int)newval->GetNumber(); 
+	m_int = (cInt)newval->GetNumber(); 
 	SetModified(true);
 }
 
@@ -329,5 +329,8 @@ void CIntValue::SetValue(CValue* newval)
 
 PyObject* CIntValue::ConvertValueToPython()
 {
-	return PyInt_FromLong(m_int);
+	if((m_int > INT_MIN) && (m_int < INT_MAX))
+		return PyInt_FromLong(m_int);
+	else
+		return PyLong_FromLongLong(m_int);
 }
diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/IntValue.h
index 4fdc1089857aadf71399f4a688d74adf3ee02234..06bf175574973aec9d1f0e37229bd1bd2ecc7efc 100644
--- a/source/gameengine/Expressions/IntValue.h
+++ b/source/gameengine/Expressions/IntValue.h
@@ -18,19 +18,21 @@
 
 #include "Value.h"
 
+typedef long long cInt; 
+
 class CIntValue : public CPropValue  
 {
 	//PLUGIN_DECLARE_SERIAL (CIntValue,CValue)
 
 public:
 	virtual const STR_String& GetText();
-	virtual float			GetNumber();
+	virtual double			GetNumber();
 	
-	int GetInt();
+	cInt GetInt();
 	CIntValue();
-	CIntValue(int innie);
-	CIntValue(int innie,
-			  STR_String name,
+	CIntValue(cInt innie);
+	CIntValue(cInt innie,
+			  const char *name,
 			  AllocationTYPE alloctype=CValue::HEAPVALUE);
 	
 	virtual	CValue* Calc(VALUE_OPERATOR op,
@@ -51,7 +53,7 @@ protected:
 	virtual			~CIntValue();
 
 private:
-	int				m_int;
+	cInt			m_int;
 	STR_String*		m_pstrRep;
 
 };
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
index 15eb8835b798a06ead89748a2f13180007c3c953..75ae2cb787f273e2762de8781e49f71c2ead88bc 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -18,6 +18,7 @@
 #include "StringValue.h"
 #include "VoidValue.h"
 #include <algorithm>
+#include "BoolValue.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -27,59 +28,86 @@
 #define Py_ssize_t int
 #endif
 
-Py_ssize_t listvalue_bufferlen(PyObject* list)
+Py_ssize_t listvalue_bufferlen(PyObject* self)
 {
-	return (Py_ssize_t)( ((CListValue*)list)->GetCount());
+	CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
+	if (list==NULL)
+		return 0;
+	
+	return (Py_ssize_t)list->GetCount();
 }
 
-PyObject* listvalue_buffer_item(PyObject* list,Py_ssize_t index)
+PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index)
 {
-	int count = ((CListValue*) list)->GetCount();
+	CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
+	CValue *cval;
+	
+	if (list==NULL) {
+		PyErr_SetString(PyExc_SystemError, "val = CList[i], "BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
+	int count = list->GetCount();
 	
 	if (index < 0)
 		index = count+index;
 	
-	if (index >= 0 && index < count)
-	{
-		PyObject* pyobj = ((CListValue*) list)->GetValue(index)->ConvertValueToPython();
-		if (pyobj)
-			return pyobj;
-		else
-			return ((CListValue*) list)->GetValue(index)->AddRef();
-
+	if (index < 0 || index >= count) {
+		PyErr_SetString(PyExc_IndexError, "CList[i]: Python ListIndex out of range in CValueList");
+		return NULL;
 	}
-	PyErr_SetString(PyExc_IndexError, "Python ListIndex out of range");
-	return NULL;
+	
+	cval= list->GetValue(index);
+	
+	PyObject* pyobj = cval->ConvertValueToPython();
+	if (pyobj)
+		return pyobj;
+	else
+		return cval->GetProxy();
 }
 
-PyObject* listvalue_mapping_subscript(PyObject* list,PyObject* pyindex)
+PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex)
 {
+	CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
+	if (list==NULL) {
+		PyErr_SetString(PyExc_SystemError, "value = CList[i], "BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
 	if (PyString_Check(pyindex))
 	{
-		STR_String  index(PyString_AsString(pyindex));
+		const char *index = PyString_AsString(pyindex);
 		CValue *item = ((CListValue*) list)->FindValue(index);
 		if (item)
-			return (PyObject*) item;
-			
+		{
+			item->Release(); /* FindValue() AddRef's */ 
+			return item->GetProxy();
+		}
 	}
-	if (PyInt_Check(pyindex))
+	else if (PyInt_Check(pyindex))
 	{
 		int index = PyInt_AsLong(pyindex);
-		return listvalue_buffer_item(list, index);
+		return listvalue_buffer_item(self, index); /* wont add a ref */
 	}
 	
 	PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */
-	PyErr_Format(PyExc_KeyError, "'%s' not in list", PyString_AsString(pyindex_str));
+	PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", PyString_AsString(pyindex_str));
 	Py_DECREF(pyindex_str);
 	return NULL;
 }
 
 
 /* just slice it into a python list... */
-PyObject* listvalue_buffer_slice(PyObject* list,Py_ssize_t ilow, Py_ssize_t ihigh)
+PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihigh)
 {
+	CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
+	if (list==NULL) {
+		PyErr_SetString(PyExc_SystemError, "val = CList[i:j], "BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
 	int i, j;
-	PyListObject *newlist;
+	PyObject *newlist;
 
 	if (ilow < 0) ilow = 0;
 
@@ -90,83 +118,94 @@ PyObject* listvalue_buffer_slice(PyObject* list,Py_ssize_t ilow, Py_ssize_t ihig
     if (ihigh < ilow)
         ihigh = ilow;
 
-	newlist = (PyListObject *) PyList_New(ihigh - ilow);
+	newlist = PyList_New(ihigh - ilow);
 	if (!newlist)
 		return NULL;
 
 	for (i = ilow, j = 0; i < ihigh; i++, j++)
 	{
-		PyObject* pyobj = ((CListValue*) list)->GetValue(i)->ConvertValueToPython();
+		PyObject* pyobj = list->GetValue(i)->ConvertValueToPython();
 		if (!pyobj)
-			pyobj = ((CListValue*) list)->GetValue(i)->AddRef();
-		newlist->ob_item[j] = pyobj;
+			pyobj = list->GetValue(i)->GetProxy();
+		PyList_SET_ITEM(newlist, i, pyobj);
 	}	
-	return (PyObject *) newlist;
+	return newlist;
 }
 
 
-
-static PyObject *
-listvalue_buffer_concat(PyObject * self, PyObject * other)
+/* clist + list, return a list that python owns */
+static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other)
 {
+	CListValue *listval= static_cast<CListValue *>(BGE_PROXY_REF(self));
+	int i, numitems, numitems_orig;
+	
+	if (listval==NULL) {
+		PyErr_SetString(PyExc_SystemError, "CList+other, "BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
+	numitems_orig= listval->GetCount();
+	
 	// for now, we support CListValue concatenated with items
 	// and CListValue concatenated to Python Lists
 	// and CListValue concatenated with another CListValue
-
-	CListValue* listval = (CListValue*) self;
-	listval->AddRef();
-	if (other->ob_type == &PyList_Type)
+	
+	/* Shallow copy, dont use listval->GetReplica(), it will screw up with KX_GameObjects */
+	CListValue* listval_new = new CListValue();
+	
+	if (PyList_Check(other))
 	{
+		CValue* listitemval;
 		bool error = false;
-
-		int i;
-		int numitems = PyList_Size(other);
+		
+		numitems = PyList_Size(other);
+		
+		/* copy the first part of the list */
+		listval_new->Resize(numitems_orig + numitems);
+		for (i=0;i<numitems_orig;i++)
+			listval_new->SetValue(i, listval->GetValue(i)->AddRef());
+		
 		for (i=0;i<numitems;i++)
 		{
-			PyObject* listitem = PyList_GetItem(other,i);
-			CValue* listitemval = listval->ConvertPythonToValue(listitem);
-			if (listitemval)
-			{
-				listval->Add(listitemval);
-			} else
-			{
-				error = true;
+			listitemval = listval->ConvertPythonToValue(PyList_GetItem(other,i), "cList + pyList: CListValue, ");
+			
+			if (listitemval) {
+				listval_new->SetValue(i+numitems_orig, listitemval);
+			} else {
+				error= true;
+				break;
 			}
 		}
-
+		
 		if (error) {
-			PyErr_SetString(PyExc_SystemError, "Python Error: couldn't add one or more items to a list");
-			return NULL;
-		}
-
-	} else
-	{
-		if (other->ob_type == &CListValue::Type)
-		{
-			// add items from otherlist to this list
-			CListValue* otherval = (CListValue*) other;
-			
-
-			for (int i=0;i<otherval->GetCount();i++)
-			{
-				otherval->Add(listval->GetValue(i)->AddRef());
-			}
+			listval_new->Resize(numitems_orig+i); /* resize so we dont try release NULL pointers */
+			listval_new->Release();
+			return NULL; /* ConvertPythonToValue above sets the error */ 
 		}
-		else
-		{
-			CValue* objval = listval->ConvertPythonToValue(other);
-			if (objval)
-			{
-				listval->Add(objval);
-			} else
-			{
-				PyErr_SetString(PyExc_SystemError, "Python Error: couldn't add item to a list");  
-				return NULL;
-			}
+	
+	}
+	else if (PyObject_TypeCheck(other, &CListValue::Type)) {
+		// add items from otherlist to this list
+		CListValue* otherval = static_cast<CListValue *>(BGE_PROXY_REF(other));
+		if(otherval==NULL) {
+			listval_new->Release();
+			PyErr_SetString(PyExc_SystemError, "CList+other, "BGE_PROXY_ERROR_MSG);
+			return NULL;
 		}
+		
+		numitems = otherval->GetCount();
+		
+		/* copy the first part of the list */
+		listval_new->Resize(numitems_orig + numitems); /* resize so we dont try release NULL pointers */
+		for (i=0;i<numitems_orig;i++)
+			listval_new->SetValue(i, listval->GetValue(i)->AddRef());
+		
+		/* now copy the other part of the list */
+		for (i=0;i<numitems;i++)
+			listval_new->SetValue(i+numitems_orig, otherval->GetValue(i)->AddRef());
+		
 	}
-
-	return self;
+	return listval_new->NewProxy(true); /* python owns this list */
 }
 
 
@@ -176,9 +215,15 @@ static  PySequenceMethods listvalue_as_sequence = {
 	listvalue_buffer_concat, /*sq_concat*/
  	NULL, /*sq_repeat*/
 	listvalue_buffer_item, /*sq_item*/
+#if (PY_VERSION_HEX >= 0x03000000) // TODO, slicing in py3?
+	NULL,
+	NULL,
+	NULL,
+#else
 	listvalue_buffer_slice, /*sq_slice*/
  	NULL, /*sq_ass_item*/
- 	NULL /*sq_ass_slice*/
+ 	NULL, /*sq_ass_slice*/
+#endif
 };
 
 
@@ -193,13 +238,18 @@ static  PyMappingMethods instance_as_mapping = {
 
 
 PyTypeObject CListValue::Type = {
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,				/*ob_size*/
+#endif
 	"CListValue",			/*tp_name*/
-	sizeof(CListValue),		/*tp_basicsize*/
+	sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/
 	0,				/*tp_itemsize*/
 	/* methods */
-	PyDestructor,	  		/*tp_dealloc*/
+	py_base_dealloc,	  		/*tp_dealloc*/
 	0,			 	/*tp_print*/
 	0, 			/*tp_getattr*/
 	0, 			/*tp_setattr*/
@@ -233,6 +283,7 @@ PyMethodDef CListValue::Methods[] = {
 	{"reverse", (PyCFunction)CListValue::sPyreverse,METH_NOARGS},
 	{"index", (PyCFunction)CListValue::sPyindex,METH_O},
 	{"count", (PyCFunction)CListValue::sPycount,METH_O},
+	{"from_id", (PyCFunction)CListValue::sPyfrom_id,METH_O},
 	
 	{NULL,NULL} //Sentinel
 };
@@ -245,6 +296,10 @@ PyObject* CListValue::py_getattro(PyObject* attr) {
 	py_getattro_up(CValue);
 }
 
+PyObject* CListValue::py_getattro_dict() {
+	py_getattro_dict_up(CValue);
+}
+
 
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
@@ -292,7 +347,7 @@ const STR_String & CListValue::GetText()
 CValue* CListValue::GetReplica() { 
 	CListValue* replica = new CListValue(*this);
 
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	replica->m_bReleaseContents=true; // for copy, complete array is copied for now...
 	// copy all values
@@ -340,7 +395,7 @@ void CListValue::ReleaseAndRemoveAll()
 
 
 
-CValue* CListValue::FindValue(const STR_String & name)
+CValue* CListValue::FindValue(const char * name)
 {
 	CValue* resultval = NULL;
 	int i=0;
@@ -405,19 +460,29 @@ void CListValue::MergeList(CListValue *otherlist)
 	{
 		SetValue(i+numelements,otherlist->GetValue(i)->AddRef());
 	}
-
 }
 
 
-
-PyObject* CListValue::Pyappend(PyObject* self, PyObject* value)
+PyObject* CListValue::Pyappend(PyObject* value)
 {
-	return listvalue_buffer_concat(self, value);
+	CValue* objval = ConvertPythonToValue(value, "CList.append(i): CValueList, ");
+
+	if (!objval) /* ConvertPythonToValue sets the error */
+		return NULL;
+	
+	if (!BGE_PROXY_PYOWNS(m_proxy)) {
+		PyErr_SetString(PyExc_TypeError, "CList.append(i): this CValueList is used internally for the game engine and can't be modified");
+		return NULL;
+	}
+	
+	Add(objval);
+	
+	Py_RETURN_NONE;
 }
 
 
 
-PyObject* CListValue::Pyreverse(PyObject* self)
+PyObject* CListValue::Pyreverse()
 {
 	std::reverse(m_pValueArray.begin(),m_pValueArray.end());
 	Py_RETURN_NONE;
@@ -430,23 +495,26 @@ bool CListValue::CheckEqual(CValue* first,CValue* second)
 	bool result = false;
 
 	CValue* eqval =  ((CValue*)first)->Calc(VALUE_EQL_OPERATOR,(CValue*)second);
-	STR_String txt = eqval->GetText();
-	eqval->Release();
-	if (txt=="TRUE")
+	
+	if (eqval==NULL)
+		return false;
+	const STR_String& text = eqval->GetText();
+	if (&text==&CBoolValue::sTrueString)
 	{
 		result = true;
 	}
+	eqval->Release();
 	return result;
 
 }
 
 
 
-PyObject* CListValue::Pyindex(PyObject* self, PyObject *value)
+PyObject* CListValue::Pyindex(PyObject *value)
 {
 	PyObject* result = NULL;
 
-	CValue* checkobj = ConvertPythonToValue(value);
+	CValue* checkobj = ConvertPythonToValue(value, "val = cList[i]: CValueList, ");
 	if (checkobj==NULL)
 		return NULL; /* ConvertPythonToValue sets the error */
 
@@ -463,7 +531,7 @@ PyObject* CListValue::Pyindex(PyObject* self, PyObject *value)
 	checkobj->Release();
 
 	if (result==NULL) {
-		PyErr_SetString(PyExc_ValueError, "ValueError: list.index(x): x not in CListValue");
+		PyErr_SetString(PyExc_ValueError, "CList.index(x): x not in CListValue");
 	}
 	return result;
 	
@@ -471,15 +539,15 @@ PyObject* CListValue::Pyindex(PyObject* self, PyObject *value)
 
 
 
-PyObject* CListValue::Pycount(PyObject* self, PyObject* value)
+PyObject* CListValue::Pycount(PyObject* value)
 {
 	int numfound = 0;
 
-	CValue* checkobj = ConvertPythonToValue(value);
+	CValue* checkobj = ConvertPythonToValue(value, ""); /* error ignored */
 	
 	if (checkobj==NULL) { /* in this case just return that there are no items in the list */
 		PyErr_Clear();
-		PyInt_FromLong(0);
+		return PyInt_FromLong(0);
 	}
 
 	int numelem = GetCount();
@@ -498,22 +566,49 @@ PyObject* CListValue::Pycount(PyObject* self, PyObject* value)
 
 
 
+PyObject* CListValue::Pyfrom_id(PyObject* value)
+{
+	uintptr_t id= (uintptr_t)PyLong_AsVoidPtr(value);
+	
+	if (PyErr_Occurred())
+		return NULL;
+
+	int numelem = GetCount();
+	for (int i=0;i<numelem;i++)
+	{
+		if (reinterpret_cast<uintptr_t>(m_pValueArray[i]->m_proxy) == id)
+			return GetValue(i)->GetProxy();
+	}
+	PyErr_SetString(PyExc_IndexError, "from_id(#): id not found in CValueList");
+	return NULL;	
+
+}
+
+
 /* --------------------------------------------------------------------- 
  * Some stuff taken from the header
  * --------------------------------------------------------------------- */
 CValue* CListValue::Calc(VALUE_OPERATOR op,CValue *val) 
 {
-	assert(false); // todo: implement me!
+	//assert(false); // todo: implement me!
+	static int error_printed =  0;
+	if (error_printed==0) {
+		fprintf(stderr, "CValueList::Calc not yet implimented\n");
+		error_printed = 1;
+	}
 	return NULL;
 }
 
-
-
 CValue* CListValue::CalcFinal(VALUE_DATA_TYPE dtype,
 							  VALUE_OPERATOR op, 
 							  CValue* val) 
 {
-	assert(false); // todo: implement me!
+	//assert(false); // todo: implement me!
+	static int error_printed =  0;
+	if (error_printed==0) {
+		fprintf(stderr, "CValueList::CalcFinal not yet implimented\n");
+		error_printed = 1;
+	}
 	return NULL;
 }
 
@@ -526,7 +621,7 @@ void CListValue::Add(CValue* value)
 
 
 
-float CListValue::GetNumber()
+double CListValue::GetNumber()
 {
 	return -1;
 }
diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h
index f936298a8c45ed28a1467730590ed361855cefe3..ad918cbb9254eeb634cba36d5854900574755029 100644
--- a/source/gameengine/Expressions/ListValue.h
+++ b/source/gameengine/Expressions/ListValue.h
@@ -36,7 +36,7 @@ public:
 	virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype,
 							  VALUE_OPERATOR op,
 							  CValue* val);
-	virtual float GetNumber();
+	virtual double GetNumber();
 	virtual CValue* GetReplica();
 
 public:
@@ -45,7 +45,7 @@ public:
 	void SetReleaseOnDestruct(bool bReleaseContents);
 	bool SearchValue(CValue* val);
 	
-	CValue* FindValue(const STR_String & name);
+	CValue* FindValue(const char *name);
 
 	void ReleaseAndRemoveAll();
 	virtual void SetModified(bool bModified);
@@ -60,11 +60,21 @@ public:
 	bool CheckEqual(CValue* first,CValue* second);
 
 	virtual PyObject* py_getattro(PyObject* attr);
+	virtual PyObject* py_getattro_dict();
+	virtual PyObject* py_repr(void) {
+		PyObject *py_proxy= this->GetProxy();
+		PyObject *py_list= PySequence_List(py_proxy);
+		PyObject *py_string= PyObject_Repr(py_list);
+		Py_DECREF(py_list);
+		Py_DECREF(py_proxy);
+		return py_string;
+	}
 
 	KX_PYMETHOD_O(CListValue,append);
 	KX_PYMETHOD_NOARGS(CListValue,reverse);
 	KX_PYMETHOD_O(CListValue,index);
 	KX_PYMETHOD_O(CListValue,count);
+	KX_PYMETHOD_O(CListValue,from_id);
 
 	
 private:
diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile
index 6736149bbcdb7426f0b37eb7923b28d4126a9985..f46c00372008091dcc2921e31fc16e7e0e666e6b 100644
--- a/source/gameengine/Expressions/Makefile
+++ b/source/gameengine/Expressions/Makefile
@@ -41,4 +41,5 @@ CPPFLAGS += -I../../blender/makesdna
 CPPFLAGS += -I$(NAN_STRING)/include
 CPPFLAGS += -I$(NAN_MOTO)/include
 CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../../gameengine/SceneGraph
 
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index ed6932b414ac4cf643694bafa932f1f276f42446..720094b6f9844cb7ef8ed51f9b1351ff0d688274 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -50,18 +50,25 @@
 #include "stdlib.h"
 #include "PyObjectPlus.h"
 #include "STR_String.h"
+#include "MT_Vector3.h"
 /*------------------------------
  * PyObjectPlus Type		-- Every class, even the abstract one should have a Type
 ------------------------------*/
 
+
 PyTypeObject PyObjectPlus::Type = {
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,				/*ob_size*/
+#endif
 	"PyObjectPlus",			/*tp_name*/
-	sizeof(PyObjectPlus),		/*tp_basicsize*/
+	sizeof(PyObjectPlus_Proxy),		/*tp_basicsize*/
 	0,				/*tp_itemsize*/
 	/* methods */
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -74,30 +81,54 @@ PyTypeObject PyObjectPlus::Type = {
 	Methods
 };
 
+
 PyObjectPlus::~PyObjectPlus()
 {
-	if (ob_refcnt)
-	{
-		_Py_ForgetReference(this);
+	if(m_proxy) {
+		Py_DECREF(m_proxy);			/* Remove own reference, python may still have 1 */
+		BGE_PROXY_REF(m_proxy)= NULL;
 	}
 //	assert(ob_refcnt==0);
 }
 
-PyObjectPlus::PyObjectPlus(PyTypeObject *T) 				// constructor
+void PyObjectPlus::py_base_dealloc(PyObject *self)				// python wrapper
+{
+	PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+	if(self_plus) {
+		if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it  */
+			self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */
+			delete self_plus;
+		}
+		
+		BGE_PROXY_REF(self)= NULL; // not really needed
+	}
+	PyObject_DEL( self );
+};
+
+PyObjectPlus::PyObjectPlus(PyTypeObject *T) : SG_QList()				// constructor
 {
 	MT_assert(T != NULL);
-	this->ob_type = T; 
-	_Py_NewReference(this);
+	m_proxy= NULL;
 };
   
 /*------------------------------
  * PyObjectPlus Methods 	-- Every class, even the abstract one should have a Methods
 ------------------------------*/
 PyMethodDef PyObjectPlus::Methods[] = {
-  {"isA",		 (PyCFunction) sPy_isA,			METH_O},
+  {"isA",		 (PyCFunction) sPyisA,			METH_O},
   {NULL, NULL}		/* Sentinel */
 };
 
+PyAttributeDef PyObjectPlus::Attributes[] = {
+	KX_PYATTRIBUTE_RO_FUNCTION("invalid",		PyObjectPlus, pyattr_get_invalid),
+	{NULL} //Sentinel
+};
+
+PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{	
+	Py_RETURN_FALSE;
+}
+
 /*------------------------------
  * PyObjectPlus Parents		-- Every class, even the abstract one should have parents
 ------------------------------*/
@@ -106,17 +137,89 @@ PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL};
 /*------------------------------
  * PyObjectPlus attributes	-- attributes
 ------------------------------*/
+
+
+/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
+PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr)
+{
+	PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+	if(self_plus==NULL) {
+		if(!strcmp("invalid", PyString_AsString(attr))) {
+			Py_RETURN_TRUE;
+		}
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
+	PyObject *ret= self_plus->py_getattro(attr);
+	
+	/* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */
+	if(ret==NULL) {
+		char *attr_str= PyString_AsString(attr);
+		
+		if (strcmp(attr_str, "__dict__")==0)
+		{
+			/* the error string will probably not
+			 * be set but just incase clear it */
+			PyErr_Clear(); 
+			ret= self_plus->py_getattro_dict();
+		}
+		else if (!PyErr_Occurred()) {
+			/* We looked for an attribute but it wasnt found
+			 * since py_getattro didnt set the error, set it here */
+			PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str);
+		}
+	}
+	return ret;
+}
+
+/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
+int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *value)
+{
+	PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+	if(self_plus==NULL) {
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+		return -1;
+	}
+	
+	if (value==NULL)
+		return self_plus->py_delattro(attr);
+	
+	return self_plus->py_setattro(attr, value); 
+}
+
+PyObject *PyObjectPlus::py_base_repr(PyObject *self)			// This should be the entry in Type.
+{
+	
+	PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+	if(self_plus==NULL) {
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
+	return self_plus->py_repr();  
+}
+
 PyObject *PyObjectPlus::py_getattro(PyObject* attr)
 {
 	PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
 	if (descr == NULL) {
-		PyErr_SetString(PyExc_AttributeError, "attribute not found");
-		return NULL;
+		return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */
 	} else {
-		return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, (PyObject *)this); \
+		/* Copied from py_getattro_up */
+		if (PyCObject_Check(descr)) {
+			return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr));
+		} else if (descr->ob_type->tp_descr_get) {
+			return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy);
+		} else {
+			return NULL;
+		}
+		/* end py_getattro_up copy */
 	}
-  //if (streq(attr, "type"))
-  //  return Py_BuildValue("s", (*(GetParents()))->tp_name);
+}
+
+PyObject* PyObjectPlus::py_getattro_dict() {
+	return py_getattr_dict(NULL, Type.tp_dict);
 }
 
 int PyObjectPlus::py_delattro(PyObject* attr)
@@ -127,568 +230,596 @@ int PyObjectPlus::py_delattro(PyObject* attr)
 
 int PyObjectPlus::py_setattro(PyObject *attr, PyObject* value)
 {
-	//return PyObject::py_setattro(attr,value);
-	//cerr << "Unknown attribute" << endl;
 	PyErr_SetString(PyExc_AttributeError, "attribute cant be set");
-	return 1;
+	return PY_SET_ATTR_MISSING;
 }
 
-PyObject *PyObjectPlus::py_getattro_self(const PyAttributeDef attrlist[], void *self, PyObject *attr)
+PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef)
 {
-	char *attr_str= PyString_AsString(attr);
-
-	const PyAttributeDef *attrdef;
-	for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++)
+	if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
+	{
+		// fake attribute, ignore
+		return NULL;
+	}
+	if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION)
 	{
-		if (!strcmp(attr_str, attrdef->m_name))
+		// the attribute has no field correspondance, handover processing to function.
+		if (attrdef->m_getFunction == NULL)
+			return NULL;
+		return (*attrdef->m_getFunction)(self, attrdef);
+	}
+	char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
+	if (attrdef->m_length > 1)
+	{
+		PyObject* resultlist = PyList_New(attrdef->m_length);
+		for (unsigned int i=0; i<attrdef->m_length; i++)
 		{
-			if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
+			switch (attrdef->m_type) {
+			case KX_PYATTRIBUTE_TYPE_BOOL:
+				{
+					bool *val = reinterpret_cast<bool*>(ptr);
+					ptr += sizeof(bool);
+					PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
+					break;
+				}
+			case KX_PYATTRIBUTE_TYPE_SHORT:
+				{
+					short int *val = reinterpret_cast<short int*>(ptr);
+					ptr += sizeof(short int);
+					PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
+					break;
+				}
+			case KX_PYATTRIBUTE_TYPE_ENUM:
+				// enum are like int, just make sure the field size is the same
+				if (sizeof(int) != attrdef->m_size)
+				{
+					Py_DECREF(resultlist);
+					return NULL;
+				}
+				// walkthrough
+			case KX_PYATTRIBUTE_TYPE_INT:
+				{
+					int *val = reinterpret_cast<int*>(ptr);
+					ptr += sizeof(int);
+					PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
+					break;
+				}
+			case KX_PYATTRIBUTE_TYPE_FLOAT:
+				{
+					float *val = reinterpret_cast<float*>(ptr);
+					ptr += sizeof(float);
+					PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(*val));
+					break;
+				}
+			default:
+				// no support for array of complex data
+				Py_DECREF(resultlist);
+				return NULL;
+			}
+		}
+		return resultlist;
+	}
+	else
+	{
+		switch (attrdef->m_type) {
+		case KX_PYATTRIBUTE_TYPE_BOOL:
+			{
+				bool *val = reinterpret_cast<bool*>(ptr);
+				return PyInt_FromLong(*val);
+			}
+		case KX_PYATTRIBUTE_TYPE_SHORT:
+			{
+				short int *val = reinterpret_cast<short int*>(ptr);
+				return PyInt_FromLong(*val);
+			}
+		case KX_PYATTRIBUTE_TYPE_ENUM:
+			// enum are like int, just make sure the field size is the same
+			if (sizeof(int) != attrdef->m_size)
 			{
-				// fake attribute, ignore
 				return NULL;
 			}
-			if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION)
+			// walkthrough
+		case KX_PYATTRIBUTE_TYPE_INT:
 			{
-				// the attribute has no field correspondance, handover processing to function.
-				if (attrdef->m_getFunction == NULL)
-					return NULL;
-				return (*attrdef->m_getFunction)(self, attrdef);
+				int *val = reinterpret_cast<int*>(ptr);
+				return PyInt_FromLong(*val);
 			}
-			char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
-			if (attrdef->m_length > 1)
+		case KX_PYATTRIBUTE_TYPE_FLOAT:
 			{
-				PyObject* resultlist = PyList_New(attrdef->m_length);
-				for (unsigned int i=0; i<attrdef->m_length; i++)
+				float *val = reinterpret_cast<float*>(ptr);
+				return PyFloat_FromDouble(*val);
+			}
+		case KX_PYATTRIBUTE_TYPE_VECTOR:
+			{
+				PyObject* resultlist = PyList_New(3);
+				MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr);
+				for (unsigned int i=0; i<3; i++)
 				{
-					switch (attrdef->m_type) {
-					case KX_PYATTRIBUTE_TYPE_BOOL:
-						{
-							bool *val = reinterpret_cast<bool*>(ptr);
-							ptr += sizeof(bool);
-							PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
-							break;
-						}
-					case KX_PYATTRIBUTE_TYPE_SHORT:
-						{
-							short int *val = reinterpret_cast<short int*>(ptr);
-							ptr += sizeof(short int);
-							PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
-							break;
-						}
-					case KX_PYATTRIBUTE_TYPE_ENUM:
-						// enum are like int, just make sure the field size is the same
-						if (sizeof(int) != attrdef->m_size)
-						{
-							Py_DECREF(resultlist);
-							return NULL;
-						}
-						// walkthrough
-					case KX_PYATTRIBUTE_TYPE_INT:
-						{
-							int *val = reinterpret_cast<int*>(ptr);
-							ptr += sizeof(int);
-							PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
-							break;
-						}
-					case KX_PYATTRIBUTE_TYPE_FLOAT:
-						{
-							float *val = reinterpret_cast<float*>(ptr);
-							ptr += sizeof(float);
-							PyList_SetItem(resultlist,i,PyFloat_FromDouble(*val));
-							break;
-						}
-					default:
-						// no support for array of complex data
-						Py_DECREF(resultlist);
-						return NULL;
-					}
+					PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i]));
 				}
 				return resultlist;
 			}
-			else
+		case KX_PYATTRIBUTE_TYPE_STRING:
 			{
-				switch (attrdef->m_type) {
-				case KX_PYATTRIBUTE_TYPE_BOOL:
-					{
-						bool *val = reinterpret_cast<bool*>(ptr);
-						return PyInt_FromLong(*val);
-					}
-				case KX_PYATTRIBUTE_TYPE_SHORT:
-					{
-						short int *val = reinterpret_cast<short int*>(ptr);
-						return PyInt_FromLong(*val);
-					}
-				case KX_PYATTRIBUTE_TYPE_ENUM:
-					// enum are like int, just make sure the field size is the same
-					if (sizeof(int) != attrdef->m_size)
-					{
-						return NULL;
-					}
-					// walkthrough
-				case KX_PYATTRIBUTE_TYPE_INT:
-					{
-						int *val = reinterpret_cast<int*>(ptr);
-						return PyInt_FromLong(*val);
-					}
-				case KX_PYATTRIBUTE_TYPE_FLOAT:
-					{
-						float *val = reinterpret_cast<float*>(ptr);
-						return PyFloat_FromDouble(*val);
-					}
-				case KX_PYATTRIBUTE_TYPE_STRING:
-					{
-						STR_String *val = reinterpret_cast<STR_String*>(ptr);
-						return PyString_FromString(*val);
-					}
-				default:
-					return NULL;
-				}
+				STR_String *val = reinterpret_cast<STR_String*>(ptr);
+				return PyString_FromString(*val);
 			}
+		default:
+			return NULL;
 		}
 	}
-	return NULL;
 }
 
-int PyObjectPlus::py_setattro_self(const PyAttributeDef attrlist[], void *self, PyObject *attr, PyObject *value)
+int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value)
 {
-	const PyAttributeDef *attrdef;
 	void *undoBuffer = NULL;
 	void *sourceBuffer = NULL;
 	size_t bufferSize = 0;
-	char *attr_str= PyString_AsString(attr);
-
-	for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++)
+	
+	char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
+	if (attrdef->m_length > 1)
 	{
-		if (!strcmp(attr_str, attrdef->m_name))
+		if (!PySequence_Check(value)) 
+		{
+			PyErr_Format(PyExc_TypeError, "expected a sequence for attribute \"%s\"", attrdef->m_name);
+			return 1;
+		}
+		if (PySequence_Size(value) != attrdef->m_length)
+		{
+			PyErr_Format(PyExc_TypeError, "incorrect number of elements in sequence for attribute \"%s\"", attrdef->m_name);
+			return 1;
+		}
+		switch (attrdef->m_type) 
 		{
-			if (attrdef->m_access == KX_PYATTRIBUTE_RO ||
-				attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
+		case KX_PYATTRIBUTE_TYPE_FUNCTION:
+			if (attrdef->m_setFunction == NULL) 
 			{
-				PyErr_SetString(PyExc_AttributeError, "property is read-only");
+				PyErr_Format(PyExc_AttributeError, "function attribute without function for attribute \"%s\", report to blender.org", attrdef->m_name);
 				return 1;
 			}
-			char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
-			if (attrdef->m_length > 1)
+			return (*attrdef->m_setFunction)(self, attrdef, value);
+		case KX_PYATTRIBUTE_TYPE_BOOL:
+			bufferSize = sizeof(bool);
+			break;
+		case KX_PYATTRIBUTE_TYPE_SHORT:
+			bufferSize = sizeof(short int);
+			break;
+		case KX_PYATTRIBUTE_TYPE_ENUM:
+		case KX_PYATTRIBUTE_TYPE_INT:
+			bufferSize = sizeof(int);
+			break;
+		case KX_PYATTRIBUTE_TYPE_FLOAT:
+			bufferSize = sizeof(float);
+			break;
+		default:
+			// should not happen
+			PyErr_Format(PyExc_AttributeError, "Unsupported attribute type for attribute \"%s\", report to blender.org", attrdef->m_name);
+			return 1;
+		}
+		// let's implement a smart undo method
+		bufferSize *= attrdef->m_length;
+		undoBuffer = malloc(bufferSize);
+		sourceBuffer = ptr;
+		if (undoBuffer)
+		{
+			memcpy(undoBuffer, sourceBuffer, bufferSize);
+		}
+		for (int i=0; i<attrdef->m_length; i++)
+		{
+			PyObject *item = PySequence_GetItem(value, i); /* new ref */
+			// we can decrement the reference immediately, the reference count
+			// is at least 1 because the item is part of an array
+			Py_DECREF(item);
+			switch (attrdef->m_type) 
 			{
-				if (!PySequence_Check(value)) 
+			case KX_PYATTRIBUTE_TYPE_BOOL:
 				{
-					PyErr_SetString(PyExc_TypeError, "expected a sequence");
-					return 1;
-				}
-				if (PySequence_Size(value) != attrdef->m_length)
-				{
-					PyErr_SetString(PyExc_TypeError, "incorrect number of elements in sequence");
-					return 1;
-				}
-				switch (attrdef->m_type) 
-				{
-				case KX_PYATTRIBUTE_TYPE_FUNCTION:
-					if (attrdef->m_setFunction == NULL) 
+					bool *var = reinterpret_cast<bool*>(ptr);
+					ptr += sizeof(bool);
+					if (PyInt_Check(item)) 
 					{
-						PyErr_SetString(PyExc_AttributeError, "function attribute without function, report to blender.org");
-						return 1;
+						*var = (PyInt_AsLong(item) != 0);
+					} 
+					else if (PyBool_Check(item))
+					{
+						*var = (item == Py_True);
+					}
+					else
+					{
+						PyErr_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name);
+						goto UNDO_AND_ERROR;
 					}
-					return (*attrdef->m_setFunction)(self, attrdef, value);
-				case KX_PYATTRIBUTE_TYPE_BOOL:
-					bufferSize = sizeof(bool);
-					break;
-				case KX_PYATTRIBUTE_TYPE_SHORT:
-					bufferSize = sizeof(short int);
-					break;
-				case KX_PYATTRIBUTE_TYPE_ENUM:
-				case KX_PYATTRIBUTE_TYPE_INT:
-					bufferSize = sizeof(int);
-					break;
-				case KX_PYATTRIBUTE_TYPE_FLOAT:
-					bufferSize = sizeof(float);
 					break;
-				default:
-					// should not happen
-					PyErr_SetString(PyExc_AttributeError, "Unsupported attribute type, report to blender.org");
-					return 1;
 				}
-				// let's implement a smart undo method
-				bufferSize *= attrdef->m_length;
-				undoBuffer = malloc(bufferSize);
-				sourceBuffer = ptr;
-				if (undoBuffer)
+			case KX_PYATTRIBUTE_TYPE_SHORT:
 				{
-					memcpy(undoBuffer, sourceBuffer, bufferSize);
-				}
-				for (int i=0; i<attrdef->m_length; i++)
-				{
-					PyObject *item = PySequence_GetItem(value, i); /* new ref */
-					// we can decrement the reference immediately, the reference count
-					// is at least 1 because the item is part of an array
-					Py_DECREF(item);
-					switch (attrdef->m_type) 
+					short int *var = reinterpret_cast<short int*>(ptr);
+					ptr += sizeof(short int);
+					if (PyInt_Check(item)) 
 					{
-					case KX_PYATTRIBUTE_TYPE_BOOL:
-						{
-							bool *var = reinterpret_cast<bool*>(ptr);
-							ptr += sizeof(bool);
-							if (PyInt_Check(item)) 
-							{
-								*var = (PyInt_AsLong(item) != 0);
-							} 
-							else if (PyBool_Check(item))
-							{
-								*var = (item == Py_True);
-							}
-							else
-							{
-								PyErr_SetString(PyExc_TypeError, "expected an integer or a bool");
-								goto UNDO_AND_ERROR;
-							}
-							break;
-						}
-					case KX_PYATTRIBUTE_TYPE_SHORT:
+						long val = PyInt_AsLong(item);
+						if (attrdef->m_clamp)
 						{
-							short int *var = reinterpret_cast<short int*>(ptr);
-							ptr += sizeof(short int);
-							if (PyInt_Check(item)) 
-							{
-								long val = PyInt_AsLong(item);
-								if (attrdef->m_clamp)
-								{
-									if (val < attrdef->m_imin)
-										val = attrdef->m_imin;
-									else if (val > attrdef->m_imax)
-										val = attrdef->m_imax;
-								}
-								else if (val < attrdef->m_imin || val > attrdef->m_imax)
-								{
-									PyErr_SetString(PyExc_ValueError, "item value out of range");
-									goto UNDO_AND_ERROR;
-								}
-								*var = (short int)val;
-							}
-							else
-							{
-								PyErr_SetString(PyExc_TypeError, "expected an integer");
-								goto UNDO_AND_ERROR;
-							}
-							break;
+							if (val < attrdef->m_imin)
+								val = attrdef->m_imin;
+							else if (val > attrdef->m_imax)
+								val = attrdef->m_imax;
 						}
-					case KX_PYATTRIBUTE_TYPE_ENUM:
-						// enum are equivalent to int, just make sure that the field size matches:
-						if (sizeof(int) != attrdef->m_size)
+						else if (val < attrdef->m_imin || val > attrdef->m_imax)
 						{
-							PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org");
+							PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
 							goto UNDO_AND_ERROR;
 						}
-						// walkthrough
-					case KX_PYATTRIBUTE_TYPE_INT:
+						*var = (short int)val;
+					}
+					else
+					{
+						PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
+						goto UNDO_AND_ERROR;
+					}
+					break;
+				}
+			case KX_PYATTRIBUTE_TYPE_ENUM:
+				// enum are equivalent to int, just make sure that the field size matches:
+				if (sizeof(int) != attrdef->m_size)
+				{
+					PyErr_Format(PyExc_AttributeError, "Size check error for attribute, \"%s\", report to blender.org", attrdef->m_name);
+					goto UNDO_AND_ERROR;
+				}
+				// walkthrough
+			case KX_PYATTRIBUTE_TYPE_INT:
+				{
+					int *var = reinterpret_cast<int*>(ptr);
+					ptr += sizeof(int);
+					if (PyInt_Check(item)) 
+					{
+						long val = PyInt_AsLong(item);
+						if (attrdef->m_clamp)
 						{
-							int *var = reinterpret_cast<int*>(ptr);
-							ptr += sizeof(int);
-							if (PyInt_Check(item)) 
-							{
-								long val = PyInt_AsLong(item);
-								if (attrdef->m_clamp)
-								{
-									if (val < attrdef->m_imin)
-										val = attrdef->m_imin;
-									else if (val > attrdef->m_imax)
-										val = attrdef->m_imax;
-								}
-								else if (val < attrdef->m_imin || val > attrdef->m_imax)
-								{
-									PyErr_SetString(PyExc_ValueError, "item value out of range");
-									goto UNDO_AND_ERROR;
-								}
-								*var = (int)val;
-							}
-							else
-							{
-								PyErr_SetString(PyExc_TypeError, "expected an integer");
-								goto UNDO_AND_ERROR;
-							}
-							break;
+							if (val < attrdef->m_imin)
+								val = attrdef->m_imin;
+							else if (val > attrdef->m_imax)
+								val = attrdef->m_imax;
 						}
-					case KX_PYATTRIBUTE_TYPE_FLOAT:
+						else if (val < attrdef->m_imin || val > attrdef->m_imax)
 						{
-							float *var = reinterpret_cast<float*>(ptr);
-							ptr += sizeof(float);
-							double val = PyFloat_AsDouble(item);
-							if (val == -1.0 && PyErr_Occurred())
-							{
-								PyErr_SetString(PyExc_TypeError, "expected a float");
-								goto UNDO_AND_ERROR;
-							}
-							else if (attrdef->m_clamp) 
-							{
-								if (val < attrdef->m_fmin)
-									val = attrdef->m_fmin;
-								else if (val > attrdef->m_fmax)
-									val = attrdef->m_fmax;
-							}
-							else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
-							{
-								PyErr_SetString(PyExc_ValueError, "item value out of range");
-								goto UNDO_AND_ERROR;
-							}
-							*var = (float)val;
-							break;
+							PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
+							goto UNDO_AND_ERROR;
 						}
-					default:
-						// should not happen
-						PyErr_SetString(PyExc_AttributeError, "attribute type check error, report to blender.org");
+						*var = (int)val;
+					}
+					else
+					{
+						PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
 						goto UNDO_AND_ERROR;
 					}
+					break;
 				}
-				// no error, call check function if any
-				if (attrdef->m_checkFunction != NULL)
+			case KX_PYATTRIBUTE_TYPE_FLOAT:
 				{
-					if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
+					float *var = reinterpret_cast<float*>(ptr);
+					ptr += sizeof(float);
+					double val = PyFloat_AsDouble(item);
+					if (val == -1.0 && PyErr_Occurred())
 					{
-						// post check returned an error, restore values
-					UNDO_AND_ERROR:
-						if (undoBuffer)
-						{
-							memcpy(sourceBuffer, undoBuffer, bufferSize);
-							free(undoBuffer);
-						}
-						return 1;
+						PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name);
+						goto UNDO_AND_ERROR;
+					}
+					else if (attrdef->m_clamp) 
+					{
+						if (val < attrdef->m_fmin)
+							val = attrdef->m_fmin;
+						else if (val > attrdef->m_fmax)
+							val = attrdef->m_fmax;
+					}
+					else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
+					{
+						PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
+						goto UNDO_AND_ERROR;
 					}
+					*var = (float)val;
+					break;
 				}
+			default:
+				// should not happen
+				PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", report to blender.org", attrdef->m_name);
+				goto UNDO_AND_ERROR;
+			}
+		}
+		// no error, call check function if any
+		if (attrdef->m_checkFunction != NULL)
+		{
+			if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
+			{
+				// if the checing function didnt set an error then set a generic one here so we dont set an error with no exception
+				if (PyErr_Occurred()==0)
+					PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", reasion unknown", attrdef->m_name);
+				
+				// post check returned an error, restore values
+			UNDO_AND_ERROR:
 				if (undoBuffer)
+				{
+					memcpy(sourceBuffer, undoBuffer, bufferSize);
 					free(undoBuffer);
-				return 0;
+				}
+				return 1;
+			}
+		}
+		if (undoBuffer)
+			free(undoBuffer);
+		return 0;
+	}
+	else	// simple attribute value
+	{
+		if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION)
+		{
+			if (attrdef->m_setFunction == NULL)
+			{
+				PyErr_Format(PyExc_AttributeError, "function attribute without function \"%s\", report to blender.org", attrdef->m_name);
+				return 1;
+			}
+			return (*attrdef->m_setFunction)(self, attrdef, value);
+		}
+		if (attrdef->m_checkFunction != NULL || attrdef->m_type == KX_PYATTRIBUTE_TYPE_VECTOR)
+		{
+			// post check function is provided, prepare undo buffer
+			sourceBuffer = ptr;
+			switch (attrdef->m_type) 
+			{
+			case KX_PYATTRIBUTE_TYPE_BOOL:
+				bufferSize = sizeof(bool);
+				break;
+			case KX_PYATTRIBUTE_TYPE_SHORT:
+				bufferSize = sizeof(short);
+				break;
+			case KX_PYATTRIBUTE_TYPE_ENUM:
+			case KX_PYATTRIBUTE_TYPE_INT:
+				bufferSize = sizeof(int);
+				break;
+			case KX_PYATTRIBUTE_TYPE_FLOAT:
+				bufferSize = sizeof(float);
+				break;
+			case KX_PYATTRIBUTE_TYPE_STRING:
+				sourceBuffer = reinterpret_cast<STR_String*>(ptr)->Ptr();
+				if (sourceBuffer)
+					bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1;
+				break;
+			case KX_PYATTRIBUTE_TYPE_VECTOR:
+				bufferSize = sizeof(MT_Vector3);
+				break;
+			default:
+				PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name);
+				return 1;
 			}
-			else	// simple attribute value
+			if (bufferSize)
 			{
-				if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION)
+				undoBuffer = malloc(bufferSize);
+				if (undoBuffer)
 				{
-					if (attrdef->m_setFunction == NULL)
-					{
-						PyErr_SetString(PyExc_AttributeError, "function attribute without function, report to blender.org");
-						return 1;
-					}
-					return (*attrdef->m_setFunction)(self, attrdef, value);
+					memcpy(undoBuffer, sourceBuffer, bufferSize);
 				}
-				if (attrdef->m_checkFunction != NULL)
+			}
+		}
+			
+		switch (attrdef->m_type) 
+		{
+		case KX_PYATTRIBUTE_TYPE_BOOL:
+			{
+				bool *var = reinterpret_cast<bool*>(ptr);
+				if (PyInt_Check(value)) 
+				{
+					*var = (PyInt_AsLong(value) != 0);
+				} 
+				else if (PyBool_Check(value))
 				{
-					// post check function is provided, prepare undo buffer
-					sourceBuffer = ptr;
-					switch (attrdef->m_type) 
+					*var = (value == Py_True);
+				}
+				else
+				{
+					PyErr_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name);
+					goto FREE_AND_ERROR;
+				}
+				break;
+			}
+		case KX_PYATTRIBUTE_TYPE_SHORT:
+			{
+				short int *var = reinterpret_cast<short int*>(ptr);
+				if (PyInt_Check(value)) 
+				{
+					long val = PyInt_AsLong(value);
+					if (attrdef->m_clamp)
 					{
-					case KX_PYATTRIBUTE_TYPE_BOOL:
-						bufferSize = sizeof(bool);
-						break;
-					case KX_PYATTRIBUTE_TYPE_SHORT:
-						bufferSize = sizeof(short);
-						break;
-					case KX_PYATTRIBUTE_TYPE_ENUM:
-					case KX_PYATTRIBUTE_TYPE_INT:
-						bufferSize = sizeof(int);
-						break;
-					case KX_PYATTRIBUTE_TYPE_FLOAT:
-						bufferSize = sizeof(float);
-						break;
-					case KX_PYATTRIBUTE_TYPE_STRING:
-						sourceBuffer = reinterpret_cast<STR_String*>(ptr)->Ptr();
-						if (sourceBuffer)
-							bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1;
-						break;
-					default:
-						PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org");
-						return 1;
+						if (val < attrdef->m_imin)
+							val = attrdef->m_imin;
+						else if (val > attrdef->m_imax)
+							val = attrdef->m_imax;
 					}
-					if (bufferSize)
+					else if (val < attrdef->m_imin || val > attrdef->m_imax)
 					{
-						undoBuffer = malloc(bufferSize);
-						if (undoBuffer)
-						{
-							memcpy(undoBuffer, sourceBuffer, bufferSize);
-						}
+						PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
+						goto FREE_AND_ERROR;
 					}
+					*var = (short int)val;
 				}
-					
-				switch (attrdef->m_type) 
+				else
 				{
-				case KX_PYATTRIBUTE_TYPE_BOOL:
-					{
-						bool *var = reinterpret_cast<bool*>(ptr);
-						if (PyInt_Check(value)) 
-						{
-							*var = (PyInt_AsLong(value) != 0);
-						} 
-						else if (PyBool_Check(value))
-						{
-							*var = (value == Py_True);
-						}
-						else
-						{
-							PyErr_SetString(PyExc_TypeError, "expected an integer or a bool");
-							goto FREE_AND_ERROR;
-						}
-						break;
-					}
-				case KX_PYATTRIBUTE_TYPE_SHORT:
+					PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
+					goto FREE_AND_ERROR;
+				}
+				break;
+			}
+		case KX_PYATTRIBUTE_TYPE_ENUM:
+			// enum are equivalent to int, just make sure that the field size matches:
+			if (sizeof(int) != attrdef->m_size)
+			{
+				PyErr_Format(PyExc_AttributeError, "attribute size check error for attribute \"%s\", report to blender.org", attrdef->m_name);
+				goto FREE_AND_ERROR;
+			}
+			// walkthrough
+		case KX_PYATTRIBUTE_TYPE_INT:
+			{
+				int *var = reinterpret_cast<int*>(ptr);
+				if (PyInt_Check(value)) 
+				{
+					long val = PyInt_AsLong(value);
+					if (attrdef->m_clamp)
 					{
-						short int *var = reinterpret_cast<short int*>(ptr);
-						if (PyInt_Check(value)) 
-						{
-							long val = PyInt_AsLong(value);
-							if (attrdef->m_clamp)
-							{
-								if (val < attrdef->m_imin)
-									val = attrdef->m_imin;
-								else if (val > attrdef->m_imax)
-									val = attrdef->m_imax;
-							}
-							else if (val < attrdef->m_imin || val > attrdef->m_imax)
-							{
-								PyErr_SetString(PyExc_ValueError, "value out of range");
-								goto FREE_AND_ERROR;
-							}
-							*var = (short int)val;
-						}
-						else
-						{
-							PyErr_SetString(PyExc_TypeError, "expected an integer");
-							goto FREE_AND_ERROR;
-						}
-						break;
+						if (val < attrdef->m_imin)
+							val = attrdef->m_imin;
+						else if (val > attrdef->m_imax)
+							val = attrdef->m_imax;
 					}
-				case KX_PYATTRIBUTE_TYPE_ENUM:
-					// enum are equivalent to int, just make sure that the field size matches:
-					if (sizeof(int) != attrdef->m_size)
+					else if (val < attrdef->m_imin || val > attrdef->m_imax)
 					{
-						PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org");
+						PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
 						goto FREE_AND_ERROR;
 					}
-					// walkthrough
-				case KX_PYATTRIBUTE_TYPE_INT:
+					*var = (int)val;
+				}
+				else
+				{
+					PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
+					goto FREE_AND_ERROR;
+				}
+				break;
+			}
+		case KX_PYATTRIBUTE_TYPE_FLOAT:
+			{
+				float *var = reinterpret_cast<float*>(ptr);
+				double val = PyFloat_AsDouble(value);
+				if (val == -1.0 && PyErr_Occurred())
+				{
+					PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name);
+					goto FREE_AND_ERROR;
+				}
+				else if (attrdef->m_clamp)
+				{
+					if (val < attrdef->m_fmin)
+						val = attrdef->m_fmin;
+					else if (val > attrdef->m_fmax)
+						val = attrdef->m_fmax;
+				}
+				else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
+				{
+					PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
+					goto FREE_AND_ERROR;
+				}
+				*var = (float)val;
+				break;
+			}
+		case KX_PYATTRIBUTE_TYPE_VECTOR:
+			{
+				if (!PySequence_Check(value) || PySequence_Size(value) != 3) 
+				{
+					PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name);
+					return 1;
+				}
+				MT_Vector3 *var = reinterpret_cast<MT_Vector3*>(ptr);
+				for (int i=0; i<3; i++)
+				{
+					PyObject *item = PySequence_GetItem(value, i); /* new ref */
+					// we can decrement the reference immediately, the reference count
+					// is at least 1 because the item is part of an array
+					Py_DECREF(item);
+					double val = PyFloat_AsDouble(item);
+					if (val == -1.0 && PyErr_Occurred())
 					{
-						int *var = reinterpret_cast<int*>(ptr);
-						if (PyInt_Check(value)) 
-						{
-							long val = PyInt_AsLong(value);
-							if (attrdef->m_clamp)
-							{
-								if (val < attrdef->m_imin)
-									val = attrdef->m_imin;
-								else if (val > attrdef->m_imax)
-									val = attrdef->m_imax;
-							}
-							else if (val < attrdef->m_imin || val > attrdef->m_imax)
-							{
-								PyErr_SetString(PyExc_ValueError, "value out of range");
-								goto FREE_AND_ERROR;
-							}
-							*var = (int)val;
-						}
-						else
-						{
-							PyErr_SetString(PyExc_TypeError, "expected an integer");
-							goto FREE_AND_ERROR;
-						}
-						break;
+						PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name);
+						goto RESTORE_AND_ERROR;
 					}
-				case KX_PYATTRIBUTE_TYPE_FLOAT:
+					else if (attrdef->m_clamp)
 					{
-						float *var = reinterpret_cast<float*>(ptr);
-						double val = PyFloat_AsDouble(value);
-						if (val == -1.0 && PyErr_Occurred())
-						{
-							PyErr_SetString(PyExc_TypeError, "expected a float");
-							goto FREE_AND_ERROR;
-						}
-						else if (attrdef->m_clamp)
-						{
-							if (val < attrdef->m_fmin)
-								val = attrdef->m_fmin;
-							else if (val > attrdef->m_fmax)
-								val = attrdef->m_fmax;
-						}
-						else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
-						{
-							PyErr_SetString(PyExc_ValueError, "value out of range");
-							goto FREE_AND_ERROR;
-						}
-						*var = (float)val;
-						break;
+						if (val < attrdef->m_fmin)
+							val = attrdef->m_fmin;
+						else if (val > attrdef->m_fmax)
+							val = attrdef->m_fmax;
 					}
-				case KX_PYATTRIBUTE_TYPE_STRING:
+					else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
 					{
-						STR_String *var = reinterpret_cast<STR_String*>(ptr);
-						if (PyString_Check(value)) 
-						{
-							char *val = PyString_AsString(value);
-							if (attrdef->m_clamp)
-							{
-								if (strlen(val) < attrdef->m_imin)
-								{
-									// can't increase the length of the string
-									PyErr_SetString(PyExc_ValueError, "string length too short");
-									goto FREE_AND_ERROR;
-								}
-								else if (strlen(val) > attrdef->m_imax)
-								{
-									// trim the string
-									char c = val[attrdef->m_imax];
-									val[attrdef->m_imax] = 0;
-									*var = val;
-									val[attrdef->m_imax] = c;
-									break;
-								}
-							} else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax)
-							{
-								PyErr_SetString(PyExc_ValueError, "string length out of range");
-								goto FREE_AND_ERROR;
-							}
-							*var = val;
-						}
-						else
-						{
-							PyErr_SetString(PyExc_TypeError, "expected a string");
-							goto FREE_AND_ERROR;
-						}
-						break;
+						PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
+						goto RESTORE_AND_ERROR;
 					}
-				default:
-					// should not happen
-					PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org");
-					goto FREE_AND_ERROR;
+					(*var)[i] = (MT_Scalar)val;
 				}
+				break;
 			}
-			// check if post processing is needed
-			if (attrdef->m_checkFunction != NULL)
+		case KX_PYATTRIBUTE_TYPE_STRING:
 			{
-				if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
+				STR_String *var = reinterpret_cast<STR_String*>(ptr);
+				if (PyString_Check(value)) 
 				{
-					// restore value
-				RESTORE_AND_ERROR:
-					if (undoBuffer)
+					char *val = PyString_AsString(value);
+					if (attrdef->m_clamp)
 					{
-						if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING)
+						if (strlen(val) < attrdef->m_imin)
 						{
-							// special case for STR_String: restore the string
-							STR_String *var = reinterpret_cast<STR_String*>(ptr);
-							*var = reinterpret_cast<char*>(undoBuffer);
+							// can't increase the length of the string
+							PyErr_Format(PyExc_ValueError, "string length too short for attribute \"%s\"", attrdef->m_name);
+							goto FREE_AND_ERROR;
 						}
-						else
+						else if (strlen(val) > attrdef->m_imax)
 						{
-							// other field type have direct values
-							memcpy(ptr, undoBuffer, bufferSize);
+							// trim the string
+							char c = val[attrdef->m_imax];
+							val[attrdef->m_imax] = 0;
+							*var = val;
+							val[attrdef->m_imax] = c;
+							break;
 						}
+					} else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax)
+					{
+						PyErr_Format(PyExc_ValueError, "string length out of range for attribute \"%s\"", attrdef->m_name);
+						goto FREE_AND_ERROR;
 					}
-				FREE_AND_ERROR:
-					if (undoBuffer)
-						free(undoBuffer);
-					return 1;
+					*var = val;
 				}
+				else
+				{
+					PyErr_Format(PyExc_TypeError, "expected a string for attribute \"%s\"", attrdef->m_name);
+					goto FREE_AND_ERROR;
+				}
+				break;
 			}
+		default:
+			// should not happen
+			PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name);
+			goto FREE_AND_ERROR;
+		}
+	}
+	// check if post processing is needed
+	if (attrdef->m_checkFunction != NULL)
+	{
+		if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
+		{
+			// restore value
+		RESTORE_AND_ERROR:
+			if (undoBuffer)
+			{
+				if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING)
+				{
+					// special case for STR_String: restore the string
+					STR_String *var = reinterpret_cast<STR_String*>(ptr);
+					*var = reinterpret_cast<char*>(undoBuffer);
+				}
+				else
+				{
+					// other field type have direct values
+					memcpy(ptr, undoBuffer, bufferSize);
+				}
+			}
+		FREE_AND_ERROR:
 			if (undoBuffer)
 				free(undoBuffer);
-			return 0;
+			return 1;
 		}
 	}
-	return -1;			
+	if (undoBuffer)
+		free(undoBuffer);
+	return 0;	
 }
 
+
+
 /*------------------------------
  * PyObjectPlus repr		-- representations
 ------------------------------*/
@@ -703,35 +834,65 @@ PyObject *PyObjectPlus::py_repr(void)
 ------------------------------*/
 bool PyObjectPlus::isA(PyTypeObject *T)		// if called with a Type, use "typename"
 {
-  return isA(T->tp_name);
+	int i;
+	PyParentObject  P;
+	PyParentObject *Ps = GetParents();
+
+	for (P = Ps[i=0]; P != NULL; P = Ps[i++])
+		if (P==T)
+			return true;
+
+	return false;
 }
 
 
 bool PyObjectPlus::isA(const char *mytypename)		// check typename of each parent
 {
-  int i;
-  PyParentObject  P;
-  PyParentObject *Ps = GetParents();
+	int i;
+	PyParentObject  P;
+	PyParentObject *Ps = GetParents();
   
-  for (P = Ps[i=0]; P != NULL; P = Ps[i++])
-  {
-      if (strcmp(P->tp_name, mytypename)==0)
-		  return true;
-  }
-	
-  return false;
+	for (P = Ps[i=0]; P != NULL; P = Ps[i++])
+		if (strcmp(P->tp_name, mytypename)==0)
+			return true;
+
+	return false;
+}
+
+PyObject *PyObjectPlus::PyisA(PyObject *value)		// Python wrapper for isA
+{
+	if (PyType_Check(value)) {
+		return PyBool_FromLong(isA((PyTypeObject *)value));
+	} else if (PyString_Check(value)) {
+		return PyBool_FromLong(isA(PyString_AsString(value)));
+	}
+    PyErr_SetString(PyExc_TypeError, "object.isA(value): expected a type or a string");
+    return NULL;	
 }
 
-PyObject *PyObjectPlus::Py_isA(PyObject *value)		// Python wrapper for isA
+
+void PyObjectPlus::ProcessReplica()
 {
-  if (!PyString_Check(value)) {
-    PyErr_SetString(PyExc_TypeError, "expected a string");
-    return NULL;
-  }
-  if(isA(PyString_AsString(value)))
-    Py_RETURN_TRUE;
-  else
-    Py_RETURN_FALSE;
+	/* Clear the proxy, will be created again if needed with GetProxy()
+	 * otherwise the PyObject will point to the wrong reference */
+	m_proxy= NULL;
+}
+
+/* Sometimes we might want to manually invalidate a BGE type even if
+ * it hasnt been released by the BGE, say for example when an object
+ * is removed from a scene, accessing it may cause problems.
+ * 
+ * In this case the current proxy is made invalid, disowned,
+ * and will raise an error on access. However if python can get access
+ * to this class again it will make a new proxy and work as expected.
+ */
+void PyObjectPlus::InvalidateProxy()		// check typename of each parent
+{
+	if(m_proxy) { 
+		BGE_PROXY_REF(m_proxy)=NULL;
+		Py_DECREF(m_proxy);
+		m_proxy= NULL;
+	}
 }
 
 /* Utility function called by the macro py_getattro_up()
@@ -742,27 +903,133 @@ PyObject *PyObjectPlus::Py_isA(PyObject *value)		// Python wrapper for isA
  * Other then making dir() useful the value returned from __dict__() is not useful
  * since every value is a Py_None
  * */
-PyObject *_getattr_dict(PyObject *pydict, PyMethodDef *meth, PyAttributeDef *attrdef)
+PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict)
 {
     if(pydict==NULL) { /* incase calling __dict__ on the parent of this object raised an error */
     	PyErr_Clear();
     	pydict = PyDict_New();
     }
 	
-    if(meth) {
-		for (; meth->ml_name != NULL; meth++) {
-			PyDict_SetItemString(pydict, meth->ml_name, Py_None);
+	PyDict_Update(pydict, tp_dict);
+	return pydict;
+}
+
+
+
+PyObject *PyObjectPlus::GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp)
+{
+	if (self->m_proxy==NULL)
+	{
+		self->m_proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp);
+		BGE_PROXY_PYOWNS(self->m_proxy) = false;
+	}
+	//PyObject_Print(self->m_proxy, stdout, 0);
+	//printf("ref %d\n", self->m_proxy->ob_refcnt);
+	
+	BGE_PROXY_REF(self->m_proxy) = self; /* Its possible this was set to NULL, so set it back here */
+	Py_INCREF(self->m_proxy); /* we own one, thos ones fore the return */
+	return self->m_proxy;
+}
+
+PyObject *PyObjectPlus::NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns)
+{
+	if (self->m_proxy)
+	{
+		if(py_owns)
+		{	/* Free */
+			BGE_PROXY_REF(self->m_proxy) = NULL;
+			Py_DECREF(self->m_proxy);
+			self->m_proxy= NULL;
 		}
+		else {
+			Py_INCREF(self->m_proxy);
+			return self->m_proxy;
+		}
+		
 	}
 	
-    if(attrdef) {
-		for (; attrdef->m_name != NULL; attrdef++) {
-			PyDict_SetItemString(pydict, attrdef->m_name, Py_None);
+	GetProxy_Ext(self, tp);
+	if(py_owns) {
+		BGE_PROXY_PYOWNS(self->m_proxy) = py_owns;
+		Py_DECREF(self->m_proxy); /* could avoid thrashing here but for now its ok */
+	}
+	return self->m_proxy;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+/* deprecation warning management */
+
+bool PyObjectPlus::m_ignore_deprecation_warnings(false);
+void PyObjectPlus::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
+{
+	m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
+}
+
+void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* new_way)
+{
+	{
+		printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
+		
+		// import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
+		
+		PyObject *getframe, *frame;
+		PyObject *f_lineno, *f_code, *co_filename;
+		
+		getframe = PySys_GetObject((char *)"_getframe"); // borrowed
+		if (getframe) {
+			frame = PyObject_CallObject(getframe, NULL);
+			if (frame) {
+				f_lineno= PyObject_GetAttrString(frame, "f_lineno");
+				f_code= PyObject_GetAttrString(frame, "f_code");
+				if (f_lineno && f_code) {
+					co_filename= PyObject_GetAttrString(f_code, "co_filename");
+					if (co_filename) {
+						
+						printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
+						
+						Py_DECREF(f_lineno);
+						Py_DECREF(f_code);
+						Py_DECREF(co_filename);
+						Py_DECREF(frame);
+						return;
+					}
+				}
+				
+				Py_XDECREF(f_lineno);
+				Py_XDECREF(f_code);
+				Py_DECREF(frame);
+			}
+			
 		}
+		PyErr_Clear();
+		printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n");
 	}
+}
 
-	return pydict;
+void PyObjectPlus::ClearDeprecationWarning()
+{
+	WarnLink *wlink_next;
+	WarnLink *wlink = GetDeprecationWarningLinkFirst();
+	
+	while(wlink)
+	{
+		wlink->warn_done= false; /* no need to NULL the link, its cleared before adding to the list next time round */
+		wlink_next= reinterpret_cast<WarnLink *>(wlink->link);
+		wlink->link= NULL;
+		wlink= wlink_next;
+	}
+	NullDeprecationWarning();
 }
 
+WarnLink*		m_base_wlink_first= NULL;
+WarnLink*		m_base_wlink_last= NULL;
+
+WarnLink*		PyObjectPlus::GetDeprecationWarningLinkFirst(void) {return m_base_wlink_first;}
+WarnLink*		PyObjectPlus::GetDeprecationWarningLinkLast(void) {return m_base_wlink_last;}
+void			PyObjectPlus::SetDeprecationWarningFirst(WarnLink* wlink) {m_base_wlink_first= wlink;}
+void			PyObjectPlus::SetDeprecationWarningLinkLast(WarnLink* wlink) {m_base_wlink_last= wlink;}
+void			PyObjectPlus::NullDeprecationWarning() {m_base_wlink_first= m_base_wlink_last= NULL;}
+
 #endif //NO_EXP_PYTHON_EMBEDDING
 
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index 77963c092ebf0de353ddca5746c2784c79e70689..45797fe797564400823d1fcd25d0eaf6792a25b8 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -38,11 +38,30 @@
 
 #include "KX_Python.h"
 #include "STR_String.h"
+#include "MT_Vector3.h"
+#include "SG_QList.h"
 
 /*------------------------------
  * Python defines
 ------------------------------*/
 
+
+
+#if PY_VERSION_HEX > 0x03000000
+#define PyString_FromString PyUnicode_FromString
+#define PyString_FromFormat PyUnicode_FromFormat
+#define PyString_Check PyUnicode_Check
+#define PyString_Size PyUnicode_GetSize
+
+#define PyInt_FromLong PyLong_FromSsize_t
+#define PyInt_AsLong PyLong_AsSsize_t
+#define PyString_AsString _PyUnicode_AsString
+#define PyInt_Check PyLong_Check
+#define PyInt_AS_LONG PyLong_AsLong // TODO - check this one
+#endif
+
+
+
 /*
    Py_RETURN_NONE
    Python 2.4 macro.
@@ -50,18 +69,19 @@
    also in api2_2x/gen_utils.h 
 */
 #ifndef Py_RETURN_NONE
-#define Py_RETURN_NONE  return Py_BuildValue("O", Py_None)
+#define Py_RETURN_NONE  return Py_INCREF(Py_None), Py_None
 #endif
 #ifndef Py_RETURN_FALSE
-#define Py_RETURN_FALSE  return PyBool_FromLong(0)
+#define Py_RETURN_FALSE  return Py_INCREF(Py_False), Py_False
 #endif
 #ifndef Py_RETURN_TRUE
-#define Py_RETURN_TRUE  return PyBool_FromLong(1)
+#define Py_RETURN_TRUE  return Py_INCREF(Py_True), Py_True
 #endif
 
 /*  for pre Py 2.5 */
 #if PY_VERSION_HEX < 0x02050000
 typedef int Py_ssize_t;
+typedef Py_ssize_t (*lenfunc)(PyObject *);
 #define PY_SSIZE_T_MAX INT_MAX
 #define PY_SSIZE_T_MIN INT_MIN
 #define PY_METHODCHAR char *
@@ -74,11 +94,56 @@ typedef int Py_ssize_t;
 
 #include "descrobject.h"
 
+
 static inline void Py_Fatal(const char *M) {
 	fprintf(stderr, "%s\n", M);
 	exit(-1);
 };
 
+
+/* Use with ShowDeprecationWarning macro */
+typedef struct {
+	bool warn_done;
+	void *link;
+} WarnLink;
+
+#define ShowDeprecationWarning(old_way, new_way) \
+{ \
+	static WarnLink wlink = {false, NULL}; \
+	if ((m_ignore_deprecation_warnings || wlink.warn_done)==0) \
+	{ \
+		ShowDeprecationWarning_func(old_way, new_way); \
+		WarnLink *wlink_last= GetDeprecationWarningLinkLast(); \
+		ShowDeprecationWarning_func(old_way, new_way); \
+		wlink.warn_done = true; \
+		wlink.link = NULL; \
+	 \
+		if(wlink_last) { \
+			wlink_last->link= (void *)&(wlink); \
+			SetDeprecationWarningLinkLast(&(wlink)); \
+		} else { \
+			SetDeprecationWarningFirst(&(wlink)); \
+			SetDeprecationWarningLinkLast(&(wlink)); \
+		} \
+	} \
+} \
+
+
+
+typedef struct {
+	PyObject_HEAD		/* required python macro   */
+	class PyObjectPlus *ref;
+	bool py_owns;
+} PyObjectPlus_Proxy;
+
+#define BGE_PROXY_ERROR_MSG "Blender Game Engine data has been freed, cannot use this python variable"
+#define BGE_PROXY_REF(_self) (((PyObjectPlus_Proxy *)_self)->ref)
+#define BGE_PROXY_PYOWNS(_self) (((PyObjectPlus_Proxy *)_self)->py_owns)
+
+/* Note, sometimes we dont care what BGE type this is as long as its a proxy */
+#define BGE_PROXY_CHECK_TYPE(_self) ((_self)->ob_type->tp_dealloc == py_base_dealloc)
+
+
 								// This must be the first line of each 
 								// PyC++ class
 #define Py_Header \
@@ -88,29 +153,71 @@ static inline void Py_Fatal(const char *M) {
   static PyAttributeDef Attributes[]; \
   static PyParentObject Parents[]; \
   virtual PyTypeObject *GetType(void) {return &Type;}; \
-  virtual PyParentObject *GetParents(void) {return Parents;}
+  virtual PyParentObject *GetParents(void) {return Parents;} \
+  virtual PyObject *GetProxy() {return GetProxy_Ext(this, &Type);}; \
+  virtual PyObject *NewProxy(bool py_owns) {return NewProxy_Ext(this, &Type, py_owns);}; \
+
 
 
 
 								// This defines the py_getattro_up macro
 								// which allows attribute and method calls
 								// to be properly passed up the hierarchy.
+								// 
+								// Note, PyDict_GetItem() WONT set an exception!
+								// let the py_base_getattro function do this.
 
 #define py_getattro_up(Parent) \
-	PyObject *rvalue; \
+	\
 	PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
 	 \
-	if (descr == NULL) { \
-		PyErr_Clear(); \
-		rvalue = Parent::py_getattro(attr); \
+	if(descr) { \
+		if (PyCObject_Check(descr)) { \
+			return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr)); \
+		} else if (descr->ob_type->tp_descr_get) { \
+			return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \
+		} else { \
+			return NULL; \
+		} \
 	} else { \
-		rvalue= PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, (PyObject *)this); \
-	} \
-	\
-	if (strcmp(PyString_AsString(attr), "__dict__")==0) {\
-		rvalue = _getattr_dict(rvalue, Methods, Attributes); \
-	} \
-	return rvalue; \
+		return Parent::py_getattro(attr); \
+	}
+
+#define py_getattro_dict_up(Parent) \
+	return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict);
+
+/*
+ * nonzero values are an error for setattr
+ * however because of the nested lookups we need to know if the errors
+ * was because the attribute didnt exits of if there was some problem setting the value
+ */
+
+#define PY_SET_ATTR_COERCE_FAIL	 2
+#define PY_SET_ATTR_FAIL		 1
+#define PY_SET_ATTR_MISSING		-1
+#define PY_SET_ATTR_SUCCESS		 0
+
+#define py_setattro_up(Parent) \
+	PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
+	 \
+	if(descr) { \
+		if (PyCObject_Check(descr)) { \
+			const PyAttributeDef* attrdef= reinterpret_cast<const PyAttributeDef *>(PyCObject_AsVoidPtr(descr)); \
+			if (attrdef->m_access == KX_PYATTRIBUTE_RO) { \
+				PyErr_Format(PyExc_AttributeError, "\"%s\" is read only", PyString_AsString(attr)); \
+				return PY_SET_ATTR_FAIL; \
+			} \
+			else { \
+				return py_set_attrdef((void *)this, attrdef, value); \
+			} \
+		} else { \
+			PyErr_Format(PyExc_AttributeError, "\"%s\" cannot be set", PyString_AsString(attr)); \
+			return PY_SET_ATTR_FAIL; \
+		} \
+	} else { \
+		PyErr_Clear(); \
+		return Parent::py_setattro(attr, value); \
+	}
 
 
 /**
@@ -118,54 +225,62 @@ static inline void Py_Fatal(const char *M) {
  * macro is one that also requires a documentation string
  */
 #define KX_PYMETHOD(class_name, method_name)			\
-	PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \
+	PyObject* Py##method_name(PyObject* args, PyObject* kwds); \
 	static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \
-		return ((class_name*) self)->Py##method_name(self, args, kwds);		\
+		if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \
+		return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args, kwds);		\
 	}; \
 
 #define KX_PYMETHOD_VARARGS(class_name, method_name)			\
-	PyObject* Py##method_name(PyObject* self, PyObject* args); \
+	PyObject* Py##method_name(PyObject* args); \
 	static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
-		return ((class_name*) self)->Py##method_name(self, args);		\
+		if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \
+		return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args);		\
 	}; \
 
 #define KX_PYMETHOD_NOARGS(class_name, method_name)			\
-	PyObject* Py##method_name(PyObject* self); \
+	PyObject* Py##method_name(); \
 	static PyObject* sPy##method_name( PyObject* self) { \
-		return ((class_name*) self)->Py##method_name(self);		\
+		if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \
+		return ((class_name*)BGE_PROXY_REF(self))->Py##method_name();		\
 	}; \
 	
 #define KX_PYMETHOD_O(class_name, method_name)			\
-	PyObject* Py##method_name(PyObject* self, PyObject* value); \
+	PyObject* Py##method_name(PyObject* value); \
 	static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \
-		return ((class_name*) self)->Py##method_name(self, value);		\
+		if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(value) - " BGE_PROXY_ERROR_MSG); return NULL; } \
+		return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(value);		\
 	}; \
 
 #define KX_PYMETHOD_DOC(class_name, method_name)			\
-	PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \
+	PyObject* Py##method_name(PyObject* args, PyObject* kwds); \
 	static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \
-		return ((class_name*) self)->Py##method_name(self, args, kwds);		\
+		if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(...) - " BGE_PROXY_ERROR_MSG); return NULL; } \
+		return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args, kwds);		\
 	}; \
     static const char method_name##_doc[]; \
 
 #define KX_PYMETHOD_DOC_VARARGS(class_name, method_name)			\
-	PyObject* Py##method_name(PyObject* self, PyObject* args); \
+	PyObject* Py##method_name(PyObject* args); \
 	static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
-		return ((class_name*) self)->Py##method_name(self, args);		\
+		if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(...) - " BGE_PROXY_ERROR_MSG); return NULL; } \
+		return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args);		\
 	}; \
     static const char method_name##_doc[]; \
 
 #define KX_PYMETHOD_DOC_O(class_name, method_name)			\
-	PyObject* Py##method_name(PyObject* self, PyObject* value); \
+	PyObject* Py##method_name(PyObject* value); \
 	static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \
-		return ((class_name*) self)->Py##method_name(self, value);		\
+		if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(value) - " BGE_PROXY_ERROR_MSG); return NULL; } \
+		return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(value);		\
 	}; \
     static const char method_name##_doc[]; \
 
 #define KX_PYMETHOD_DOC_NOARGS(class_name, method_name)			\
-	PyObject* Py##method_name(PyObject* self); \
+	PyObject* Py##method_name(); \
 	static PyObject* sPy##method_name( PyObject* self) { \
-		return ((class_name*) self)->Py##method_name(self);		\
+		if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \
+		return ((class_name*)BGE_PROXY_REF(self))->Py##method_name();		\
 	}; \
     static const char method_name##_doc[]; \
 
@@ -188,19 +303,19 @@ static inline void Py_Fatal(const char *M) {
  */
 #define KX_PYMETHODDEF_DOC(class_name, method_name, doc_string) \
 const char class_name::method_name##_doc[] = doc_string; \
-PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*)
+PyObject* class_name::Py##method_name(PyObject* args, PyObject*)
 
 #define KX_PYMETHODDEF_DOC_VARARGS(class_name, method_name, doc_string) \
 const char class_name::method_name##_doc[] = doc_string; \
-PyObject* class_name::Py##method_name(PyObject*, PyObject* args)
+PyObject* class_name::Py##method_name(PyObject* args)
 
 #define KX_PYMETHODDEF_DOC_O(class_name, method_name, doc_string) \
 const char class_name::method_name##_doc[] = doc_string; \
-PyObject* class_name::Py##method_name(PyObject*, PyObject* value)
+PyObject* class_name::Py##method_name(PyObject* value)
 
 #define KX_PYMETHODDEF_DOC_NOARGS(class_name, method_name, doc_string) \
 const char class_name::method_name##_doc[] = doc_string; \
-PyObject* class_name::Py##method_name(PyObject*)
+PyObject* class_name::Py##method_name()
 
 /**
  * Attribute management
@@ -214,6 +329,7 @@ enum KX_PYATTRIBUTE_TYPE {
 	KX_PYATTRIBUTE_TYPE_STRING,
 	KX_PYATTRIBUTE_TYPE_DUMMY,
 	KX_PYATTRIBUTE_TYPE_FUNCTION,
+	KX_PYATTRIBUTE_TYPE_VECTOR,
 };
 
 enum KX_PYATTRIBUTE_ACCESS {
@@ -251,97 +367,105 @@ typedef struct KX_PYATTRIBUTE_DEF {
 		int *m_intPtr;
 		float *m_floatPtr;
 		STR_String *m_stringPtr;
+		MT_Vector3 *m_vectorPtr;
 	} m_typeCheck;
 } PyAttributeDef;
 
 #define KX_PYATTRIBUTE_DUMMY(name) \
-	{ name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL} }
 
 #define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
 
 // enum field cannot be mapped to pointer (because we would need a pointer for each enum)
 // use field size to verify mapping at runtime only, assuming enum size is equal to int size.
 #define KX_PYATTRIBUTE_ENUM_RW(name,min,max,clamp,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_ENUM_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_ENUM_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL} }
 
 #define KX_PYATTRIBUTE_SHORT_RW(name,min,max,clamp,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
 // SHORT_LIST
 #define KX_PYATTRIBUTE_SHORT_LIST_RW(name,min,max,clamp,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_SHORT_LIST_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
 
 #define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_INT_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
 // INT_LIST
 #define KX_PYATTRIBUTE_INT_LIST_RW(name,min,max,clamp,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_INT_LIST_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
 
 // always clamp for float
 #define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
 #define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
 #define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
 #define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL} }
 #define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL} }
 #define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \
-	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL} }
 
 #define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
 #define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,clamp,object,field,function) \
-	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
 #define KX_PYATTRIBUTE_STRING_RO(name,object,field) \
-	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+	{ name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
+
+#define KX_PYATTRIBUTE_VECTOR_RW(name,min,max,object,field) \
+	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field} }
+#define KX_PYATTRIBUTE_VECTOR_RW_CHECK(name,min,max,clamp,object,field,function) \
+	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field} }
+#define KX_PYATTRIBUTE_VECTOR_RO(name,object,field) \
+	{ name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field} }
 
 #define KX_PYATTRIBUTE_RW_FUNCTION(name,object,getfunction,setfunction) \
-	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_RO_FUNCTION(name,object,getfunction) \
-	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_ARRAY_RW_FUNCTION(name,object,length,getfunction,setfunction) \
-	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL} }
 #define KX_PYATTRIBUTE_ARRAY_RO_FUNCTION(name,object,length,getfunction) \
-	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} }
+	{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL} }
 
 
 /*------------------------------
@@ -349,62 +473,87 @@ typedef struct KX_PYATTRIBUTE_DEF {
 ------------------------------*/
 typedef PyTypeObject * PyParentObject;				// Define the PyParent Object
 
-class PyObjectPlus : public PyObject 
+// By making SG_QList the ultimate parent for PyObjectPlus objects, it
+// allows to put them in 2 different dynamic lists at the same time
+// The use of these links is interesting because they free of memory allocation
+// but it's very important not to mess up with them. If you decide that 
+// the SG_QList or SG_DList component is used for something for a certain class,
+// they cannot can be used for anything else at a parent level!
+// What these lists are and what they are used for must be carefully documented
+// at the level where they are used.
+// DON'T MAKE ANY USE OF THESE LIST AT THIS LEVEL, they are already used
+// at SCA_IActuator, SCA_ISensor, SCA_IController level which rules out the
+// possibility to use them at SCA_ILogicBrick, CValue and PyObjectPlus level.
+class PyObjectPlus : public SG_QList
 {				// The PyObjectPlus abstract class
 	Py_Header;							// Always start with Py_Header
 	
 public:
 	PyObjectPlus(PyTypeObject *T);
+
+	PyObject *m_proxy; /* actually a PyObjectPlus_Proxy */
 	
 	virtual ~PyObjectPlus();					// destructor
-	static void PyDestructor(PyObject *P)				// python wrapper
-	{  
-		delete ((PyObjectPlus *) P);  
-	};
 	
-//	void INCREF(void) {
-//		  Py_INCREF(this);
-//	  };				// incref method
-//	void DECREF(void) {
-//		  Py_DECREF(this);
-//	  };				// decref method
+	/* These static functions are referenced by ALL PyObjectPlus_Proxy types
+	 * they take the C++ reference from the PyObjectPlus_Proxy and call
+	 * its own virtual py_getattro, py_setattro etc. functions.
+	 */
+	static void			py_base_dealloc(PyObject *self);
+	static  PyObject*		py_base_getattro(PyObject * self, PyObject *attr);
+	static  int			py_base_setattro(PyObject *self, PyObject *attr, PyObject *value);
+	static PyObject*		py_base_repr(PyObject *self);
+
+	/* These are all virtual python methods that are defined in each class
+	 * Our own fake subclassing calls these on each class, then calls the parent */
+	virtual PyObject*		py_getattro(PyObject *attr);
+	virtual PyObject*		py_getattro_dict();
+	virtual int			py_delattro(PyObject *attr);
+	virtual int			py_setattro(PyObject *attr, PyObject *value);
+	virtual PyObject*		py_repr(void);
+
+	static PyObject*		py_get_attrdef(void *self, const PyAttributeDef *attrdef);
+	static int				py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value);
 	
-	virtual PyObject *py_getattro(PyObject *attr);			// py_getattro method
-	static  PyObject *py_base_getattro(PyObject * PyObj, PyObject *attr) 	// This should be the entry in Type. 
-	{
-		return ((PyObjectPlus*) PyObj)->py_getattro(attr); 
-	}
-	static PyObject *py_getattro_self(const PyAttributeDef attrlist[], void *self, PyObject *attr);
-	static int py_setattro_self(const PyAttributeDef attrlist[], void *self, PyObject *attr, PyObject *value);
+	/* isA() methods, shonky replacement for pythons issubclass()
+	 * which we cant use because we have our own subclass system  */
+	bool isA(PyTypeObject *T);
+	bool isA(const char *mytypename);
 	
-	virtual int py_delattro(PyObject *attr);
-	virtual int py_setattro(PyObject *attr, PyObject *value);		// py_setattro method
-	static  int py_base_setattro(PyObject *PyObj, 			// This should be the entry in Type. 
-				PyObject *attr, 
-				PyObject *value)
-	{ 
-		if (value==NULL)
-			return ((PyObjectPlus*) PyObj)->py_delattro(attr);
-		return ((PyObjectPlus*) PyObj)->py_setattro(attr, value);  
-	}
+	KX_PYMETHOD_O(PyObjectPlus,isA);
 	
-	virtual PyObject *py_repr(void);				// py_repr method
-	static  PyObject *py_base_repr(PyObject *PyObj)			// This should be the entry in Type.
-	{
-		return ((PyObjectPlus*) PyObj)->py_repr();  
-	}
+	/* Kindof dumb, always returns True, the false case is checked for, before this function gets accessed */
+	static PyObject*	pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	
+	static PyObject *GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp);
+	static PyObject *NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns);
+	
+	void	InvalidateProxy();
+	
+	/**
+	 * Makes sure any internal data owned by this class is deep copied.
+	 */
+	virtual void ProcessReplica();
+	
+	
+	static bool			m_ignore_deprecation_warnings;
+	
+	static	WarnLink*		GetDeprecationWarningLinkFirst(void);
+	static	WarnLink*		GetDeprecationWarningLinkLast(void);
+	static	void			SetDeprecationWarningFirst(WarnLink* wlink);
+	static	void			SetDeprecationWarningLinkLast(WarnLink* wlink);
+	static void			NullDeprecationWarning();
+	
+	/** enable/disable display of deprecation warnings */
+	static void			SetDeprecationWarnings(bool ignoreDeprecationWarnings);
+ 	/** Shows a deprecation warning */
+	static void			ShowDeprecationWarning_func(const char* method,const char* prop);
+	static void			ClearDeprecationWarning();
 	
-									// isA methods
-	bool isA(PyTypeObject *T);
-	bool isA(const char *mytypename);
-	PyObject *Py_isA(PyObject *value);
-	static PyObject *sPy_isA(PyObject *self, PyObject *value)
-	{
-		return ((PyObjectPlus*)self)->Py_isA(value);
-	}
 };
 
-PyObject *_getattr_dict(PyObject *pydict, PyMethodDef *meth, PyAttributeDef *attrdef);
+
+PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict);
 
 #endif //  _adr_py_lib_h_
 
diff --git a/source/gameengine/Expressions/SConscript b/source/gameengine/Expressions/SConscript
index 3d855d406231b708437723d901daabc31a170c7e..12d4a163c86523d2826e9545189142b21c28889f 100644
--- a/source/gameengine/Expressions/SConscript
+++ b/source/gameengine/Expressions/SConscript
@@ -3,7 +3,7 @@ Import ('env')
 
 sources = env.Glob('*.cpp')
 
-incs ='. #source/kernel/gen_system #intern/string #intern/moto/include'
+incs ='. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/SceneGraph'
 incs += ' ' + env['BF_PYTHON_INC']
 
 cxxflags = []
diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/StringValue.cpp
index 1ef8c5629a00a906862c6777b42403c4bf260c37..a7033fcf11ce82bbd746d4eb927889f7c8c7b530 100644
--- a/source/gameengine/Expressions/StringValue.cpp
+++ b/source/gameengine/Expressions/StringValue.cpp
@@ -34,7 +34,7 @@ effect: constructs a new CStringValue
 	m_strString = "[Illegal String constructor call]";
 }
 
-CStringValue::CStringValue(STR_String txt,STR_String name,AllocationTYPE alloctype)
+CStringValue::CStringValue(const char *txt,const char *name,AllocationTYPE alloctype)
 /*
 pre:
 effect: constructs a new CStringValue containing text txt
@@ -113,7 +113,7 @@ this object
 
 
 
-float CStringValue::GetNumber()
+double CStringValue::GetNumber()
 {
 	return -1;
 }
@@ -133,7 +133,7 @@ bool CStringValue::IsEqual(const STR_String & other)
 CValue* CStringValue::GetReplica()
 { 
 	CStringValue* replica = new CStringValue(*this);
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	return replica;
 };
 
diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h
index b824d4ef86d318cd56d3cf7c1b1092938b3c643f..52f8a580f4d6a3a7b7e6a6a5233bb1357c45006c 100644
--- a/source/gameengine/Expressions/StringValue.h
+++ b/source/gameengine/Expressions/StringValue.h
@@ -26,14 +26,14 @@ class CStringValue : public CPropValue
 public:
 	/// Construction / destruction
 	CStringValue();
-	CStringValue (STR_String txt, STR_String name , AllocationTYPE alloctype = CValue::HEAPVALUE);
+	CStringValue (const char *txt, const char *name , AllocationTYPE alloctype = CValue::HEAPVALUE);
 
 	virtual ~CStringValue() {
 	};
 	/// CValue implementation
 	virtual bool		IsEqual(const STR_String & other);
 	virtual const STR_String &	GetText();
-	virtual float		GetNumber();
+	virtual double		GetNumber();
 	
 	virtual	CValue*		Calc(VALUE_OPERATOR op, CValue *val);
 	virtual	CValue*		CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index 8b910b9038b3f6bf86db7c5a907697986c33f66f..83deeef91a3a0d10898d8bb76fbe50651de6458c 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -32,125 +32,27 @@
 //////////////////////////////////////////////////////////////////////
 
 double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
-bool CValue::m_ignore_deprecation_warnings(false);
 
 #ifndef NO_EXP_PYTHON_EMBEDDING
 
-PyObject* cvalue_add(PyObject*v, PyObject*w)
-{
-	return  ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_sub(PyObject*v, PyObject*w)
-{
-	return  ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_mul(PyObject*v, PyObject*w)
-{
-	return  ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_div(PyObject*v, PyObject*w)
-{
-	return  ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_mod(PyObject*v, PyObject*w)
-{
-	return  ((CValue*)v)->Calc(VALUE_MOD_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_neg(PyObject*v)
-{
-	return  ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
-}
-PyObject* cvalue_pos(PyObject*v)
-{
-	return  ((CValue*)v)->Calc(VALUE_POS_OPERATOR,(CValue*)v);
-}
-
-
-int MyPyCompare (PyObject* v,PyObject* w)
-{
-	CValue* eqval =  ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w);
-	STR_String txt = eqval->GetText();
-	eqval->Release();
-	if (txt=="TRUE")
-		return 0;
-	CValue* lessval =  ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w);
-	txt = lessval->GetText();
-	lessval->Release();
-	if (txt=="TRUE")
-		return -1;
-
-	return 1;
-}
-
-
-int cvalue_coerce(PyObject** pv,PyObject** pw)
-{
-	if (PyInt_Check(*pw)) {
-		double db  = (double)PyInt_AsLong(*pw);
-		*pw = new CIntValue((int) db);
-		Py_INCREF(*pv);
-		return 0;
-	}
-	else if (PyLong_Check(*pw)) {
-		double db = PyLong_AsDouble(*pw);
-		*pw = new CFloatValue(db);
-		Py_INCREF(*pv);
-		return 0;
-	}
-	else if (PyFloat_Check(*pw)) {
-		double db = PyFloat_AsDouble(*pw);
-		*pw = new CFloatValue(db);
-		Py_INCREF(*pv);
-		return 0;
-	} else if (PyString_Check(*pw)) {
-		const STR_String str = PyString_AsString(*pw);
-		*pw = new CStringValue(str,"");
-		Py_INCREF(*pv);
-		return 0;
-	}
-	return 1; /* Can't do it */
-
-}
-static PyNumberMethods cvalue_as_number = {
-	(binaryfunc)cvalue_add, /*nb_add*/
-	(binaryfunc)cvalue_sub, /*nb_subtract*/
-	(binaryfunc)cvalue_mul, /*nb_multiply*/
-	(binaryfunc)cvalue_div, /*nb_divide*/
-	(binaryfunc)cvalue_mod, /*nb_remainder*/
-	0,//(binaryfunc)cvalue_divmod,	/*nb_divmod*/
-	0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
-	(unaryfunc)cvalue_neg, /*nb_negative*/
-	0,//(unaryfunc)cvalue_pos, /*nb_positive*/
-	0,//(unaryfunc)cvalue_abs, /*nb_absolute*/
-	0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/
-	0,		/*nb_invert*/
-	0,		/*nb_lshift*/
-	0,		/*nb_rshift*/
-	0,		/*nb_and*/
-	0,		/*nb_xor*/
-	0,		/*nb_or*/
-	(coercion)cvalue_coerce, /*nb_coerce*/
-	0,//(unaryfunc)cvalue_int, /*nb_int*/
-	0,//(unaryfunc)cvalue_long, /*nb_long*/
-	0,//(unaryfunc)cvalue_float, /*nb_float*/
-	0,		/*nb_oct*/
-	0,		/*nb_hex*/
-};
-
-
 PyTypeObject CValue::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"CValue",
-	sizeof(CValue),
+	sizeof(PyObjectPlus_Proxy),
+	0,
+	py_base_dealloc,
 	0,
-	PyDestructor,
 	0,
 	0,
 	0,
-	&MyPyCompare,
 	py_base_repr,
-	&cvalue_as_number,
+	0,
 	0,0,0,0,0,
 	py_base_getattro,
 	py_base_setattro,
@@ -169,7 +71,7 @@ PyMethodDef CValue::Methods[] = {
 	{NULL,NULL} //Sentinel
 };
 
-PyObject* CValue::PyGetName(PyObject* self)
+PyObject* CValue::PyGetName()
 {
 	return PyString_FromString(this->GetName());
 }
@@ -389,20 +291,24 @@ CValue* CValue::GetProperty(const char *inName)
 //
 // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
 //
-STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext)
+const STR_String& CValue::GetPropertyText(const STR_String & inName,const char *deftext)
 {
+	const static STR_String sEmpty("");
+
 	CValue *property = GetProperty(inName);
 	if (property)
 		return property->GetText();
+	else if (deftext)
+		return STR_String(deftext);
 	else
-		return deftext;//String::sEmpty;
+		return sEmpty;
 }
 
 float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
 {
 	CValue *property = GetProperty(inName);
 	if (property)
-		return property->GetNumber();
+		return property->GetNumber(); 
 	else
 		return defnumber;
 }
@@ -436,6 +342,8 @@ vector<STR_String> CValue::GetPropertyNames()
 {
 	vector<STR_String> result;
 	if(!m_pNamedPropertyArray) return result;
+	result.reserve(m_pNamedPropertyArray->size());
+	
 	std::map<STR_String,CValue*>::iterator it;
 	for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
 	{
@@ -539,27 +447,6 @@ int CValue::GetPropertyCount()
 }
 
 
-
-
-
-void CValue::CloneProperties(CValue *replica)
-{
-	
-	if (m_pNamedPropertyArray)
-	{
-		replica->m_pNamedPropertyArray=NULL;
-		std::map<STR_String,CValue*>::iterator it;
-		for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
-		{
-			CValue *val = (*it).second->GetReplica();
-			replica->SetProperty((*it).first,val);
-			val->Release();
-		}
-	}
-
-	
-}
-
 double*		CValue::GetVector3(bool bGetTransformedVec)
 {
 	assertd(false); // don;t get vector from me
@@ -570,49 +457,12 @@ double*		CValue::GetVector3(bool bGetTransformedVec)
 /*---------------------------------------------------------------------------------------------------------------------
 	Reference Counting
 ---------------------------------------------------------------------------------------------------------------------*/
-//
-// Add a reference to this value
-//
-CValue *CValue::AddRef()
-{
-	// Increase global reference count, used to see at the end of the program
-	// if all CValue-derived classes have been dereferenced to 0
-	//debug(gRefCountValue++);
-#ifdef _DEBUG
-	//gRefCountValue++;
-#endif
-	m_refcount++; 
-	return this;
-}
 
 
 
 //
 // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
 //
-int	CValue::Release()
-{
-	// Decrease global reference count, used to see at the end of the program
-	// if all CValue-derived classes have been dereferenced to 0
-	//debug(gRefCountValue--);
-#ifdef _DEBUG
-	//gRefCountValue--;
-#endif
-	// Decrease local reference count, if it reaches 0 the object should be freed
-	if (--m_refcount > 0)
-	{
-		// Reference count normal, return new reference count
-		return m_refcount;
-	}
-	else
-	{
-		// Reference count reached 0, delete ourselves and return 0
-//		MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
-		delete this;
-		return 0;
-	}
-
-}
 
 
 
@@ -633,26 +483,32 @@ void CValue::DisableRefCount()
 
 
 
-void CValue::AddDataToReplica(CValue *replica)
+void CValue::ProcessReplica() /* was AddDataToReplica in 2.48 */
 {
-	replica->m_refcount = 1;
-
-	//register with Python
-	_Py_NewReference(replica);
-
+	m_refcount = 1;
+	
 #ifdef _DEBUG
 	//gRefCountValue++;
 #endif
-	replica->m_ValFlags.RefCountDisabled = false;
+	PyObjectPlus::ProcessReplica();
 
-	replica->ReplicaSetName(GetName());
+	m_ValFlags.RefCountDisabled = false;
 
-	//copy all props
-	CloneProperties(replica);
+	/* copy all props */
+	if (m_pNamedPropertyArray)
+	{
+		std::map<STR_String,CValue*> *pOldArray = m_pNamedPropertyArray;
+		m_pNamedPropertyArray=NULL;
+		std::map<STR_String,CValue*>::iterator it;
+		for (it= pOldArray->begin(); (it != pOldArray->end()); it++)
+		{
+			CValue *val = (*it).second->GetReplica();
+			SetProperty((*it).first,val);
+			val->Release();
+		}
+	}
 }
 
-
-
 CValue*	CValue::FindIdentifier(const STR_String& identifiername)
 {
 
@@ -709,16 +565,21 @@ PyObject*	CValue::py_getattro(PyObject *attr)
 		if (pyconvert)
 			return pyconvert;
 		else
-			return resultattr; // also check if it's already in pythoninterpreter!
+			return resultattr->GetProxy();
 	}
 	py_getattro_up(PyObjectPlus);
 }
 
-CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
+PyObject* CValue::py_getattro_dict() {
+	py_getattro_dict_up(PyObjectPlus);
+}
+
+CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
 {
 
 	CValue* vallie = NULL;
-
+	/* refcounting is broking here! - this crashes anyway, just store a python list for KX_GameObject */
+#if 0
 	if (PyList_Check(pyobj))
 	{
 		CListValue* listval = new CListValue();
@@ -729,7 +590,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
 		for (i=0;i<numitems;i++)
 		{
 			PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
-			CValue* listitemval = ConvertPythonToValue(listitem);
+			CValue* listitemval = ConvertPythonToValue(listitem, error_prefix);
 			if (listitemval)
 			{
 				listval->Add(listitemval);
@@ -749,25 +610,39 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
 		}
 
 	} else
+#endif
 	if (PyFloat_Check(pyobj))
 	{
 		vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
 	} else
 	if (PyInt_Check(pyobj))
 	{
-		vallie = new CIntValue( (int)PyInt_AS_LONG(pyobj) );
+		vallie = new CIntValue( (cInt)PyInt_AS_LONG(pyobj) );
+	} else
+	if (PyLong_Check(pyobj))
+	{
+		vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) );
 	} else
 	if (PyString_Check(pyobj))
 	{
 		vallie = new CStringValue(PyString_AsString(pyobj),"");
 	} else
-	if (pyobj->ob_type==&CValue::Type || pyobj->ob_type==&CListValue::Type)
+	if (BGE_PROXY_CHECK_TYPE(pyobj)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */
 	{
-		vallie = ((CValue*) pyobj)->AddRef();
+		if (BGE_PROXY_REF(pyobj) && (BGE_PROXY_REF(pyobj))->isA(&CValue::Type))
+		{
+			vallie = (static_cast<CValue *>(BGE_PROXY_REF(pyobj)))->AddRef();
+		} else {
+			
+			if(BGE_PROXY_REF(pyobj))	/* this is not a CValue */
+				PyErr_Format(PyExc_TypeError, "%sgame engine python type cannot be used as a property", error_prefix);
+			else						/* PyObjectPlus_Proxy has been removed, cant use */
+				PyErr_Format(PyExc_SystemError, "%s"BGE_PROXY_ERROR_MSG, error_prefix);
+		}
 	} else
 	{
 		/* return an error value from the caller */
-		PyErr_SetString(PyExc_TypeError, "This python value could not be assigned to a game engine property");
+		PyErr_Format(PyExc_TypeError, "%scould convert python value to a game engine property", error_prefix);
 	}
 	return vallie;
 
@@ -776,7 +651,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
 int	CValue::py_delattro(PyObject *attr)
 {
 	char *attr_str= PyString_AsString(attr);
-	if (RemoveProperty(STR_String(attr_str)))
+	if (RemoveProperty(attr_str))
 		return 0;
 	
 	PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str);
@@ -785,25 +660,39 @@ int	CValue::py_delattro(PyObject *attr)
 
 int	CValue::py_setattro(PyObject *attr, PyObject* pyobj)
 {
-	CValue* vallie = ConvertPythonToValue(pyobj);
-	if (vallie)
+	char *attr_str= PyString_AsString(attr);
+	CValue* oldprop = GetProperty(attr_str);	
+	CValue* vallie;
+
+	/* Dissallow python to assign GameObjects, Scenes etc as values */
+	if ((BGE_PROXY_CHECK_TYPE(pyobj)==0) && (vallie = ConvertPythonToValue(pyobj, "cvalue.attr = value: ")))
 	{
-		char *attr_str= PyString_AsString(attr);
-		CValue* oldprop = GetProperty(attr_str);
-		
 		if (oldprop)
 			oldprop->SetValue(vallie);
 		else
 			SetProperty(attr_str, vallie);
 		
 		vallie->Release();
-	} else
-	{
-		return 1; /* ConvertPythonToValue sets the error message */
+	}
+	else {
+		// ConvertPythonToValue sets the error message
+		// must return missing so KX_GameObect knows this
+		// attribute was not a function or bult in attribute,
+		//
+		// CValue attributes override internal attributes
+		// so if it exists as a CValue attribute already,
+		// assume your trying to set it to a differnt CValue attribute
+		// otherwise return PY_SET_ATTR_MISSING so children
+		// classes know they can set it without conflict 
+		
+		if (GetProperty(attr_str))
+			return PY_SET_ATTR_COERCE_FAIL; /* failed to set an existing attribute */
+		else
+			return PY_SET_ATTR_MISSING; /* allow the KX_GameObject dict to set */
 	}
 	
 	//PyObjectPlus::py_setattro(attr,value);
-	return 0;
+	return PY_SET_ATTR_SUCCESS;
 };
 
 PyObject*	CValue::ConvertKeysToPython( void )
@@ -828,15 +717,45 @@ PyObject*	CValue::ConvertKeysToPython( void )
 PyObject*	CValue::PyMake(PyObject* ignored,PyObject* args)
 {
 
-	//if (!PyArg_ParseTuple(args,"s",&name)) return NULL;
+	//if (!PyArg_ParseTuple(args,"s:make",&name)) return NULL;
 	Py_RETURN_NONE;//new CValue();
 }
 */
 
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef CValue_module_def = {
+	{}, /* m_base */
+	"CValue",  /* m_name */
+	0,  /* m_doc */
+	0,  /* m_size */
+	CValueMethods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
+
 extern "C" {
 	void initCValue(void)
 	{
-		Py_InitModule("CValue",CValueMethods);
+		PyObject *m;
+		/* Use existing module where possible
+		 * be careful not to init any runtime vars after this */
+		m = PyImport_ImportModule( "CValue" );
+		if(m) {
+			Py_DECREF(m);
+			//return m;
+		}
+		else {
+			PyErr_Clear();
+		
+#if (PY_VERSION_HEX >= 0x03000000)
+			PyModule_Create(&CValue_module_def);
+#else
+			Py_InitModule("CValue",CValueMethods);
+#endif
+		}
 	}
 }
 
@@ -862,52 +781,3 @@ void CValue::SetValue(CValue* newval)
 	// no one should get here
 	assertd(newval->GetNumber() == 10121969);	
 }
-///////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////
-/* deprecation warning management */
-void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
-{
-	m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
-}
-
-void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way)
-{
-	if (!m_ignore_deprecation_warnings) {
-		printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
-		
-		// import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
-		
-		PyObject *getframe, *frame;
-		PyObject *f_lineno, *f_code, *co_filename;
-		
-		getframe = PySys_GetObject("_getframe"); // borrowed
-		if (getframe) {
-			frame = PyObject_CallObject(getframe, NULL);
-			if (frame) {
-				f_lineno= PyObject_GetAttrString(frame, "f_lineno");
-				f_code= PyObject_GetAttrString(frame, "f_code");
-				if (f_lineno && f_code) {
-					co_filename= PyObject_GetAttrString(f_code, "co_filename");
-					if (co_filename) {
-						
-						printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
-						
-						Py_DECREF(f_lineno);
-						Py_DECREF(f_code);
-						Py_DECREF(co_filename);
-						Py_DECREF(frame);
-						return;
-					}
-				}
-				
-				Py_XDECREF(f_lineno);
-				Py_XDECREF(f_code);
-				Py_DECREF(frame);
-			}
-			
-		}
-		PyErr_Clear();
-		printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n");
-	}
-}
-
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index 7a2816a9778ee6e500865b6108324a0d81f7f79d..e5c95df1c5c8d908a390bd13c837c578eb7e0ce1 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -219,36 +219,18 @@ public:
 	//static PyObject*	PyMake(PyObject*,PyObject*);
 	virtual PyObject *py_repr(void)
 	{
-		return Py_BuildValue("s",(const char*)GetText());
+		return PyString_FromString((const char*)GetText());
 	}
 
 
 
 	virtual PyObject*			py_getattro(PyObject *attr);
-
-	void	SpecialRelease()
-	{
-		int i=0;
-		if (ob_refcnt == 0)
-		{
-			_Py_NewReference(this);
-			
-		} else
-		{
-			i++;
-		}
-		Release();
-	}
-	static void PyDestructor(PyObject *P)				// python wrapper
-	{
-	  ((CValue*)P)->SpecialRelease();
-	};
-
+	virtual PyObject*			py_getattro_dict();
 	virtual PyObject*	ConvertValueToPython() {
 		return NULL;
 	}
 
-	virtual CValue*	ConvertPythonToValue(PyObject* pyobj);
+	virtual CValue*	ConvertPythonToValue(PyObject* pyobj, const char *error_prefix);
 
 
 	virtual int				py_delattro(PyObject *attr);
@@ -277,16 +259,56 @@ public:
 	};
 
 	/// Reference Counting
-	int					GetRefCount()											{ return m_refcount; }
-	virtual	CValue*		AddRef();												// Add a reference to this value
-	virtual int			Release();												// Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+	int					GetRefCount()											
+	{ 
+		return m_refcount; 
+	}
+
+	// Add a reference to this value
+	CValue*				AddRef()												
+	{
+		// Increase global reference count, used to see at the end of the program
+		// if all CValue-derived classes have been dereferenced to 0
+		//debug(gRefCountValue++);
+	#ifdef _DEBUG
+		//gRefCountValue++;
+	#endif
+		m_refcount++; 
+		return this;
+	}
+
+	// Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+	int			Release()								
+	{
+		// Decrease global reference count, used to see at the end of the program
+		// if all CValue-derived classes have been dereferenced to 0
+		//debug(gRefCountValue--);
+	#ifdef _DEBUG
+		//gRefCountValue--;
+	#endif
+		// Decrease local reference count, if it reaches 0 the object should be freed
+		if (--m_refcount > 0)
+		{
+			// Reference count normal, return new reference count
+			return m_refcount;
+		}
+		else
+		{
+			// Reference count reached 0, delete ourselves and return 0
+	//		MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
+			
+			delete this;
+			return 0;
+		}
+	}
+
 
 	/// Property Management
 	virtual void		SetProperty(const STR_String& name,CValue* ioProperty);						// Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
 	virtual void		SetProperty(const char* name,CValue* ioProperty);
 	virtual CValue*		GetProperty(const char* inName);							// Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
 	virtual CValue*		GetProperty(const STR_String & inName);
-	STR_String			GetPropertyText(const STR_String & inName,const STR_String& deftext="");						// Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
+	const STR_String&	GetPropertyText(const STR_String & inName,const char *deftext=NULL);						// Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
 	float				GetPropertyNumber(const STR_String& inName,float defnumber);
 	virtual bool		RemoveProperty(const char *inName);						// Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
 	virtual vector<STR_String>	GetPropertyNames();
@@ -298,7 +320,6 @@ public:
 	virtual CValue*		GetProperty(int inIndex);								// Get property number <inIndex>
 	virtual int			GetPropertyCount();										// Get the amount of properties assiocated with this value
 
-	virtual void		CloneProperties(CValue* replica);
 	virtual CValue*		FindIdentifier(const STR_String& identifiername);
 	/** Set the wireframe color of this value depending on the CSG
 	 * operator type <op>
@@ -306,25 +327,21 @@ public:
 	virtual void		SetColorOperator(VALUE_OPERATOR op);
 
 	virtual const STR_String &	GetText() = 0;
-	virtual float		GetNumber() = 0;
+	virtual double		GetNumber() = 0;
 	double*				ZeroVector() { return m_sZeroVec; };
 	virtual double*		GetVector3(bool bGetTransformedVec = false);
 
-	virtual STR_String	GetName() = 0;											// Retrieve the name of the value
-	virtual void		SetName(STR_String name) = 0;								// Set the name of the value
-	virtual void		ReplicaSetName(STR_String name) = 0;
+	virtual STR_String&	GetName() = 0;											// Retrieve the name of the value
+	virtual void		SetName(const char *name) = 0;								// Set the name of the value
 	/** Sets the value to this cvalue.
 	 * @attention this particular function should never be called. Why not abstract? */
 	virtual void		SetValue(CValue* newval);
 	virtual CValue*		GetReplica() =0;
+	virtual void			ProcessReplica();
 	//virtual CValue*		Copy() = 0;
 	
 	
 	STR_String				op2str(VALUE_OPERATOR op);
-	/** enable/disable display of deprecation warnings */
-	static void			SetDeprecationWarnings(bool ignoreDeprecationWarnings);
- 	/** Shows a deprecation warning */
-	static void			ShowDeprecationWarning(const char* method,const char* prop);
 		
 	// setting / getting flags
 	inline void			SetSelected(bool bSelected)								{ m_ValFlags.Selected = bSelected; }
@@ -345,10 +362,10 @@ public:
 
 	virtual void		SetCustomFlag2(bool bCustomFlag)						{ m_ValFlags.CustomFlag2 = bCustomFlag;};
 	virtual bool		IsCustomFlag2()											{ return m_ValFlags.CustomFlag2;};
-																				
+
 protected:																		
 	virtual void		DisableRefCount();										// Disable reference counting for this value
-	virtual void		AddDataToReplica(CValue* replica);						
+	//virtual void		AddDataToReplica(CValue* replica);						
 	virtual				~CValue();
 private:
 	// Member variables															
@@ -356,7 +373,6 @@ private:
 	ValueFlags			m_ValFlags;												// Frequently used flags in a bitfield (low memoryusage)
 	int					m_refcount;												// Reference Counter	
 	static	double m_sZeroVec[3];	
-	static bool			m_ignore_deprecation_warnings;
 
 };
 
@@ -404,49 +420,28 @@ public:
 #else
 	CPropValue() :
 #endif //NO_EXP_PYTHON_EMBEDDING
-		m_pstrNewName(NULL)
+		m_strNewName()
 
 	{
 	}
 	
 	virtual ~CPropValue()
 	{
-		if (m_pstrNewName)
-		{
-			delete m_pstrNewName;
-			m_pstrNewName = NULL;
-		}
 	}
 	
-	virtual void			SetName(STR_String name) {
-		if (m_pstrNewName)
-		{
-			delete m_pstrNewName;
-			m_pstrNewName = NULL;	
-		}
-		if (name.Length())
-			m_pstrNewName = new STR_String(name);
-	}
-	virtual void			ReplicaSetName(STR_String name) {
-		m_pstrNewName=NULL;
-		if (name.Length())
-			m_pstrNewName = new STR_String(name);
+	virtual void			SetName(const char *name) {
+		m_strNewName = name;
 	}
 	
-	virtual STR_String			GetName() {
+	virtual STR_String&			GetName() {
 		//STR_String namefromprop = GetPropertyText("Name");
 		//if (namefromprop.Length() > 0)
 		//	return namefromprop;
-		
-		if (m_pstrNewName)
-		{
-			return *m_pstrNewName;
-		}
-		return STR_String("");
+		return m_strNewName;
 	};						// name of Value
 	
 protected:
-	STR_String*					m_pstrNewName;				    // Identification
+	STR_String					m_strNewName;				    // Identification
 };
 
 #endif // !defined _VALUEBASECLASS_H
diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/VectorValue.cpp
index bea6902eba88afa45e67529044790723169fa21b..c58c78e6ebedd1d8f5b7ae154a19994dfc3e39ec 100644
--- a/source/gameengine/Expressions/VectorValue.cpp
+++ b/source/gameengine/Expressions/VectorValue.cpp
@@ -48,7 +48,7 @@ CVectorValue::CVectorValue(float x,float y,float z, AllocationTYPE alloctype)
 	m_vec[KX_Z] = m_transformedvec[KX_Z] = z;
 	
 }
-CVectorValue::CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype) {
+CVectorValue::CVectorValue(double vec[],const char *name,AllocationTYPE alloctype) {
 	
 	SetCustomFlag1(false);//FancyOutput=false;
 	
@@ -156,7 +156,7 @@ this object
 	return ret;
 }
 
-float CVectorValue::GetNumber()
+double CVectorValue::GetNumber()
 {
 	return m_vec[KX_X];
 }
@@ -204,7 +204,7 @@ const STR_String & CVectorValue::GetText()
 
 CValue* CVectorValue::GetReplica() { 
 	CVectorValue* replica = new CVectorValue(*this);
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	return replica;
 };
 
diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/VectorValue.h
index 5d9b2a9889195adc0997859ddca09fbd4702b90a..19c7dd30076243d4e48235a7e9672ea4da120388 100644
--- a/source/gameengine/Expressions/VectorValue.h
+++ b/source/gameengine/Expressions/VectorValue.h
@@ -32,7 +32,7 @@ public:
 	void SetVector(double newvec[]);
 	void Configure(CValue* menuvalue);
 	virtual double* GetVector3(bool bGetTransformedVec=false);
-	virtual float		GetNumber();
+	virtual double		GetNumber();
 	
 	CValue*		Calc(VALUE_OPERATOR op, CValue *val) {
 		return val->CalcFinal(VALUE_VECTOR_TYPE, op, this);
@@ -41,7 +41,7 @@ public:
 	CValue*		CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
 	
 	
-	CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE);
+	CVectorValue(double vec[],const char *name,AllocationTYPE alloctype=CValue::HEAPVALUE);
 	CVectorValue() {};
 
 	CVectorValue(double vec[],AllocationTYPE alloctype=CValue::HEAPVALUE);
diff --git a/source/gameengine/Expressions/VoidValue.h b/source/gameengine/Expressions/VoidValue.h
index 4bde025478734df1ac7d32dec7b944c3f138ec0c..10a6ff9ad3dcbb9d5f4eb1a64ceea13b26a5a4aa 100644
--- a/source/gameengine/Expressions/VoidValue.h
+++ b/source/gameengine/Expressions/VoidValue.h
@@ -47,7 +47,7 @@ public:
 
 	/// Value -> String or number
 	virtual const STR_String &	GetText();												// Get string description of void value (unimplemented)
-	virtual float		GetNumber()												{ return -1; }
+	virtual double		GetNumber()												{ return -1; }
 
 	/// Value calculation
 	virtual CValue*		Calc(VALUE_OPERATOR op, CValue *val);
diff --git a/source/gameengine/GameLogic/CMakeLists.txt b/source/gameengine/GameLogic/CMakeLists.txt
index a7519196d50f7824e353b092bb558e9223c351f1..449aae3ac849f176dd024489e55921e8c6767e34 100644
--- a/source/gameengine/GameLogic/CMakeLists.txt
+++ b/source/gameengine/GameLogic/CMakeLists.txt
@@ -31,6 +31,7 @@ SET(INC
   ../../../source/kernel/gen_system 
   ../../../intern/string
   ../../../source/gameengine/Expressions 
+  ../../../source/gameengine/Scenegraph
   ../../../intern/moto/include
   ../../../source/gameengine/Rasterizer
   ${PYTHON_INC}
diff --git a/source/gameengine/GameLogic/Joystick/Makefile b/source/gameengine/GameLogic/Joystick/Makefile
index 7016f1ed16f6025a00c99eb5c7912cef98886ee5..02def1cec6291645d7256f4c392a559566b86ca7 100644
--- a/source/gameengine/GameLogic/Joystick/Makefile
+++ b/source/gameengine/GameLogic/Joystick/Makefile
@@ -40,5 +40,5 @@ CPPFLAGS += -I$(NAN_STRING)/include
 CPPFLAGS += -I$(NAN_MOTO)/include
 CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
 CPPFLAGS += $(NAN_SDLCFLAGS)
-
+CPPFLAGS += -I../../SceneGraph
 CPPFLAGS += -I../../../kernel/gen_system
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index c21e5db1410bcb1e83a573173b4922da4e504b32..c300baa9bd4643717935834efe15077544d8800b 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -29,6 +29,7 @@
 #endif
 
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "SCA_Joystick.h"
 #include "SCA_JoystickPrivate.h"
@@ -36,21 +37,19 @@
 SCA_Joystick::SCA_Joystick(short int index)
 	:
 	m_joyindex(index),
-	m_axis10(0),
-	m_axis11(0),
-	m_axis20(0),
-	m_axis21(0),
 	m_prec(3200),
 	m_buttonnum(-2),
 	m_axismax(-1),
-	m_hatdir(-2),
 	m_buttonmax(-1),
 	m_hatmax(-1),
+	m_hatdir(-2),
 	m_isinit(0),
 	m_istrig_axis(0),
 	m_istrig_button(0),
 	m_istrig_hat(0)
 {
+	for(int i=0; i<JOYAXIS_MAX; i++)
+		m_axis_array[i]= 0;
 #ifndef DISABLE_SDL
 	m_private = new PrivateData();
 #endif
@@ -125,47 +124,30 @@ void SCA_Joystick::cSetPrecision(int val)
 }
 
 
-bool SCA_Joystick::aAnyAxisIsPositive(int axis)
+bool SCA_Joystick::aAxisPairIsPositive(int axis)
 {
-	bool result;
-	int res = pAxisTest(axis);
-	res > m_prec? result = true: result = false;
-	return result;
+	return (pAxisTest(axis) > m_prec) ? true:false;
 }
 
-bool SCA_Joystick::aRightAxisIsPositive(int axis)
+bool SCA_Joystick::aAxisPairDirectionIsPositive(int axis, int dir)
 {
-	bool result;
-	int res = pGetAxis(axis,1);
-	res > m_prec? result = true: result = false;
-	return result;
-}
 
-
-bool SCA_Joystick::aUpAxisIsPositive(int axis)
-{
-	bool result;
-	int res = pGetAxis(axis,0);
-	res < -m_prec? result = true : result = false;
-	return result;
+	int res;
+
+	if (dir==JOYAXIS_UP || dir==JOYAXIS_DOWN)
+		res = pGetAxis(axis, 1);
+	else /* JOYAXIS_LEFT || JOYAXIS_RIGHT */
+		res = pGetAxis(axis, 0);
+	
+	if (dir==JOYAXIS_DOWN || dir==JOYAXIS_RIGHT)
+		return (res > m_prec) ? true : false;
+	else /* JOYAXIS_UP || JOYAXIS_LEFT */
+		return (res < -m_prec) ? true : false;
 }
 
-
-bool SCA_Joystick::aLeftAxisIsPositive(int axis)
+bool SCA_Joystick::aAxisIsPositive(int axis_single)
 {
-	bool result;
-	int res = pGetAxis(axis,1);
-	res < -m_prec ? result = true : result = false;
-	return result;
-}
-
-
-bool SCA_Joystick::aDownAxisIsPositive(int axis)
-{
-	bool result;
-	int res = pGetAxis(axis,0);
-	res > m_prec ? result = true:result = false;
-	return result;
+	return abs(m_axis_array[axis_single]) > m_prec ? true:false;
 }
 
 bool SCA_Joystick::aAnyButtonPressIsPositive(void)
@@ -255,8 +237,12 @@ bool SCA_Joystick::CreateJoystickDevice(void)
 		
 		/* must run after being initialized */
 		m_axismax =		SDL_JoystickNumAxes(m_private->m_joystick);
+		if (m_axismax > JOYAXIS_MAX) m_axismax= JOYAXIS_MAX;		/* very unlikely */
+		
 		m_buttonmax =	SDL_JoystickNumButtons(m_private->m_joystick);
 		m_hatmax =		SDL_JoystickNumHats(m_private->m_joystick);
+		
+		
 	}
 	return true;
 #endif
@@ -288,17 +274,8 @@ int SCA_Joystick::Connected(void)
 void SCA_Joystick::pFillAxes()
 {
 #ifndef DISABLE_SDL
-	if(m_axismax == 1){
-		m_axis10 = SDL_JoystickGetAxis(m_private->m_joystick, 0);
-		m_axis11 = SDL_JoystickGetAxis(m_private->m_joystick, 1);
-	}else if(m_axismax > 1){
-		m_axis10 = SDL_JoystickGetAxis(m_private->m_joystick, 0);
-		m_axis11 = SDL_JoystickGetAxis(m_private->m_joystick, 1);
-		m_axis20 = SDL_JoystickGetAxis(m_private->m_joystick, 2);
-		m_axis21 = SDL_JoystickGetAxis(m_private->m_joystick, 3);
-	}else{
-		m_axis10 = m_axis11 = m_axis20 = m_axis21 = 0;
-	}
+	for(int i=0; i<m_axismax; i++)
+		m_axis_array[i]= SDL_JoystickGetAxis(m_private->m_joystick, i);
 #endif
 }
 
@@ -306,10 +283,7 @@ void SCA_Joystick::pFillAxes()
 int SCA_Joystick::pGetAxis(int axisnum, int udlr)
 {
 #ifndef DISABLE_SDL
-	if(axisnum == 1 && udlr == 1)return m_axis10; //u/d
-	if(axisnum == 1 && udlr == 0)return m_axis11; //l/r
-	if(axisnum == 2 && udlr == 0)return m_axis20; //...
-	if(axisnum == 2 && udlr == 1)return m_axis21;
+	return m_axis_array[(axisnum*2)+udlr];
 #endif
 	return 0;
 }
@@ -317,13 +291,9 @@ int SCA_Joystick::pGetAxis(int axisnum, int udlr)
 int SCA_Joystick::pAxisTest(int axisnum)
 {
 #ifndef DISABLE_SDL
-	short i1,i2;
-	if(axisnum == 1) {
-		i1 = m_axis10;	i2 = m_axis11;
-	}
-	else if(axisnum == 2) {
-		i1 = m_axis20;	i2 = m_axis21;
-	}
+	short i1= m_axis_array[(axisnum*2)];
+	short i2= m_axis_array[(axisnum*2)+1];
+	
 	/* long winded way to do
 	 *   return MAX2(abs(i1), abs(i2))
 	 * avoid abs from math.h */
@@ -335,4 +305,3 @@ int SCA_Joystick::pAxisTest(int axisnum)
 	return 0;
 #endif
 }
-
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
index 8335d5538ad118236cb7c23cf2114ae0b8b5b03e..53cd65cd49507a836bdb14617993931bea2c5fb6 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
@@ -55,10 +55,8 @@ class SCA_Joystick
 	/* 
 	 *support for 2 axes 
 	 */
-
-	int m_axis10,m_axis11;
-	int m_axis20,m_axis21;
-
+	int m_axis_array[JOYAXIS_MAX];
+	
 	/*
 	 * Precision or range of the axes
 	 */
@@ -120,7 +118,10 @@ class SCA_Joystick
 	void OnButtonUp(SDL_Event *sdl_event);
 	void OnButtonDown(SDL_Event *sdl_event);
 	void OnNothing(SDL_Event *sdl_event);
+#if 0 /* not used yet */
 	void OnBallMotion(SDL_Event *sdl_event){}
+#endif
+		
 #endif
 	/*
 	 * Open the joystick
@@ -139,12 +140,12 @@ class SCA_Joystick
 	void pFillButtons(void);
 
 	/*
-	 * returns m_axis10,m_axis11...
+	 * returns m_axis_array
 	 */
 
 	int pAxisTest(int axisnum);
 	/*
-	 * returns m_axis10,m_axis11...
+	 * returns m_axis_array
 	 */
 	int pGetAxis(int axisnum, int udlr);
 
@@ -166,11 +167,9 @@ public:
 
 	/*
 	 */
-	bool aAnyAxisIsPositive(int axis);
-	bool aUpAxisIsPositive(int axis);
-	bool aDownAxisIsPositive(int axis);
-	bool aLeftAxisIsPositive(int axis);
-	bool aRightAxisIsPositive(int axis);
+	bool aAxisPairIsPositive(int axis);
+	bool aAxisPairDirectionIsPositive(int axis, int dir); /* function assumes joysticks are in axis pairs */
+	bool aAxisIsPositive(int axis_single); /* check a single axis only */
 
 	bool aAnyButtonPressIsPositive(void);
 	bool aAnyButtonReleaseIsPositive(void);
@@ -184,24 +183,10 @@ public:
 
 	void cSetPrecision(int val);
 
-	int GetAxis10(void){
-
-		return m_axis10;
-
-	}
-
-	int GetAxis11(void){
-		return m_axis11;
-	}
-
-	int GetAxis20(void){
-		return m_axis20;
+	int GetAxisPosition(int index){
+		return m_axis_array[index];
 	}
-
-	int GetAxis21(void){
-		return m_axis21;
-	}
-
+	
 	int GetButton(void){
 		return m_buttonnum;
 	}
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
index 73ffe1406d91ad8057e7d8a01db57f7769c8b04c..636c4dd5a422fb0b4c11ba70e2193d2bb9852b21 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
@@ -39,5 +39,11 @@
 #endif
 
 #define JOYINDEX_MAX			8
+#define JOYAXIS_MAX				16
+
+#define JOYAXIS_RIGHT		0
+#define JOYAXIS_UP			1
+#define JOYAXIS_DOWN		3
+#define JOYAXIS_LEFT		2
 
 #endif
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
index 73ca288861d31c123cbe2c1819787d689c3f03ff..8e190060e95e4128b553f32a9a70e3c039312cd9 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
@@ -68,7 +68,7 @@ void SCA_Joystick::OnButtonUp(SDL_Event* sdl_event)
 
 void SCA_Joystick::OnButtonDown(SDL_Event* sdl_event)
 {
-	if(sdl_event->jbutton.button >= 0 || sdl_event->jbutton.button <= m_buttonmax)
+	if(sdl_event->jbutton.button <= m_buttonmax) /* unsigned int so always above 0 */
 	{
 		m_istrig_button = 1;
 		m_buttonnum = sdl_event->jbutton.button;
@@ -111,9 +111,11 @@ void SCA_Joystick::HandleEvents(void)
 		case SDL_JOYBUTTONDOWN:
 			SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonDown(&sdl_event);
 			break;
+#if 0	/* Not used yet */
 		case SDL_JOYBALLMOTION:
 			SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event);
 			break;
+#endif
 		default:
 			printf("SCA_Joystick::HandleEvents, Unknown SDL event, this should not happen\n");
 			break;
diff --git a/source/gameengine/GameLogic/Makefile b/source/gameengine/GameLogic/Makefile
index 355ece6e8bd11a48611630d1a7b3cef65df2b378..a1794a60452c85885e52ebc2e1ce5da12a1b0a2c 100644
--- a/source/gameengine/GameLogic/Makefile
+++ b/source/gameengine/GameLogic/Makefile
@@ -39,6 +39,7 @@ include nan_compile.mk
 CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
 
 CPPFLAGS += -I../Expressions 
+CPPFLAGS += -I../SceneGraph
 CPPFLAGS += -I../Rasterizer
 CPPFLAGS += -I$(NAN_STRING)/include    
 CPPFLAGS += -I$(NAN_MOTO)/include
diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
index 9d4dc1f33d697464f7264cb40590a4adfcee4964..7682f6755efbdcebea319a2dc9fedd325a4d39c0 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
@@ -1,5 +1,29 @@
-#include "SCA_IActuator.h"
+/**
+ * SCA_2DFilterActuator.cpp
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
 
+#include "SCA_IActuator.h"
 #include "SCA_2DFilterActuator.h"
 
 #ifdef HAVE_CONFIG_H
@@ -22,7 +46,7 @@ SCA_2DFilterActuator::SCA_2DFilterActuator(
         PyTypeObject* T)
     : SCA_IActuator(gameobj, T),
      m_type(type),
-	 m_flag(flag),
+	 m_disableMotionBlur(flag),
 	 m_float_arg(float_arg),
 	 m_int_arg(int_arg),
 	 m_rasterizer(rasterizer),
@@ -35,19 +59,11 @@ SCA_2DFilterActuator::SCA_2DFilterActuator(
 	}
 }
 
-void SCA_2DFilterActuator::SetShaderText(STR_String text)
-{
-	m_shaderText = text;
-}
-
-
 
 CValue* SCA_2DFilterActuator::GetReplica()
 {
     SCA_2DFilterActuator* replica = new SCA_2DFilterActuator(*this);
     replica->ProcessReplica();
-    CValue::AddDataToReplica(replica);
-
     return replica;
 }
 
@@ -63,7 +79,7 @@ bool SCA_2DFilterActuator::Update()
 
 	if( m_type == RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR )
 	{
-		if(!m_flag)
+		if(!m_disableMotionBlur)
 			m_rasterizer->EnableMotionBlur(m_float_arg);
 		else
 			m_rasterizer->DisableMotionBlur();
@@ -79,13 +95,30 @@ bool SCA_2DFilterActuator::Update()
 }
 
 
+void SCA_2DFilterActuator::SetShaderText(const char *text)
+{
+	m_shaderText = text;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions                                                          */
+/* ------------------------------------------------------------------------- */
+
+
+
+/* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_2DFilterActuator::Type = {
-        PyObject_HEAD_INIT(NULL)
-        0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
         "SCA_2DFilterActuator",
-        sizeof(SCA_2DFilterActuator),
+        sizeof(PyObjectPlus_Proxy),
         0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -109,14 +142,30 @@ PyParentObject SCA_2DFilterActuator::Parents[] = {
 
 
 PyMethodDef SCA_2DFilterActuator::Methods[] = {
-    /* add python functions to deal with m_msg... */
+	/* add python functions to deal with m_msg... */
     {NULL,NULL}
 };
 
 PyAttributeDef SCA_2DFilterActuator::Attributes[] = {
+	KX_PYATTRIBUTE_STRING_RW("shaderText", 0, 64000, false, SCA_2DFilterActuator, m_shaderText),
+	KX_PYATTRIBUTE_SHORT_RW("disableMotionBlur", 0, 1, true, SCA_2DFilterActuator, m_disableMotionBlur),
+	KX_PYATTRIBUTE_ENUM_RW("type",RAS_2DFilterManager::RAS_2DFILTER_ENABLED,RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS,false,SCA_2DFilterActuator,m_type),
+	KX_PYATTRIBUTE_INT_RW("passNb", 0, 100, true, SCA_2DFilterActuator, m_int_arg),
+	KX_PYATTRIBUTE_FLOAT_RW("value", 0.0, 100.0, SCA_2DFilterActuator, m_float_arg),
 	{ NULL }	//Sentinel
 };
 
-PyObject* SCA_2DFilterActuator::py_getattro(PyObject *attr) {
+PyObject* SCA_2DFilterActuator::py_getattro(PyObject *attr) 
+{
     py_getattro_up(SCA_IActuator);
 }
+
+PyObject* SCA_2DFilterActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
+int SCA_2DFilterActuator::py_setattro(PyObject *attr, PyObject* value) 
+{
+	py_setattro_up(SCA_IActuator);
+}
+
diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h
index f69c680b7747f6f76b91dcc573a70780e7b3964b..13b9997a0107bce26d6e16324dc102015b0d7e41 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h
@@ -1,3 +1,30 @@
+/**
+ * SCA_2DFilterActuator.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
 #ifndef __SCA_2DFILETRACTUATOR_H__
 #define __SCA_2DFILETRACTUATOR_H__
 
@@ -13,7 +40,7 @@ private:
 	vector<STR_String> m_propNames;
 	void * m_gameObj;
 	RAS_2DFilterManager::RAS_2DFILTER_MODE m_type;
-	short m_flag;
+	short m_disableMotionBlur;
 	float m_float_arg;
 	int   m_int_arg;
 	STR_String	m_shaderText;
@@ -33,12 +60,19 @@ public:
         PyTypeObject* T=&Type
         );
 
-	void	SetShaderText(STR_String text);
+	void	SetShaderText(const char *text);
     virtual ~SCA_2DFilterActuator();
     virtual bool Update();
 
     virtual CValue* GetReplica();
+
+	/* --------------------------------------------------------------------- */
+	/* Python interface ---------------------------------------------------- */
+	/* --------------------------------------------------------------------- */
+
     virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
+	virtual int py_setattro(PyObject *attr, PyObject* value);
 
 };
 #endif
diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp
index cb62e2b5a1dc871dc4e882b26f13b50ad39ac208..87f7c612e7c1023bbbe87540b80c5957d8bd3d38 100644
--- a/source/gameengine/GameLogic/SCA_ANDController.cpp
+++ b/source/gameengine/GameLogic/SCA_ANDController.cpp
@@ -66,26 +66,19 @@ void SCA_ANDController::Trigger(SCA_LogicManager* logicmgr)
 	!(is==m_linkedsensors.end());is++)
 	{
 		SCA_ISensor* sensor = *is;
-		if (!sensor->IsPositiveTrigger())
+		if (!sensor->GetState())
 		{
 			sensorresult = false;
 			break;
 		}
 	}
 	
-	CValue* newevent = new CBoolValue(sensorresult);
-
 	for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
 	!(i==m_linkedactuators.end());i++)
 	{
-		SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
-		logicmgr->AddActiveActuator(actua,newevent);
+		SCA_IActuator* actua = *i;
+		logicmgr->AddActiveActuator(actua,sensorresult);
 	}
-
-	// every actuator that needs the event, has a it's own reference to it now so
-	// release it (so to be clear: if there is no actuator, it's deleted right now)
-	newevent->Release();
-
 }
 
 
@@ -94,7 +87,7 @@ CValue* SCA_ANDController::GetReplica()
 {
 	CValue* replica = new SCA_ANDController(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -107,12 +100,17 @@ CValue* SCA_ANDController::GetReplica()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_ANDController::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_ANDController",
-	sizeof(SCA_ANDController),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -145,4 +143,8 @@ PyObject* SCA_ANDController::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_IController);
 }
 
+PyObject* SCA_ANDController::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IController);
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h
index fdb93d0fc4290dad8609a66a085a2e709e1e6ec3..9a359d57cb407864e80b0987f1ec666e4803019a 100644
--- a/source/gameengine/GameLogic/SCA_ANDController.h
+++ b/source/gameengine/GameLogic/SCA_ANDController.h
@@ -49,6 +49,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 
 };
 
diff --git a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp
index 768a3a45937ad844f8b337179d5c4028f01c00c4..a80b2af55c8229c398f3373513cc76aac16726d6 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp
@@ -51,17 +51,19 @@ SCA_ActuatorEventManager::~SCA_ActuatorEventManager()
 void SCA_ActuatorEventManager::NextFrame()
 {
 	// check for changed actuator
-	for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++)
+	SG_DList::iterator<SCA_ISensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
 	{
-		(*it)->Activate(m_logicmgr,NULL);
+		(*it)->Activate(m_logicmgr);
 	}
 }
 
 void SCA_ActuatorEventManager::UpdateFrame()
 {
 	// update the state of actuator before executing them
-	for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++)
+	SG_DList::iterator<SCA_ActuatorSensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
 	{
-		((SCA_ActuatorSensor*)(*it))->Update();
+		(*it)->Update();
 	}
 }
\ No newline at end of file
diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
index ed7aa66d04b50c5905088ec6759e777ab45eff09..4dad65c5a250854f48b40bf8bd95496da69700b0 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
@@ -60,7 +60,7 @@ CValue* SCA_ActuatorSensor::GetReplica()
 {
 	SCA_ActuatorSensor* replica = new SCA_ActuatorSensor(*this);
 	// m_range_expr must be recalculated on replica!
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	replica->Init();
 
 	return replica;
@@ -89,7 +89,7 @@ SCA_ActuatorSensor::~SCA_ActuatorSensor()
 
 
 
-bool SCA_ActuatorSensor::Evaluate(CValue* event)
+bool SCA_ActuatorSensor::Evaluate()
 {
 	if (m_actuator)
 	{
@@ -122,12 +122,17 @@ void SCA_ActuatorSensor::Update()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_ActuatorSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_ActuatorSensor",
-	sizeof(SCA_ActuatorSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -162,10 +167,15 @@ PyAttributeDef SCA_ActuatorSensor::Attributes[] = {
 };
 
 PyObject* SCA_ActuatorSensor::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
-	py_getattro_up(SCA_ISensor); /* implicit return! */
+	py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_ActuatorSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_ActuatorSensor::py_setattro(PyObject *attr, PyObject *value) {
+	py_setattro_up(SCA_ISensor);
 }
 
 int SCA_ActuatorSensor::CheckActuator(void *self, const PyAttributeDef*)
@@ -180,18 +190,11 @@ int SCA_ActuatorSensor::CheckActuator(void *self, const PyAttributeDef*)
 	return 1;
 }
 
-int SCA_ActuatorSensor::py_setattro(PyObject *attr, PyObject *value) {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_ISensor::py_setattro(attr, value);
-}
-
 /* 3. getActuator */
 const char SCA_ActuatorSensor::GetActuator_doc[] = 
 "getActuator()\n"
 "\tReturn the Actuator with which the sensor operates.\n";
-PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self) 
+PyObject* SCA_ActuatorSensor::PyGetActuator() 
 {
 	ShowDeprecationWarning("getActuator()", "the actuator property");
 	return PyString_FromString(m_checkactname);
@@ -203,14 +206,14 @@ const char SCA_ActuatorSensor::SetActuator_doc[] =
 "\t- name: string\n"
 "\tSets the Actuator with which to operate. If there is no Actuator\n"
 "\tof this name, the call is ignored.\n";
-PyObject* SCA_ActuatorSensor::PySetActuator(PyObject* self, PyObject* args, PyObject* kwds) 
+PyObject* SCA_ActuatorSensor::PySetActuator(PyObject* args) 
 {
 	ShowDeprecationWarning("setActuator()", "the actuator property");
 	/* We should query whether the name exists. Or should we create a prop   */
 	/* on the fly?                                                           */
 	char *actNameArg = NULL;
 
-	if (!PyArg_ParseTuple(args, "s", &actNameArg)) {
+	if (!PyArg_ParseTuple(args, "s:setActuator", &actNameArg)) {
 		return NULL;
 	}
 
diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h
index 9bc873e4ee132f40ba751fb60326ee8d92159b7f..6655e08dc70821b72f7e608aaeba0bca259c4ec9 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h
+++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h
@@ -52,7 +52,7 @@ public:
 	virtual ~SCA_ActuatorSensor();
 	virtual CValue* GetReplica();
 	virtual void Init();
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool	IsPositiveTrigger();
 	virtual void	ReParent(SCA_IObject* parent);
 	void Update();
@@ -62,10 +62,11 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	/* 3. setProperty */
-	KX_PYMETHOD_DOC(SCA_ActuatorSensor,SetActuator);
+	KX_PYMETHOD_DOC_VARARGS(SCA_ActuatorSensor,SetActuator);
 	/* 4. getProperty */
 	KX_PYMETHOD_DOC_NOARGS(SCA_ActuatorSensor,GetActuator);
 	
diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp
index 4cd2dfba99406661d0ea6d4702fe9b3121c2de27..dd3b55abcc9dc9a4462aba0bb034bad277e492fa 100644
--- a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp
@@ -51,9 +51,10 @@ SCA_AlwaysEventManager::SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr)
 
 void SCA_AlwaysEventManager::NextFrame()
 {
-	for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+	SG_DList::iterator<SCA_ISensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
 	{
-		(*i)->Activate(m_logicmgr, NULL);
+		(*it)->Activate(m_logicmgr);
 	}
 }
 
diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp
index a7b0e5a14d2244c5d1eea21df5fa71e7a166451b..ff02680f1914c848460cd1262762e3e106170f42 100644
--- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp
@@ -72,7 +72,7 @@ CValue* SCA_AlwaysSensor::GetReplica()
 {
 	CValue* replica = new SCA_AlwaysSensor(*this);//m_float,GetName());
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -86,7 +86,7 @@ bool SCA_AlwaysSensor::IsPositiveTrigger()
 
 
 
-bool SCA_AlwaysSensor::Evaluate(CValue* event)
+bool SCA_AlwaysSensor::Evaluate()
 {
 	/* Nice! :) */
 		//return true;
@@ -105,12 +105,17 @@ bool SCA_AlwaysSensor::Evaluate(CValue* event)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_AlwaysSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_AlwaysSensor",
-	sizeof(SCA_AlwaysSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -143,4 +148,8 @@ PyObject* SCA_AlwaysSensor::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_ISensor);
 }
 
+PyObject* SCA_AlwaysSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h
index 87949babf595310662bf8f1eb8fa2996e32c9043..0f85a641ef1e0c53e33c866e679e8a6395cff994 100644
--- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h
+++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h
@@ -43,7 +43,7 @@ public:
 					PyTypeObject* T =&Type);
 	virtual ~SCA_AlwaysSensor();
 	virtual CValue* GetReplica();
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool IsPositiveTrigger();
 	virtual void Init();
 
@@ -53,7 +53,7 @@ public:
 	/* --------------------------------------------------------------------- */
 	
 	virtual PyObject* py_getattro(PyObject *attr);
-
+	virtual PyObject* py_getattro_dict();
 	
 };
 
diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp
index 5082caacfd503cd6524869f6d75908d0d635bf9c..dcdae0b4e75bfb6f55c3d5a041a4e8dc2192d2ab 100644
--- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp
@@ -77,7 +77,7 @@ CValue* SCA_DelaySensor::GetReplica()
 {
 	CValue* replica = new SCA_DelaySensor(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -89,7 +89,7 @@ bool SCA_DelaySensor::IsPositiveTrigger()
 	return (m_invert ? !m_lastResult : m_lastResult);
 }
 
-bool SCA_DelaySensor::Evaluate(CValue* event)
+bool SCA_DelaySensor::Evaluate()
 {
 	bool trigger = false;
 	bool result;
@@ -131,12 +131,17 @@ bool SCA_DelaySensor::Evaluate(CValue* event)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_DelaySensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_DelaySensor",
-	sizeof(SCA_DelaySensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -179,17 +184,15 @@ PyAttributeDef SCA_DelaySensor::Attributes[] = {
 };
 
 PyObject* SCA_DelaySensor::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_ISensor);
 }
 
+PyObject* SCA_DelaySensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 int SCA_DelaySensor::py_setattro(PyObject *attr, PyObject *value) {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_ISensor::py_setattro(attr, value);
+	py_setattro_up(SCA_ISensor);
 }
 
 
@@ -198,12 +201,12 @@ const char SCA_DelaySensor::SetDelay_doc[] =
 "\t- delay: length of the initial OFF period as number of frame\n"
 "\t         0 for immediate trigger\n"
 "\tSet the initial delay before the positive trigger\n";
-PyObject* SCA_DelaySensor::PySetDelay(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_DelaySensor::PySetDelay(PyObject* args)
 {
 	ShowDeprecationWarning("setDelay()", "the delay property");
 	int delay;
 	
-	if(!PyArg_ParseTuple(args, "i", &delay)) {
+	if(!PyArg_ParseTuple(args, "i:setDelay", &delay)) {
 		return NULL;
 	}
 	if (delay < 0) {
@@ -220,12 +223,12 @@ const char SCA_DelaySensor::SetDuration_doc[] =
 "\t            0 for no ON period\n"
 "\tSet the duration of the ON pulse after initial delay.\n"
 "\tIf > 0, a negative trigger is fired at the end of the ON pulse.\n";
-PyObject* SCA_DelaySensor::PySetDuration(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_DelaySensor::PySetDuration(PyObject* args)
 {
 	ShowDeprecationWarning("setDuration()", "the duration property");
 	int duration;
 	
-	if(!PyArg_ParseTuple(args, "i", &duration)) {
+	if(!PyArg_ParseTuple(args, "i:setDuration", &duration)) {
 		return NULL;
 	}
 	if (duration < 0) {
@@ -241,12 +244,12 @@ const char SCA_DelaySensor::SetRepeat_doc[] =
 "\t- repeat: 1 if the initial OFF-ON cycle should be repeated indefinately\n"
 "\t          0 if the initial OFF-ON cycle should run only once\n"
 "\tSet the sensor repeat mode\n";
-PyObject* SCA_DelaySensor::PySetRepeat(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_DelaySensor::PySetRepeat(PyObject* args)
 {
 	ShowDeprecationWarning("setRepeat()", "the repeat property");
 	int repeat;
 	
-	if(!PyArg_ParseTuple(args, "i", &repeat)) {
+	if(!PyArg_ParseTuple(args, "i:setRepeat", &repeat)) {
 		return NULL;
 	}
 	m_repeat = (repeat != 0);
@@ -256,7 +259,7 @@ PyObject* SCA_DelaySensor::PySetRepeat(PyObject* self, PyObject* args, PyObject*
 const char SCA_DelaySensor::GetDelay_doc[] = 
 "getDelay()\n"
 "\tReturn the delay parameter value\n";
-PyObject* SCA_DelaySensor::PyGetDelay(PyObject* self)
+PyObject* SCA_DelaySensor::PyGetDelay()
 {
 	ShowDeprecationWarning("getDelay()", "the delay property");
 	return PyInt_FromLong(m_delay);
@@ -265,7 +268,7 @@ PyObject* SCA_DelaySensor::PyGetDelay(PyObject* self)
 const char SCA_DelaySensor::GetDuration_doc[] = 
 "getDuration()\n"
 "\tReturn the duration parameter value\n";
-PyObject* SCA_DelaySensor::PyGetDuration(PyObject* self)
+PyObject* SCA_DelaySensor::PyGetDuration()
 {
 	ShowDeprecationWarning("getDuration()", "the duration property");
 	return PyInt_FromLong(m_duration);
@@ -274,7 +277,7 @@ PyObject* SCA_DelaySensor::PyGetDuration(PyObject* self)
 const char SCA_DelaySensor::GetRepeat_doc[] = 
 "getRepeat()\n"
 "\tReturn the repeat parameter value\n";
-PyObject* SCA_DelaySensor::PyGetRepeat(PyObject* self)
+PyObject* SCA_DelaySensor::PyGetRepeat()
 {
 	ShowDeprecationWarning("getRepeat()", "the repeat property");
 	return BoolToPyArg(m_repeat);
diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h
index f9e3d619198550a60569f304fee035f2800b0018..5ccb33f8a160ff1c9bf08db19258a16fe0724fda 100644
--- a/source/gameengine/GameLogic/SCA_DelaySensor.h
+++ b/source/gameengine/GameLogic/SCA_DelaySensor.h
@@ -51,7 +51,7 @@ public:
 					PyTypeObject* T =&Type);
 	virtual ~SCA_DelaySensor();
 	virtual CValue* GetReplica();
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool IsPositiveTrigger();
 	virtual void Init();
 
@@ -61,12 +61,13 @@ public:
 	/* --------------------------------------------------------------------- */
 	
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject*		py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	/* setProperty */
-	KX_PYMETHOD_DOC(SCA_DelaySensor,SetDelay);
-	KX_PYMETHOD_DOC(SCA_DelaySensor,SetDuration);
-	KX_PYMETHOD_DOC(SCA_DelaySensor,SetRepeat);
+	KX_PYMETHOD_DOC_VARARGS(SCA_DelaySensor,SetDelay);
+	KX_PYMETHOD_DOC_VARARGS(SCA_DelaySensor,SetDuration);
+	KX_PYMETHOD_DOC_VARARGS(SCA_DelaySensor,SetRepeat);
 	/* getProperty */
 	KX_PYMETHOD_DOC_NOARGS(SCA_DelaySensor,GetDelay);
 	KX_PYMETHOD_DOC_NOARGS(SCA_DelaySensor,GetDuration);
diff --git a/source/gameengine/GameLogic/SCA_EventManager.cpp b/source/gameengine/GameLogic/SCA_EventManager.cpp
index e4fd03795977359f777c2e4f3bee1a5921673a93..d1301541a0ab54157886496f5a5e243cac8e8c3e 100644
--- a/source/gameengine/GameLogic/SCA_EventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_EventManager.cpp
@@ -28,6 +28,7 @@
 
 #include <assert.h>
 #include "SCA_EventManager.h"
+#include "SCA_ISensor.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -43,16 +44,18 @@ SCA_EventManager::SCA_EventManager(EVENT_MANAGER_TYPE mgrtype)
 
 SCA_EventManager::~SCA_EventManager()
 {
+	// all sensors should be removed
+	assert(m_sensors.Empty());
 }
 
 void SCA_EventManager::RegisterSensor(class SCA_ISensor* sensor)
 {
-	m_sensors.insert(sensor);
+	m_sensors.AddBack(sensor);
 }
 
 void SCA_EventManager::RemoveSensor(class SCA_ISensor* sensor)
 {
-	m_sensors.erase(sensor);
+	sensor->Delink();
 }
 
 void SCA_EventManager::NextFrame(double curtime, double fixedtime)
diff --git a/source/gameengine/GameLogic/SCA_EventManager.h b/source/gameengine/GameLogic/SCA_EventManager.h
index 9dbb5a6d24f44b1e68769d221fbc0984d827f46d..5ff55849bfe46cee2a5265f1748a45301d2e744d 100644
--- a/source/gameengine/GameLogic/SCA_EventManager.h
+++ b/source/gameengine/GameLogic/SCA_EventManager.h
@@ -33,11 +33,14 @@
 #include <set>
 #include <algorithm>
 
+#include "SG_DList.h"
+
 class SCA_EventManager
 {
 protected:
 	// use a set to speed-up insertion/removal
-	std::set <class SCA_ISensor*>				m_sensors;
+	//std::set <class SCA_ISensor*>				m_sensors;
+	SG_DList		m_sensors;
 
 public:
 	enum EVENT_MANAGER_TYPE {
diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp
index 8ed46beb7f3e5b89c33d87134c85221ef803f080..8e044b89c71b704743295a24267343f01542647a 100644
--- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp
+++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp
@@ -70,7 +70,7 @@ CValue* SCA_ExpressionController::GetReplica()
 	replica->m_exprText = m_exprText;
 	replica->m_exprCache = NULL;
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -109,43 +109,20 @@ void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr)
 				printf(value->GetText());
 			} else
 			{
-				float num = value->GetNumber();
+				float num = (float)value->GetNumber();
 				expressionresult = !MT_fuzzyZero(num);
 			}
 			value->Release();
 
 		}
-		//m_exprCache->Release();
-		//m_exprCache = NULL;
 	}
 
-	/*
-
-	for (vector<SCA_ISensor*>::const_iterator is=m_linkedsensors.begin();
-	!(is==m_linkedsensors.end());is++)
-	{
-		SCA_ISensor* sensor = *is;
-		if (!sensor->IsPositiveTrigger())
-		{
-			sensorresult = false;
-			break;
-		}
-	}
-	
-	  */
-	
-	CValue* newevent = new CBoolValue(expressionresult);
-
 	for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
 	!(i==m_linkedactuators.end());i++)
 	{
 		SCA_IActuator* actua = *i;
-		logicmgr->AddActiveActuator(actua,newevent);
+		logicmgr->AddActiveActuator(actua,expressionresult);
 	}
-	//printf("expr %d.",expressionresult);
-	// every actuator that needs the event, has a it's own reference to it now so
-	// release it (so to be clear: if there is no actuator, it's deleted right now)
-	newevent->Release();
 }
 
 
@@ -161,7 +138,7 @@ CValue* SCA_ExpressionController::FindIdentifier(const STR_String& identifiernam
 		SCA_ISensor* sensor = *is;
 		if (sensor->GetName() == identifiername)
 		{
-			identifierval = new CBoolValue(sensor->IsPositiveTrigger());
+			identifierval = new CBoolValue(sensor->GetState());
 			//identifierval = sensor->AddRef();
 		}
 
diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h
index 2936742be19e4875a0c29954dd81f22c3bb9465e..6a34d7b2dff9e8959425e3ad921bda2b008c97e6 100644
--- a/source/gameengine/GameLogic/SCA_ExpressionController.h
+++ b/source/gameengine/GameLogic/SCA_ExpressionController.h
@@ -60,6 +60,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 //	virtual PyObject* py_getattro(PyObject *attr);
+//	virtual PyObject* py_getattro_dict();
 
 };
 
diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp
index 309f3108418e2743e8fe92d8467a1b5377b0ebbf..5f71bb3f9e435d27db27c6f5aeb5d343dd72c0f9 100644
--- a/source/gameengine/GameLogic/SCA_IActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_IActuator.cpp
@@ -37,53 +37,13 @@ using namespace std;
 SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj,
 							 PyTypeObject* T) :
 	SCA_ILogicBrick(gameobj,T),
-	m_links(0)
+	m_links(0),
+	m_posevent(false),
+	m_negevent(false)
 {
 	// nothing to do
 }
 
-
-
-void SCA_IActuator::AddEvent(CValue* event)
-{
-	m_events.push_back(event);
-}
-
-
-
-void SCA_IActuator::RemoveAllEvents()
-{	// remove event queue!
-	for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++)
-	{
-		(*i)->Release();
-	}
-	m_events.clear();
-}
-
-
-
-
-
-bool SCA_IActuator::IsNegativeEvent() const
-{
-	bool bPositiveEvent(false);
-	bool bNegativeEvent(false);
-
-	for (vector<CValue*>::const_iterator i=m_events.begin(); i!=m_events.end();++i)
-	{
-		if ((*i)->GetNumber() == 0.0f)
-		{
-			bNegativeEvent = true;
-		} else {
-			bPositiveEvent = true;
-		}
-	}
-
-	// if at least 1 positive event, return false
-	
-	return !bPositiveEvent && bNegativeEvent;
-}
-
 bool SCA_IActuator::Update(double curtime, bool frame)
 {
 	if (frame)
@@ -100,7 +60,9 @@ bool SCA_IActuator::Update()
 
 void SCA_IActuator::ProcessReplica()
 {
-	m_events.clear();
+	SCA_ILogicBrick::ProcessReplica();
+	RemoveAllEvents();
+	m_linkedcontrollers.clear();
 }
 
 
@@ -119,3 +81,36 @@ void SCA_IActuator::DecLink()
 		m_links = 0;
 	}
 }
+
+void SCA_IActuator::LinkToController(SCA_IController* controller)
+{
+	m_linkedcontrollers.push_back(controller);
+}
+
+void SCA_IActuator::UnlinkController(SCA_IController* controller)
+{
+	std::vector<class SCA_IController*>::iterator contit;
+	for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit)
+	{
+		if ((*contit) == controller)
+		{
+			*contit = m_linkedcontrollers.back();
+			m_linkedcontrollers.pop_back();
+			return;
+		}
+	}
+	printf("Missing link from actuator %s:%s to controller %s:%s\n", 
+		m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), 
+		controller->GetParent()->GetName().ReadPtr(), controller->GetName().ReadPtr());
+}
+
+void SCA_IActuator::UnlinkAllControllers()
+{
+	std::vector<class SCA_IController*>::iterator contit;
+	for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit)
+	{
+		(*contit)->UnlinkActuator(this);
+	}
+	m_linkedcontrollers.clear();
+}
+
diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h
index 51bd6454d927002bd66c6db9b58b989032854b5d..3055e1d946fc27f3864eb83f3add6cc126e1775b 100644
--- a/source/gameengine/GameLogic/SCA_IActuator.h
+++ b/source/gameengine/GameLogic/SCA_IActuator.h
@@ -29,17 +29,33 @@
 #ifndef __KX_IACTUATOR
 #define __KX_IACTUATOR
 
-#include "SCA_ILogicBrick.h"
+#include "SCA_IController.h"
 #include <vector>
 
+/*
+ * Use of SG_DList : element of actuator being deactivated
+ *                   Head: SCA_LogicManager::m_removedActuators
+ * Use of SG_QList : element of activated actuator list of their owner
+ *                   Head: SCA_IObject::m_activeActuators
+ */
 class SCA_IActuator : public SCA_ILogicBrick
 {
 	friend class SCA_LogicManager;
 protected:
 	int					 m_links;	// number of active links to controllers
 									// when 0, the actuator is automatically stopped
-	std::vector<CValue*> m_events;
-	void RemoveAllEvents();
+	//std::vector<CValue*> m_events;
+	bool			     m_posevent;
+	bool			     m_negevent;
+
+	std::vector<class SCA_IController*>		m_linkedcontrollers;
+
+	void RemoveAllEvents()
+	{
+		m_posevent = false;
+		m_negevent = false;
+	}
+
 
 public:
 	/**
@@ -75,7 +91,15 @@ public:
 	/** 
 	 * Add an event to an actuator.
 	 */ 
-	void AddEvent(CValue* event);
+	//void AddEvent(CValue* event)
+	void AddEvent(bool event)
+	{
+		if (event)
+			m_posevent = true;
+		else
+			m_negevent = true;
+	}
+
 	virtual void ProcessReplica();
 
 	/** 
@@ -84,9 +108,38 @@ public:
 	 * not immediately clear. But usually refers to key-up events
 	 * or events where no action is required.
 	 */
-	bool IsNegativeEvent() const;
+	bool IsNegativeEvent() const
+	{
+		return !m_posevent && m_negevent;
+	}
+
 	virtual ~SCA_IActuator();
 
+	/**
+	 * remove this actuator from the list of active actuators
+	 */
+	void Deactivate()
+	{
+		if (QDelink())
+			// the actuator was in the active list
+			if (m_gameobj->m_activeActuators.QEmpty())
+				// the owner object has no more active actuators, remove it from the global list
+				m_gameobj->m_activeActuators.Delink();
+	}
+
+	void Activate(SG_DList& head)
+	{
+		if (QEmpty())
+		{
+			InsertActiveQList(m_gameobj->m_activeActuators);
+			head.AddBack(&m_gameobj->m_activeActuators);
+		}
+	}
+
+	void	LinkToController(SCA_IController* controller);
+	void	UnlinkController(class SCA_IController* cont);
+	void	UnlinkAllControllers();
+
 	void ClrLink() { m_links=0; }
 	void IncLink() { m_links++; }
 	void DecLink();
diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp
index f9c192cae5cd432a38712943d9fc13f0d731cd01..f8b081ef050e3517c13338afefa8ff532facb70c 100644
--- a/source/gameengine/GameLogic/SCA_IController.cpp
+++ b/source/gameengine/GameLogic/SCA_IController.cpp
@@ -30,6 +30,8 @@
 #include "SCA_LogicManager.h"
 #include "SCA_IActuator.h"
 #include "SCA_ISensor.h"
+#include "PyObjectPlus.h"
+#include "../Ketsji/KX_PythonSeq.h" /* not nice, only need for KX_PythonSeq_CreatePyObject */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -39,7 +41,8 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj,
 								 PyTypeObject* T)
 	:
 	SCA_ILogicBrick(gameobj,T),
-	m_statemask(0)
+	m_statemask(0),
+	m_justActivated(false)
 {
 }
 	
@@ -47,19 +50,19 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj,
 	
 SCA_IController::~SCA_IController()
 {
-	UnlinkAllActuators();
+	//UnlinkAllActuators();
 }
 
 
 
-const std::vector<class SCA_ISensor*>& SCA_IController::GetLinkedSensors()
+std::vector<class SCA_ISensor*>& SCA_IController::GetLinkedSensors()
 {
 	return m_linkedsensors;
 }
 
 
 
-const std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators()
+std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators()
 {
 	return m_linkedactuators;
 }
@@ -68,13 +71,14 @@ const std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators()
 
 void SCA_IController::UnlinkAllSensors()
 {
-	if (IsActive()) 
+	std::vector<class SCA_ISensor*>::iterator sensit;
+	for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
 	{
-		std::vector<class SCA_ISensor*>::iterator sensit;
-		for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
+		if (IsActive()) 
 		{
 			(*sensit)->DecLink();
 		}
+		(*sensit)->UnlinkController(this);
 	}
 	m_linkedsensors.clear();
 }
@@ -83,34 +87,18 @@ void SCA_IController::UnlinkAllSensors()
 
 void SCA_IController::UnlinkAllActuators()
 {
-	if (IsActive()) 
+	std::vector<class SCA_IActuator*>::iterator actit;
+	for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit)
 	{
-		std::vector<class SCA_IActuator*>::iterator actit;
-		for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit)
+		if (IsActive()) 
 		{
 			(*actit)->DecLink();
 		}
+		(*actit)->UnlinkController(this);
 	}
 	m_linkedactuators.clear();
 }
 
-
-
-/*
-void SCA_IController::Trigger(SCA_LogicManager* logicmgr)
-{
-	//for (int i=0;i<m_linkedactuators.size();i++)
-	for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
-	!(i==m_linkedactuators.end());i++)
-	{
-		SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
-		
-		logicmgr->AddActiveActuator(actua);
-	}
-
-}
-*/
-
 void SCA_IController::LinkToActuator(SCA_IActuator* actua)
 {
 	m_linkedactuators.push_back(actua);
@@ -127,18 +115,18 @@ void	SCA_IController::UnlinkActuator(class SCA_IActuator* actua)
 	{
 		if ((*actit) == actua)
 		{
-			break;
-		}
-		
-	}
-	if (!(actit==m_linkedactuators.end()))
-	{
-		if (IsActive())
-		{
-			(*actit)->DecLink();
+			if (IsActive())
+			{
+				(*actit)->DecLink();
+			}
+			*actit = m_linkedactuators.back();
+			m_linkedactuators.pop_back();
+			return;
 		}
-		m_linkedactuators.erase(actit);
 	}
+	printf("Missing link from controller %s:%s to actuator %s:%s\n", 
+		m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), 
+		actua->GetParent()->GetName().ReadPtr(), actua->GetName().ReadPtr());
 }
 
 void SCA_IController::LinkToSensor(SCA_ISensor* sensor)
@@ -157,20 +145,21 @@ void SCA_IController::UnlinkSensor(class SCA_ISensor* sensor)
 	{
 		if ((*sensit) == sensor)
 		{
-			break;
-		}
-		
-	}
-	if (!(sensit==m_linkedsensors.end()))
-	{
-		if (IsActive())
-		{
-			(*sensit)->DecLink();
+			if (IsActive())
+			{
+				sensor->DecLink();
+			}
+			*sensit = m_linkedsensors.back();
+			m_linkedsensors.pop_back();
+			return;
 		}
-		m_linkedsensors.erase(sensit);
 	}
+	printf("Missing link from controller %s:%s to sensor %s:%s\n", 
+		m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), 
+		sensor->GetParent()->GetName().ReadPtr(), sensor->GetName().ReadPtr());
 }
 
+
 void SCA_IController::ApplyState(unsigned int state)
 {
 	std::vector<class SCA_IActuator*>::iterator actit;
@@ -185,13 +174,13 @@ void SCA_IController::ApplyState(unsigned int state)
 			{
 				(*actit)->IncLink();
 			}
+
 			for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
 			{
 				(*sensit)->IncLink();
-				// remember that this controller just activated that sensor
-				(*sensit)->AddNewController(this);
 			}
 			SetActive(true);
+			m_justActivated = true;
 		}
 	} else if (IsActive())
 	{
@@ -204,6 +193,167 @@ void SCA_IController::ApplyState(unsigned int state)
 			(*sensit)->DecLink();
 		}
 		SetActive(false);
+		m_justActivated = false;
 	}
 }
 
+/* Python api */
+
+PyTypeObject SCA_IController::Type = {
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
+		"SCA_IController",
+		sizeof(PyObjectPlus_Proxy),
+		0,
+		py_base_dealloc,
+		0,
+		0,
+		0,
+		0,
+		py_base_repr,
+		0,0,0,0,0,0,
+		py_base_getattro,
+		py_base_setattro,
+		0,0,0,0,0,0,0,0,0,
+		Methods
+};
+
+PyParentObject SCA_IController::Parents[] = {
+	&SCA_IController::Type,
+	&CValue::Type,
+	NULL
+};
+
+PyMethodDef SCA_IController::Methods[] = {
+	//Deprecated functions ------>
+	{"getSensor", (PyCFunction) SCA_IController::sPyGetSensor, METH_O},
+	{"getActuator", (PyCFunction) SCA_IController::sPyGetActuator, METH_O},
+	{"getSensors", (PyCFunction) SCA_IController::sPyGetSensors, METH_NOARGS},
+	{"getActuators", (PyCFunction) SCA_IController::sPyGetActuators, METH_NOARGS},
+	{"getState", (PyCFunction) SCA_IController::sPyGetState, METH_NOARGS},
+	//<----- Deprecated
+	{NULL,NULL} //Sentinel
+};
+
+PyAttributeDef SCA_IController::Attributes[] = {
+	KX_PYATTRIBUTE_RO_FUNCTION("state", SCA_IController, pyattr_get_state),
+	KX_PYATTRIBUTE_RO_FUNCTION("sensors", SCA_IController, pyattr_get_sensors),
+	KX_PYATTRIBUTE_RO_FUNCTION("actuators", SCA_IController, pyattr_get_actuators),
+	{ NULL }	//Sentinel
+};
+
+PyObject* SCA_IController::py_getattro(PyObject *attr)
+{
+	py_getattro_up(SCA_ILogicBrick);
+}
+
+PyObject* SCA_IController::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ILogicBrick);
+}
+
+int SCA_IController::py_setattro(PyObject *attr, PyObject *value)
+{
+	py_setattro_up(SCA_ILogicBrick);
+}
+
+
+
+PyObject* SCA_IController::PyGetActuators()
+{
+	ShowDeprecationWarning("getActuators()", "the actuators property");
+	
+	PyObject* resultlist = PyList_New(m_linkedactuators.size());
+	for (unsigned int index=0;index<m_linkedactuators.size();index++)
+	{
+		PyList_SET_ITEM(resultlist,index, m_linkedactuators[index]->GetProxy());
+	}
+
+	return resultlist;
+}
+
+PyObject* SCA_IController::PyGetSensor(PyObject* value)
+{
+	ShowDeprecationWarning("getSensor(string)", "the sensors[string] property");
+	
+	char *scriptArg = PyString_AsString(value);
+	if (scriptArg==NULL) {
+		PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)");
+		return NULL;
+	}
+	
+	for (unsigned int index=0;index<m_linkedsensors.size();index++)
+	{
+		SCA_ISensor* sensor = m_linkedsensors[index];
+		STR_String& realname = sensor->GetName();
+		if (realname == scriptArg)
+		{
+			return sensor->GetProxy();
+		}
+	}
+	
+	PyErr_Format(PyExc_AttributeError, "controller.getSensor(string): Python Controller, unable to find requested sensor \"%s\"", scriptArg);
+	return NULL;
+}
+
+PyObject* SCA_IController::PyGetActuator(PyObject* value)
+{
+	ShowDeprecationWarning("getActuator(string)", "the actuators[string] property");
+	
+	char *scriptArg = PyString_AsString(value);
+	if (scriptArg==NULL) {
+		PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)");
+		return NULL;
+	}
+	
+	for (unsigned int index=0;index<m_linkedactuators.size();index++)
+	{
+		SCA_IActuator* actua = m_linkedactuators[index];
+		if (actua->GetName() == scriptArg)
+		{
+			return actua->GetProxy();
+		}
+	}
+	
+	PyErr_Format(PyExc_AttributeError, "controller.getActuator(string): Python Controller, unable to find requested actuator \"%s\"", scriptArg);
+	return NULL;
+}
+
+PyObject* SCA_IController::PyGetSensors()
+{
+	ShowDeprecationWarning("getSensors()", "the sensors property");
+	
+	PyObject* resultlist = PyList_New(m_linkedsensors.size());
+	for (unsigned int index=0;index<m_linkedsensors.size();index++)
+	{
+		PyList_SET_ITEM(resultlist,index, m_linkedsensors[index]->GetProxy());
+	}
+	
+	return resultlist;
+}
+
+PyObject* SCA_IController::PyGetState()
+{
+	ShowDeprecationWarning("getState()", "the state property");
+	return PyInt_FromLong(m_statemask);
+}
+
+PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_IController* self= static_cast<SCA_IController*>(self_v);
+	return PyInt_FromLong(self->m_statemask);
+}
+
+PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_SENSORS);	
+}
+
+PyObject* SCA_IController::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_ACTUATORS);	
+}
diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h
index f67c0942eb41f5cafdc56e29a99d79df066d5267..1b9d8fb0d2bcab7491c1ad2ebb91d0afc412edf8 100644
--- a/source/gameengine/GameLogic/SCA_IController.h
+++ b/source/gameengine/GameLogic/SCA_IController.h
@@ -30,28 +30,75 @@
 #define __KX_ICONTROLLER
 
 #include "SCA_ILogicBrick.h"
+#include "PyObjectPlus.h"
 
+/*
+ * Use of SG_DList element: none
+ * Use of SG_QList element: build ordered list of activated controller on the owner object
+ *                          Head: SCA_IObject::m_activeControllers
+ */
 class SCA_IController : public SCA_ILogicBrick
 {
+	Py_Header;
 protected:
 	std::vector<class SCA_ISensor*>		m_linkedsensors;
 	std::vector<class SCA_IActuator*>	m_linkedactuators;
 	unsigned int						m_statemask;
+	bool								m_justActivated;
 public:
 	SCA_IController(SCA_IObject* gameobj,PyTypeObject* T);
 	virtual ~SCA_IController();
 	virtual void Trigger(class SCA_LogicManager* logicmgr)=0;
 	void	LinkToSensor(SCA_ISensor* sensor);
 	void	LinkToActuator(SCA_IActuator*);
-	const std::vector<class SCA_ISensor*>&		GetLinkedSensors();
-	const std::vector<class SCA_IActuator*>&	GetLinkedActuators();
+	std::vector<class SCA_ISensor*>&	GetLinkedSensors();
+	std::vector<class SCA_IActuator*>&	GetLinkedActuators();
+	void	ReserveActuator(int num)
+	{
+		m_linkedactuators.reserve(num);
+	}
 	void	UnlinkAllSensors();
 	void	UnlinkAllActuators();
 	void	UnlinkActuator(class SCA_IActuator* actua);
 	void	UnlinkSensor(class SCA_ISensor* sensor);
 	void    SetState(unsigned int state) { m_statemask = state; }
 	void    ApplyState(unsigned int state);
+	void	Deactivate()
+	{
+		// the controller can only be part of a sensor m_newControllers list
+		Delink();
+	}
+	bool IsJustActivated()
+	{
+		return m_justActivated;
+	}
+	void ClrJustActivated()
+	{
+		m_justActivated = false;
+	}
+
+	void Activate(SG_DList& head)
+	{
+		if (QEmpty())
+		{
+			InsertActiveQList(m_gameobj->m_activeControllers);
+			head.AddBack(&m_gameobj->m_activeControllers);
+		}
+	}
 
+	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
+	virtual int py_setattro(PyObject *attr, PyObject *value);
+	
+	KX_PYMETHOD_NOARGS(SCA_IController,GetSensors);
+	KX_PYMETHOD_NOARGS(SCA_IController,GetActuators);
+	KX_PYMETHOD_O(SCA_IController,GetSensor);
+	KX_PYMETHOD_O(SCA_IController,GetActuator);
+	KX_PYMETHOD_NOARGS(SCA_IController,GetState);
+	
+	static PyObject*	pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 
 };
 
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
index 45ebd874ea5b9c5e052a25d20171341c77d3f297..2dc80f54568560466434a2e0b3f37e323222c134 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
@@ -71,13 +71,6 @@ void SCA_ILogicBrick::SetUeberExecutePriority(int execute_Priority)
 
 
 
-SCA_IObject* SCA_ILogicBrick::GetParent()
-{
-	return m_gameobj;
-}
-
-
-
 void SCA_ILogicBrick::ReParent(SCA_IObject* parent)
 {
 	m_gameobj = parent;
@@ -123,40 +116,24 @@ const STR_String& SCA_ILogicBrick::GetText()
 
 
 
-float SCA_ILogicBrick::GetNumber()
+double SCA_ILogicBrick::GetNumber()
 {
 	return -1;
 }
 
 
 
-STR_String SCA_ILogicBrick::GetName()
+STR_String& SCA_ILogicBrick::GetName()
 {
 	return m_name;
 }
 
 
 
-void SCA_ILogicBrick::SetName(STR_String name)
-{
-	m_name = name;
-}
-
-
-
-void SCA_ILogicBrick::ReplicaSetName(STR_String name)
+void SCA_ILogicBrick::SetName(const char *name)
 {
 	m_name = name;
 }
-		
-
-
-bool SCA_ILogicBrick::IsActive()
-{
-	return m_bActive;
-}
-
-
 
 bool SCA_ILogicBrick::LessComparedTo(SCA_ILogicBrick* other)
 {
@@ -165,22 +142,6 @@ bool SCA_ILogicBrick::LessComparedTo(SCA_ILogicBrick* other)
 		(this->m_Execute_Priority < other->m_Execute_Priority));
 }
 
-
-
-void SCA_ILogicBrick::SetActive(bool active)
-{
-	m_bActive=active;
-	if (active)
-	{
-		//m_gameobj->SetDebugColor(GetDrawColor());
-	} else
-	{
-		//m_gameobj->ResetDebugColor();
-	}
-}
-
-
-
 void SCA_ILogicBrick::RegisterEvent(CValue* eventval)
 {
 	if (m_eventval)
@@ -217,12 +178,17 @@ CValue* SCA_ILogicBrick::GetEvent()
 /* python stuff */
 
 PyTypeObject SCA_ILogicBrick::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_ILogicBrick",
-	sizeof(SCA_ILogicBrick),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -246,8 +212,8 @@ PyParentObject SCA_ILogicBrick::Parents[] = {
 
 
 PyMethodDef SCA_ILogicBrick::Methods[] = {
+	// --> Deprecated
   {"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_NOARGS},
-  // --> Deprecated
   {"getExecutePriority", (PyCFunction) SCA_ILogicBrick::sPyGetExecutePriority, METH_NOARGS},
   {"setExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_VARARGS},
   // <-- Deprecated
@@ -255,7 +221,9 @@ PyMethodDef SCA_ILogicBrick::Methods[] = {
 };
 
 PyAttributeDef SCA_ILogicBrick::Attributes[] = {
-	KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Ueber_Priority),
+	KX_PYATTRIBUTE_RO_FUNCTION("owner",	SCA_ILogicBrick, pyattr_get_owner),
+	KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Priority),
+	KX_PYATTRIBUTE_STRING_RO("name", SCA_ILogicBrick, m_name),
 	{NULL} //Sentinel
 };
 
@@ -277,31 +245,29 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef)
 	return 0;
 }
 
-PyObject*
-SCA_ILogicBrick::py_getattro(PyObject *attr)
+PyObject* SCA_ILogicBrick::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
   py_getattro_up(CValue);
 }
 
+PyObject* SCA_ILogicBrick::py_getattro_dict() {
+	py_getattro_dict_up(CValue);
+}
+
 int SCA_ILogicBrick::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return CValue::py_setattro(attr, value);
+	py_setattro_up(CValue);
 }
 
 
-PyObject* SCA_ILogicBrick::PyGetOwner(PyObject* self)
+PyObject* SCA_ILogicBrick::PyGetOwner()
 {
+	ShowDeprecationWarning("getOwner()", "the owner property");
+	
 	CValue* parent = GetParent();
 	if (parent)
 	{
-		parent->AddRef();
-		return parent;
+		return parent->GetProxy();
 	}
 
 	printf("ERROR: Python scriptblock without owner\n");
@@ -310,29 +276,40 @@ PyObject* SCA_ILogicBrick::PyGetOwner(PyObject* self)
 
 
 
-PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* self, 
-			       PyObject* args, 
-			       PyObject* kwds)
+PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* args)
 {
 	ShowDeprecationWarning("setExecutePriority()", "the executePriority property");
 
 	int priority=0;
 
-    if (!PyArg_ParseTuple(args, "i", &priority)) {
+    if (!PyArg_ParseTuple(args, "i:setExecutePriority", &priority)) {
 		return NULL;
     }
 	
-	m_Execute_Ueber_Priority = priority;
+	m_Execute_Priority = priority;
 
 	Py_RETURN_NONE;
 }
 
 
 
-PyObject* SCA_ILogicBrick::PyGetExecutePriority(PyObject* self)
+PyObject* SCA_ILogicBrick::PyGetExecutePriority()
 {
 	ShowDeprecationWarning("getExecutePriority()", "the executePriority property");
-	return PyInt_FromLong(m_Execute_Ueber_Priority);
+	return PyInt_FromLong(m_Execute_Priority);
+}
+
+
+/*Attribute functions */
+PyObject* SCA_ILogicBrick::pyattr_get_owner(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_ILogicBrick* self= static_cast<SCA_ILogicBrick*>(self_v);
+	CValue* parent = self->GetParent();
+	
+	if (parent)
+		return parent->GetProxy();
+	
+	Py_RETURN_NONE;
 }
 
 
@@ -347,8 +324,6 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg)
 	}
 }
 
-
-
 PyObject* SCA_ILogicBrick::BoolToPyArg(bool boolarg)
 {
 	return PyInt_FromLong(boolarg? KX_TRUE: KX_FALSE);	
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h
index c098f9dfd8ab735cc400b55dabb4ebc93d6569c7..90881c0536f297cfb58f0047901b594d21f79daf 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.h
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h
@@ -59,7 +59,8 @@ public:
 	void SetExecutePriority(int execute_Priority);
 	void SetUeberExecutePriority(int execute_Priority);
 
-	SCA_IObject*	GetParent();
+	SCA_IObject*	GetParent() { return m_gameobj; }
+
 	virtual void	ReParent(SCA_IObject* parent);
 	virtual void	Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
 	virtual void Delete() { Release(); }
@@ -69,17 +70,32 @@ public:
 	virtual CValue*	CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
 
 	virtual const STR_String &	GetText();
-	virtual float		GetNumber();
-	virtual STR_String	GetName();
-	virtual void		SetName(STR_String name);
-	virtual void		ReplicaSetName(STR_String name);
+	virtual double		GetNumber();
+	virtual STR_String&	GetName();
+	virtual void		SetName(const char *);
 		
-	bool				IsActive();
-	void				SetActive(bool active) ;
+	bool				IsActive()
+	{
+		return m_bActive;
+	}
+
+	void				SetActive(bool active)
+	{
+		m_bActive=active;
+	}
+
+	// insert in a QList at position corresponding to m_Execute_Priority
+	void			    InsertActiveQList(SG_QList& head)
+	{
+		SG_QList::iterator<SCA_ILogicBrick> it(head);
+		for(it.begin(); !it.end() && m_Execute_Priority > (*it)->m_Execute_Priority; ++it);
+		it.add_back(this);
+	}
 
 	virtual	bool		LessComparedTo(SCA_ILogicBrick* other);
 	
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	static class SCA_LogicManager*	m_sCurrentLogicManager;
@@ -88,8 +104,10 @@ public:
 	// python methods
 
 	KX_PYMETHOD_NOARGS(SCA_ILogicBrick,GetOwner);
-	KX_PYMETHOD(SCA_ILogicBrick,SetExecutePriority);
+	KX_PYMETHOD_VARARGS(SCA_ILogicBrick,SetExecutePriority);
 	KX_PYMETHOD_NOARGS(SCA_ILogicBrick,GetExecutePriority);
+	
+	static PyObject*	pyattr_get_owner(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 
 	// check that attribute is a property
 	static int CheckProperty(void *self, const PyAttributeDef *attrdef);
diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp
index d1ce377316b9a9f42428dbd1ce81d3a1e63f0c19..8962c8e85808887d351e0e10197c571b97de1d41 100644
--- a/source/gameengine/GameLogic/SCA_IObject.cpp
+++ b/source/gameengine/GameLogic/SCA_IObject.cpp
@@ -70,7 +70,7 @@ SCA_IObject::~SCA_IObject()
 	}
 	for (ita = m_actuators.begin(); !(ita==m_actuators.end()); ++ita)
 	{
-		((CValue*)(*ita))->Release();
+		(*ita)->Delete();
 	}
 
 	//T_InterpolatorList::iterator i;
@@ -79,29 +79,6 @@ SCA_IObject::~SCA_IObject()
 	//}
 }
 
-
-
-SCA_ControllerList& SCA_IObject::GetControllers()
-{
-	return m_controllers;
-}
-
-
-
-SCA_SensorList& SCA_IObject::GetSensors()
-{
-	return m_sensors;
-}
-
-
-
-SCA_ActuatorList& SCA_IObject::GetActuators()
-{
-	return m_actuators;
-}
-
-
-
 void SCA_IObject::AddSensor(SCA_ISensor* act)
 {
 	act->AddRef();
@@ -133,7 +110,7 @@ void SCA_IObject::RegisterActuator(SCA_IActuator* act)
 void SCA_IObject::UnregisterActuator(SCA_IActuator* act)
 {
 	SCA_ActuatorList::iterator ita;
-	for (ita = m_registeredActuators.begin(); ita != m_registeredActuators.end(); ita++)
+	for (ita = m_registeredActuators.begin(); ita != m_registeredActuators.end(); ++ita)
 	{
 		if ((*ita) == act) {
 			(*ita) = m_registeredActuators.back();
@@ -143,20 +120,6 @@ void SCA_IObject::UnregisterActuator(SCA_IActuator* act)
 	}
 }
 
-void SCA_IObject::SetIgnoreActivityCulling(bool b)
-{
-	m_ignore_activity_culling = b;
-}
-
-
-
-bool SCA_IObject::GetIgnoreActivityCulling()
-{
-	return m_ignore_activity_culling;
-}
-
-
-
 void SCA_IObject::ReParentLogic()
 {
 	SCA_ActuatorList& oldactuators  = GetActuators();
@@ -208,7 +171,7 @@ SCA_ISensor* SCA_IObject::FindSensor(const STR_String& sensorname)
 {
 	SCA_ISensor* foundsensor = NULL;
 
-	for (SCA_SensorList::iterator its = m_sensors.begin();!(its==m_sensors.end());its++)
+	for (SCA_SensorList::iterator its = m_sensors.begin();!(its==m_sensors.end());++its)
 	{
 		if ((*its)->GetName() == sensorname)
 		{
@@ -225,7 +188,7 @@ SCA_IController* SCA_IObject::FindController(const STR_String& controllername)
 {
 	SCA_IController* foundcontroller = NULL;
 
-	for (SCA_ControllerList::iterator itc = m_controllers.begin();!(itc==m_controllers.end());itc++)
+	for (SCA_ControllerList::iterator itc = m_controllers.begin();!(itc==m_controllers.end());++itc)
 	{
 		if ((*itc)->GetName() == controllername)
 		{
@@ -242,7 +205,7 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname)
 {
 	SCA_IActuator* foundactuator = NULL;
 
-	for (SCA_ActuatorList::iterator ita = m_actuators.begin();!(ita==m_actuators.end());ita++)
+	for (SCA_ActuatorList::iterator ita = m_actuators.begin();!(ita==m_actuators.end());++ita)
 	{
 		if ((*ita)->GetName() == actuatorname)
 		{
@@ -256,14 +219,6 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname)
 
 
 
-void SCA_IObject::SetCurrentTime(float currentTime) {
-	//T_InterpolatorList::iterator i;
-	//for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
-	//	(*i)->Execute(currentTime);
-	//}
-}
-	
-
 #if 0
 const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist)
 {
@@ -317,7 +272,7 @@ void SCA_IObject::Suspend()
 		SCA_SensorList::iterator i = m_sensors.begin();
 		while (i != m_sensors.end()) {
 			(*i)->Suspend();
-			i++;
+			++i;
 		}
 	}
 }
@@ -332,7 +287,7 @@ void SCA_IObject::Resume(void)
 		SCA_SensorList::iterator i = m_sensors.begin();
 		while (i != m_sensors.end()) {
 			(*i)->Resume();
-			i++;
+			++i;
 		}
 	}
 }
@@ -352,7 +307,7 @@ void SCA_IObject::SetState(unsigned int state)
 	if (tmpstate != m_state)
 	{
 		// update the status of the controllers
-		for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++)
+		for (contit = m_controllers.begin(); contit != m_controllers.end(); ++contit)
 		{
 			(*contit)->ApplyState(tmpstate);
 		}
@@ -360,7 +315,7 @@ void SCA_IObject::SetState(unsigned int state)
 	m_state = state;
 	if (m_state != tmpstate)
 	{
-		for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++)
+		for (contit = m_controllers.begin(); contit != m_controllers.end(); ++contit)
 		{
 			(*contit)->ApplyState(m_state);
 		}
@@ -375,12 +330,17 @@ void SCA_IObject::SetState(unsigned int state)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_IObject::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_IObject",
-	sizeof(SCA_IObject),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -418,3 +378,6 @@ PyObject* SCA_IObject::py_getattro(PyObject *attr) {
 	py_getattro_up(CValue);
 }
 
+PyObject* SCA_IObject::py_getattro_dict() {
+	py_getattro_dict_up(CValue);
+}
diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h
index 44ed3c8f3fe7cc19a00d35e38673af83f0c57612..281c72ecd460a0cf4e1823e3a8173c4532e1b3db 100644
--- a/source/gameengine/GameLogic/SCA_IObject.h
+++ b/source/gameengine/GameLogic/SCA_IObject.h
@@ -52,10 +52,24 @@ class SCA_IObject :	public CValue
 	Py_Header;
 	
 protected:
+	friend class SCA_IActuator;
+	friend class SCA_IController;
 	SCA_SensorList         m_sensors;
 	SCA_ControllerList     m_controllers;
 	SCA_ActuatorList       m_actuators;
 	SCA_ActuatorList       m_registeredActuators;	// actuators that use a pointer to this object
+
+	// SG_Dlist: element of objects with active actuators
+	//           Head: SCA_LogicManager::m_activeActuators
+	// SG_QList: Head of active actuators list on this object
+	//           Elements: SCA_IActuator
+	SG_QList			   m_activeActuators;
+	// SG_Dlist: element of objects with active controllers
+	//           Head: SCA_LogicManager::m_activeControllers
+	// SG_QList: Head of active controller list on this object
+	//           Elements: SCA_IController
+	SG_QList			   m_activeControllers;
+
 	static class MT_Point3 m_sDummy;
 
 	/**
@@ -83,13 +97,38 @@ public:
 	SCA_IObject(PyTypeObject* T=&Type);
 	virtual ~SCA_IObject();
 
-	SCA_ControllerList& GetControllers();
-	SCA_SensorList& GetSensors();
-	SCA_ActuatorList& GetActuators();
+	SCA_ControllerList& GetControllers()
+	{
+		return m_controllers;
+	}
+	SCA_SensorList& GetSensors()
+	{
+		return m_sensors;
+	}
+	SCA_ActuatorList& GetActuators()
+	{
+		return m_actuators;
+	}
+	SG_QList& GetActiveActuators()
+	{
+		return m_activeActuators;
+	}
 
 	void AddSensor(SCA_ISensor* act);
+	void ReserveSensor(int num)
+	{
+		m_sensors.reserve(num);
+	}
 	void AddController(SCA_IController* act);
+	void ReserveController(int num)
+	{
+		m_controllers.reserve(num);
+	}
 	void AddActuator(SCA_IActuator* act);
+	void ReserveActuator(int num)
+	{
+		m_actuators.reserve(num);
+	}
 	void RegisterActuator(SCA_IActuator* act);
 	void UnregisterActuator(SCA_IActuator* act);
 	
@@ -97,20 +136,26 @@ public:
 	SCA_IActuator* FindActuator(const STR_String& actuatorname);
 	SCA_IController* FindController(const STR_String& controllername);
 
-	void SetCurrentTime(float currentTime);
+	void SetCurrentTime(float currentTime) {}
 
 	void ReParentLogic();
 	
 	/**
 	 * Set whether or not to ignore activity culling requests
 	 */
-	void SetIgnoreActivityCulling(bool b);
+	void SetIgnoreActivityCulling(bool b)
+	{
+		m_ignore_activity_culling = b;
+	}
 
 	/**
 	 * Set whether or not this object wants to ignore activity culling
 	 * requests
 	 */
-	bool GetIgnoreActivityCulling();
+	bool GetIgnoreActivityCulling()
+	{
+		return m_ignore_activity_culling;
+	}
 
 	/**
 	 * Suspend all progress.
@@ -146,6 +191,7 @@ public:
 	
 	// here come the python forwarded methods
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 
 	virtual int GetGameObjectType() {return -1;}
 	
diff --git a/source/gameengine/GameLogic/SCA_IScene.cpp b/source/gameengine/GameLogic/SCA_IScene.cpp
index 9fbeb7069107347827bf2bbf2963b948a0040adb..86b176a38b0950d6015e17d63f178acb687198ee 100644
--- a/source/gameengine/GameLogic/SCA_IScene.cpp
+++ b/source/gameengine/GameLogic/SCA_IScene.cpp
@@ -50,7 +50,7 @@ SCA_IScene::SCA_IScene()
 void SCA_IScene::RemoveAllDebugProperties()
 {
 	for (std::vector<SCA_DebugProp*>::iterator it = m_debugList.begin();
-		!(it==m_debugList.end());it++)
+		!(it==m_debugList.end());++it)
 	{
 		delete (*it);
 	}
diff --git a/source/gameengine/GameLogic/SCA_IScene.h b/source/gameengine/GameLogic/SCA_IScene.h
index d18778a37c213b31b09c7539a4b0c8c00ae25aee..b641efc6ee1c74ee03d9870b9de3fb8b2ff76e96 100644
--- a/source/gameengine/GameLogic/SCA_IScene.h
+++ b/source/gameengine/GameLogic/SCA_IScene.h
@@ -52,7 +52,7 @@ public:
 												int lifespan=0)=0;
 	virtual void	RemoveObject(class CValue* gameobj)=0;
 	virtual void	DelayedRemoveObject(class CValue* gameobj)=0;
-	virtual void	DelayedReleaseObject(class CValue* gameobj)=0;
+	//virtual void	DelayedReleaseObject(class CValue* gameobj)=0;
 	
 	virtual void	ReplaceMesh(class CValue* gameobj,
 								void* meshobj)=0;
diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp
index 8a40c0c35f3a99ecbfc10a73630df5c347f4a485..2783bf146004489f701e9b8b0a3877d470a30cac 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ISensor.cpp
@@ -45,26 +45,28 @@ void	SCA_ISensor::ReParent(SCA_IObject* parent)
 	SCA_ILogicBrick::ReParent(parent);
 	// will be done when the sensor is activated
 	//m_eventmgr->RegisterSensor(this);
-	this->SetActive(false);
+	//this->SetActive(false);
 }
 
 
 SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj,
 						 class SCA_EventManager* eventmgr,
 						 PyTypeObject* T ) :
-	SCA_ILogicBrick(gameobj,T),
-	m_triggered(false)
+	SCA_ILogicBrick(gameobj,T)
 {
 	m_links = 0;
 	m_suspended = false;
 	m_invert = false;
 	m_level = false;
+	m_tap = false;
 	m_reset = false;
 	m_pos_ticks = 0;
 	m_neg_ticks = 0;
 	m_pos_pulsemode = false;
 	m_neg_pulsemode = false;
 	m_pulse_frequency = 0;
+	m_state = false;
+	m_prev_state = false;
 	
 	m_eventmgr = eventmgr;
 }
@@ -75,6 +77,12 @@ SCA_ISensor::~SCA_ISensor()
 	// intentionally empty
 }
 
+void SCA_ISensor::ProcessReplica()
+{
+	SCA_ILogicBrick::ProcessReplica();
+	m_linkedcontrollers.clear();
+}
+
 bool SCA_ISensor::IsPositiveTrigger() { 
 	bool result = false;
 	
@@ -104,9 +112,13 @@ void SCA_ISensor::SetLevel(bool lvl) {
 	m_level = lvl;
 }
 
+void SCA_ISensor::SetTap(bool tap) {
+	m_tap = tap;
+}
 
-float SCA_ISensor::GetNumber() {
-	return IsPositiveTrigger();
+
+double SCA_ISensor::GetNumber() {
+	return GetState();
 }
 
 void SCA_ISensor::Suspend() {
@@ -143,27 +155,80 @@ void SCA_ISensor::RegisterToManager()
 {
 	// sensor is just activated, initialize it
 	Init();
-	m_newControllers.erase(m_newControllers.begin(), m_newControllers.end());
+	m_state = false;
 	m_eventmgr->RegisterSensor(this);
 }
 
+void SCA_ISensor::LinkToController(SCA_IController* controller)
+{
+	m_linkedcontrollers.push_back(controller);
+}
+
+void SCA_ISensor::UnlinkController(SCA_IController* controller)
+{
+	std::vector<class SCA_IController*>::iterator contit;
+	for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit)
+	{
+		if ((*contit) == controller)
+		{
+			*contit = m_linkedcontrollers.back();
+			m_linkedcontrollers.pop_back();
+			return;
+		}
+	}
+	printf("Missing link from sensor %s:%s to controller %s:%s\n", 
+		m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), 
+		controller->GetParent()->GetName().ReadPtr(), controller->GetName().ReadPtr());
+}
+
+void SCA_ISensor::UnlinkAllControllers()
+{
+	std::vector<class SCA_IController*>::iterator contit;
+	for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit)
+	{
+		(*contit)->UnlinkSensor(this);
+	}
+	m_linkedcontrollers.clear();
+}
+
 void SCA_ISensor::UnregisterToManager()
 {
 	m_eventmgr->RemoveSensor(this);
+	m_links = 0;
 }
 
-void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr,	  CValue* event)
+void SCA_ISensor::ActivateControllers(class SCA_LogicManager* logicmgr)
+{
+    for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin();
+		c!=m_linkedcontrollers.end();++c)
+	{
+		SCA_IController* contr = *c;
+		if (contr->IsActive())
+			logicmgr->AddTriggeredController(contr, this);
+	}
+}
+
+void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr)
 {
 	
 	// calculate if a __triggering__ is wanted
 	// don't evaluate a sensor that is not connected to any controller
 	if (m_links && !m_suspended) {
-		bool result = this->Evaluate(event);
+		bool result = this->Evaluate();
+		// store the state for the rest of the logic system
+		m_prev_state = m_state;
+		m_state = this->IsPositiveTrigger();
 		if (result) {
-			logicmgr->AddActivatedSensor(this);	
-			// reset these counters so that pulse are synchronized with transition
-			m_pos_ticks = 0;
-			m_neg_ticks = 0;
+			// the sensor triggered this frame
+			if (m_state || !m_tap) {
+				ActivateControllers(logicmgr);	
+				// reset these counters so that pulse are synchronized with transition
+				m_pos_ticks = 0;
+				m_neg_ticks = 0;
+			} else
+			{
+				result = false;
+			}
 		} else
 		{
 			/* First, the pulsing behaviour, if pulse mode is
@@ -172,41 +237,55 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr,	  CValue* event)
 			if (m_pos_pulsemode) {
 				m_pos_ticks++;
 				if (m_pos_ticks > m_pulse_frequency) {
-					if ( this->IsPositiveTrigger() )
+					if ( m_state )
 					{
-						logicmgr->AddActivatedSensor(this);
+						ActivateControllers(logicmgr);
+						result = true;
 					}
 					m_pos_ticks = 0;
 				} 
 			}
-			
-			if (m_neg_pulsemode)
+			// negative pulse doesn't make sense in tap mode, skip
+			if (m_neg_pulsemode && !m_tap)
 			{
 				m_neg_ticks++;
 				if (m_neg_ticks > m_pulse_frequency) {
-					if (!this->IsPositiveTrigger() )
+					if (!m_state )
 					{
-						logicmgr->AddActivatedSensor(this);
+						ActivateControllers(logicmgr);
+						result = true;
 					}
 					m_neg_ticks = 0;
 				}
 			}
 		}
-		if (!m_newControllers.empty())
+		if (m_tap)
 		{
-			if (!IsActive() && m_level)
+			// in tap mode: we send always a negative pulse immediately after a positive pulse
+			if (!result)
 			{
-				// This level sensor is connected to at least one controller that was just made 
-				// active but it did not generate an event yet, do it now to those controllers only 
-				for (std::vector<SCA_IController*>::iterator ci=m_newControllers.begin();
-					 ci != m_newControllers.end(); ci++)
+				// the sensor did not trigger on this frame
+				if (m_prev_state)
 				{
-					logicmgr->AddTriggeredController(*ci, this);
+					// but it triggered on previous frame => send a negative pulse
+					ActivateControllers(logicmgr);
+					result = true;
 				}
+				// in any case, absence of trigger means sensor off
+				m_state = false;
+			}
+		}
+		if (!result && m_level)
+		{
+			// This level sensor is connected to at least one controller that was just made 
+			// active but it did not generate an event yet, do it now to those controllers only 
+			for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin();
+				c!=m_linkedcontrollers.end();++c)
+			{
+				SCA_IController* contr = *c;
+				if (contr->IsJustActivated())
+					logicmgr->AddTriggeredController(contr, this);
 			}
-			// clear the list. Instead of using clear, which also release the memory,
-			// use erase, which keeps the memory available for next time.
-			m_newControllers.erase(m_newControllers.begin(), m_newControllers.end());
 		}
 	} 
 }
@@ -218,17 +297,17 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr,	  CValue* event)
 const char SCA_ISensor::IsPositive_doc[] = 
 "isPositive()\n"
 "\tReturns whether the sensor is in an active state.\n";
-PyObject* SCA_ISensor::PyIsPositive(PyObject* self)
+PyObject* SCA_ISensor::PyIsPositive()
 {
 	ShowDeprecationWarning("isPositive()", "the read-only positive property");
-	int retval = IsPositiveTrigger();
+	int retval = GetState();
 	return PyInt_FromLong(retval);
 }
 
 const char SCA_ISensor::IsTriggered_doc[] = 
 "isTriggered()\n"
 "\tReturns whether the sensor has triggered the current controller.\n";
-PyObject* SCA_ISensor::PyIsTriggered(PyObject* self)
+PyObject* SCA_ISensor::PyIsTriggered()
 {
 	ShowDeprecationWarning("isTriggered()", "the read-only triggered property");
 	// check with the current controller
@@ -244,7 +323,7 @@ PyObject* SCA_ISensor::PyIsTriggered(PyObject* self)
 const char SCA_ISensor::GetUsePosPulseMode_doc[] = 
 "getUsePosPulseMode()\n"
 "\tReturns whether positive pulse mode is active.\n";
-PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self)
+PyObject* SCA_ISensor::PyGetUsePosPulseMode()
 {
 	ShowDeprecationWarning("getUsePosPulseMode()", "the usePosPulseMode property");
 	return BoolToPyArg(m_pos_pulsemode);
@@ -258,11 +337,11 @@ const char SCA_ISensor::SetUsePosPulseMode_doc[] =
 "\t - pulse? : Pulse when a positive event occurs?\n"
 "\t            (KX_TRUE, KX_FALSE)\n"
 "\tSet whether to do pulsing when positive pulses occur.\n";
-PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* args)
 {
 	ShowDeprecationWarning("setUsePosPulseMode()", "the usePosPulseMode property");
 	int pyarg = 0;
-	if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
+	if(!PyArg_ParseTuple(args, "i:setUsePosPulseMode", &pyarg)) { return NULL; }
 	m_pos_pulsemode = PyArgToBool(pyarg);
 	Py_RETURN_NONE;
 }
@@ -273,7 +352,7 @@ PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyOb
 const char SCA_ISensor::GetFrequency_doc[] = 
 "getFrequency()\n"
 "\tReturns the frequency of the updates in pulse mode.\n" ;
-PyObject* SCA_ISensor::PyGetFrequency(PyObject* self)
+PyObject* SCA_ISensor::PyGetFrequency()
 {
 	ShowDeprecationWarning("getFrequency()", "the frequency property");
 	return PyInt_FromLong(m_pulse_frequency);
@@ -287,12 +366,12 @@ const char SCA_ISensor::SetFrequency_doc[] =
 "\t- pulse_frequency: The frequency of the updates in pulse mode (integer)"
 "\tSet the frequency of the updates in pulse mode.\n"
 "\tIf the frequency is negative, it is set to 0.\n" ;
-PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PySetFrequency(PyObject* args)
 {
 	ShowDeprecationWarning("setFrequency()", "the frequency property");
 	int pulse_frequencyArg = 0;
 
-	if(!PyArg_ParseTuple(args, "i", &pulse_frequencyArg)) {
+	if(!PyArg_ParseTuple(args, "i:setFrequency", &pulse_frequencyArg)) {
 		return NULL;
 	}
 	
@@ -310,7 +389,7 @@ PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject*
 const char SCA_ISensor::GetInvert_doc[] = 
 "getInvert()\n"
 "\tReturns whether or not pulses from this sensor are inverted.\n" ;
-PyObject* SCA_ISensor::PyGetInvert(PyObject* self)
+PyObject* SCA_ISensor::PyGetInvert()
 {
 	ShowDeprecationWarning("getInvert()", "the invert property");
 	return BoolToPyArg(m_invert);
@@ -320,11 +399,11 @@ const char SCA_ISensor::SetInvert_doc[] =
 "setInvert(invert?)\n"
 "\t- invert?: Invert the event-values? (KX_TRUE, KX_FALSE)\n"
 "\tSet whether to invert pulses.\n";
-PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PySetInvert(PyObject* args)
 {
 	ShowDeprecationWarning("setInvert()", "the invert property");
 	int pyarg = 0;
-	if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
+	if(!PyArg_ParseTuple(args, "i:setInvert", &pyarg)) { return NULL; }
 	m_invert = PyArgToBool(pyarg);
 	Py_RETURN_NONE;
 }
@@ -336,7 +415,7 @@ const char SCA_ISensor::GetLevel_doc[] =
 "\tA level detector will immediately generate a pulse, negative or positive\n"
 "\tdepending on the sensor condition, as soon as the state is activated.\n"
 "\tA edge detector will wait for a state change before generating a pulse.\n";
-PyObject* SCA_ISensor::PyGetLevel(PyObject* self)
+PyObject* SCA_ISensor::PyGetLevel()
 {
 	ShowDeprecationWarning("getLevel()", "the level property");
 	return BoolToPyArg(m_level);
@@ -346,11 +425,11 @@ const char SCA_ISensor::SetLevel_doc[] =
 "setLevel(level?)\n"
 "\t- level?: Detect level instead of edge? (KX_TRUE, KX_FALSE)\n"
 "\tSet whether to detect level or edge transition when entering a state.\n";
-PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PySetLevel(PyObject* args)
 {
 	ShowDeprecationWarning("setLevel()", "the level property");
 	int pyarg = 0;
-	if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
+	if(!PyArg_ParseTuple(args, "i:setLevel", &pyarg)) { return NULL; }
 	m_level = PyArgToBool(pyarg);
 	Py_RETURN_NONE;
 }
@@ -358,7 +437,7 @@ PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds
 const char SCA_ISensor::GetUseNegPulseMode_doc[] = 
 "getUseNegPulseMode()\n"
 "\tReturns whether negative pulse mode is active.\n";
-PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self)
+PyObject* SCA_ISensor::PyGetUseNegPulseMode()
 {
 	ShowDeprecationWarning("getUseNegPulseMode()", "the useNegPulseMode property");
 	return BoolToPyArg(m_neg_pulsemode);
@@ -369,11 +448,11 @@ const char SCA_ISensor::SetUseNegPulseMode_doc[] =
 "\t - pulse? : Pulse when a negative event occurs?\n"
 "\t            (KX_TRUE, KX_FALSE)\n"
 "\tSet whether to do pulsing when negative pulses occur.\n";
-PyObject* SCA_ISensor::PySetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PySetUseNegPulseMode(PyObject* args)
 {
 	ShowDeprecationWarning("setUseNegPulseMode()", "the useNegPulseMode property");
 	int pyarg = 0;
-	if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
+	if(!PyArg_ParseTuple(args, "i:setUseNegPulseMode", &pyarg)) { return NULL; }
 	m_neg_pulsemode = PyArgToBool(pyarg);
 	Py_RETURN_NONE;
 }
@@ -385,6 +464,7 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset,
 "\tThe sensor is put in its initial state as if it was just activated.\n")
 {
 	Init();
+	m_prev_state = false;
 	Py_RETURN_NONE;
 }
 
@@ -393,12 +473,17 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset,
 /* ----------------------------------------------- */
 
 PyTypeObject SCA_ISensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_ISensor",
-	sizeof(SCA_ISensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -453,41 +538,59 @@ PyAttributeDef SCA_ISensor::Attributes[] = {
 	KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode),
 	KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency),
 	KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert),
-	KX_PYATTRIBUTE_BOOL_RW("level",SCA_ISensor,m_level),
-	// make these properties read-only in _setaddr, must still implement them in py_getattro
-	KX_PYATTRIBUTE_DUMMY("triggered"),
-	KX_PYATTRIBUTE_DUMMY("positive"),
+	KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level),
+	KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap),
+	KX_PYATTRIBUTE_RO_FUNCTION("triggered", SCA_ISensor, pyattr_get_triggered),
+	KX_PYATTRIBUTE_RO_FUNCTION("positive", SCA_ISensor, pyattr_get_positive),
+	//KX_PYATTRIBUTE_TODO("links"),
+	//KX_PYATTRIBUTE_TODO("posTicks"),
+	//KX_PYATTRIBUTE_TODO("negTicks"),
 	{ NULL }	//Sentinel
 };
 
-PyObject*
-SCA_ISensor::py_getattro(PyObject *attr)
+PyObject* SCA_ISensor::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
-	
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "triggered"))
-	{
-		int retval = 0;
-		if (SCA_PythonController::m_sCurrentController)
-			retval = SCA_PythonController::m_sCurrentController->IsTriggered(this);
-		return PyInt_FromLong(retval);
-	}
-	if (!strcmp(attr_str, "positive"))
-	{	
-		int retval = IsPositiveTrigger();
-		return PyInt_FromLong(retval);
-	}
 	py_getattro_up(SCA_ILogicBrick);
 }
 
+PyObject* SCA_ISensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ILogicBrick);
+}
+
 int SCA_ISensor::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_ILogicBrick::py_setattro(attr, value);
+	py_setattro_up(SCA_ILogicBrick);
+}
+
+PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
+	int retval = 0;
+	if (SCA_PythonController::m_sCurrentController)
+		retval = SCA_PythonController::m_sCurrentController->IsTriggered(self);
+	return PyInt_FromLong(retval);
+}
+
+PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
+	return PyInt_FromLong(self->GetState());
 }
+
+int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
+	if (self->m_level)
+		self->m_tap = false;
+	return 0;
+}
+
+int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v);
+	if (self->m_tap)
+		self->m_level = false;
+	return 0;
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h
index ce7b66df1cda4b8c81df235dd1adee16e189bde3..9aeda728caf8d0f03129ea34ae9863bd55738d98 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.h
+++ b/source/gameengine/GameLogic/SCA_ISensor.h
@@ -32,18 +32,22 @@
 #ifndef __SCA_ISENSOR
 #define __SCA_ISENSOR
 
-#include "SCA_ILogicBrick.h"
+#include "SCA_IController.h"
 
 #include <vector>
 
 /**
  * Interface Class for all logic Sensors. Implements
- * pulsemode,pulsefrequency */
+ * pulsemode,pulsefrequency 
+ * Use of SG_DList element: link sensors to their respective event manager
+ *                          Head: SCA_EventManager::m_sensors
+ * Use of SG_QList element: not used
+ */
 class SCA_ISensor : public SCA_ILogicBrick
 {
 	Py_Header;
+protected:
 	class SCA_EventManager* m_eventmgr;
-	bool	m_triggered;
 
 	/** Pulse positive  pulses? */
 	bool m_pos_pulsemode;
@@ -66,6 +70,9 @@ class SCA_ISensor : public SCA_ILogicBrick
 	/** detect level instead of edge*/
 	bool m_level;
 
+	/** tap mode */
+	bool m_tap;
+
 	/** sensor has been reset */
 	bool m_reset;
 
@@ -75,8 +82,13 @@ class SCA_ISensor : public SCA_ILogicBrick
 	/** number of connections to controller */
 	int m_links;
 
-	/** list of controllers that have just activated this sensor because of a state change */
-	std::vector<class SCA_IController*> m_newControllers;
+	/** current sensor state */
+	bool m_state;
+
+	/** previous state (for tap option) */
+	bool m_prev_state;
+
+	std::vector<class SCA_IController*>		m_linkedcontrollers;
 
 public:
 	SCA_ISensor(SCA_IObject* gameobj,
@@ -89,8 +101,8 @@ public:
 	/* an implementation on this level. It requires an evaluate on the lower */
 	/* level of individual sensors. Mapping the old activate()s is easy.     */
 	/* The IsPosTrig() also has to change, to keep things consistent.        */
-	void Activate(class SCA_LogicManager* logicmgr,CValue* event);
-	virtual bool Evaluate(CValue* event) = 0;
+	void Activate(class SCA_LogicManager* logicmgr);
+	virtual bool Evaluate() = 0;
 	virtual bool IsPositiveTrigger();
 	virtual void Init();
 
@@ -109,11 +121,22 @@ public:
 	void SetInvert(bool inv);
 	/** set the level detection on or off */
 	void SetLevel(bool lvl);
+	void SetTap(bool tap);
 
 	virtual void RegisterToManager();
 	virtual void UnregisterToManager();
+	void ReserveController(int num)
+	{
+		m_linkedcontrollers.reserve(num);
+	}
+	void LinkToController(SCA_IController* controller);
+	void UnlinkController(SCA_IController* controller);
+	void UnlinkAllControllers();
+	void ActivateControllers(class SCA_LogicManager* logicmgr);
 
-	virtual float GetNumber();
+	virtual void ProcessReplica();
+
+	virtual double GetNumber();
 
 	/** Stop sensing for a while. */
 	void Suspend();
@@ -121,11 +144,15 @@ public:
 	/** Is this sensor switched off? */
 	bool IsSuspended();
 	
+	/** get the state of the sensor: positive or negative */
+	bool GetState()
+	{
+		return m_state;
+	}
+
 	/** Resume sensing. */
 	void Resume();
 
-	void AddNewController(class SCA_IController* controller)
-		{ m_newControllers.push_back(controller); }
 	void ClrLink()
 		{ m_links = 0; }
 	void IncLink()
@@ -137,23 +164,29 @@ public:
 	/* Python functions: */
 	
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	//Deprecated functions ----->
 	KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive);
 	KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered);
 	KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode);
-	KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode);
+	KX_PYMETHOD_DOC_VARARGS(SCA_ISensor,SetUsePosPulseMode);
 	KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency);
-	KX_PYMETHOD_DOC(SCA_ISensor,SetFrequency);
+	KX_PYMETHOD_DOC_VARARGS(SCA_ISensor,SetFrequency);
 	KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUseNegPulseMode);
-	KX_PYMETHOD_DOC(SCA_ISensor,SetUseNegPulseMode);
+	KX_PYMETHOD_DOC_VARARGS(SCA_ISensor,SetUseNegPulseMode);
 	KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetInvert);
-	KX_PYMETHOD_DOC(SCA_ISensor,SetInvert);
+	KX_PYMETHOD_DOC_VARARGS(SCA_ISensor,SetInvert);
 	KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetLevel);
-	KX_PYMETHOD_DOC(SCA_ISensor,SetLevel);
+	KX_PYMETHOD_DOC_VARARGS(SCA_ISensor,SetLevel);
 	//<------
 	KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,reset);
+	
+	static PyObject*	pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int          pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int          pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 };
 
 #endif //__SCA_ISENSOR
diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp
index f3ce549a6373eeb12c5e3a9f41c7305e81d95a70..ff8f3b1c81fbbec7aedf9cbecff6b909f17f804e 100644
--- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp
+++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp
@@ -59,20 +59,21 @@ SCA_JoystickManager::~SCA_JoystickManager()
 
 void SCA_JoystickManager::NextFrame(double curtime,double deltatime)
 {
-	if (m_sensors.size()==0) {
+	if (m_sensors.Empty()) {
 		return;
 	}
 	else {
-		set<SCA_ISensor*>::iterator it;
+		;
 #ifndef	DISABLE_SDL
 		SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */
 #endif
-		for (it = m_sensors.begin(); it != m_sensors.end(); it++)
+		SG_DList::iterator<SCA_JoystickSensor> it(m_sensors);
+		for (it.begin();!it.end();++it)
 		{
-			SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it);
+			SCA_JoystickSensor* joysensor = *it;
 			if(!joysensor->IsSuspended())
 			{
-				joysensor->Activate(m_logicmgr, NULL);
+				joysensor->Activate(m_logicmgr);
 			}
 		}
 	}
diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
index 0cfd6843c1b965e438cd01e520a1c31ea947f69d..906d454b728f4ebf2758fb181a5032cdd7aefa3a 100644
--- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
@@ -87,7 +87,7 @@ CValue* SCA_JoystickSensor::GetReplica()
 {
 	SCA_JoystickSensor* replica = new SCA_JoystickSensor(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	replica->Init();
 	return replica;
 }
@@ -102,7 +102,7 @@ bool SCA_JoystickSensor::IsPositiveTrigger()
 }
 
 
-bool SCA_JoystickSensor::Evaluate(CValue* event)
+bool SCA_JoystickSensor::Evaluate()
 {
 	SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
 	bool result = false;
@@ -117,11 +117,15 @@ bool SCA_JoystickSensor::Evaluate(CValue* event)
 	case KX_JOYSENSORMODE_AXIS:
 		{
 		/* what is what!
-			m_axisf == 0 == right
+			m_axisf == JOYAXIS_RIGHT, JOYAXIS_UP, JOYAXIS_DOWN, JOYAXIS_LEFT
 			m_axisf == 1 == up
 			m_axisf == 2 == left
 			m_axisf == 3 == down
-			numberof== m_axis  -- max 2
+			
+			numberof== m_axis (1-4), range is half of JOYAXIS_MAX since 
+				it assumes the axis joysticks are axis parirs (0,1), (2,3), etc
+				also note that this starts at 1 where functions its used
+				with expect a zero index.
 			*/
 			
 			if (!js->IsTrigAxis() && !reset) /* No events from SDL? - dont bother */
@@ -129,7 +133,7 @@ bool SCA_JoystickSensor::Evaluate(CValue* event)
 			
 			js->cSetPrecision(m_precision);
 			if (m_bAllEvents) {
-				if(js->aAnyAxisIsPositive(m_axis)){
+				if(js->aAxisPairIsPositive(m_axis-1)){ /* use zero based axis index internally */
 					m_istrig = 1;
 					result = true;
 				}else{
@@ -139,8 +143,8 @@ bool SCA_JoystickSensor::Evaluate(CValue* event)
 					}
 				}
 			}
-			else if(m_axisf == 1){
-				if(js->aUpAxisIsPositive(m_axis)){
+			else {
+				if(js->aAxisPairDirectionIsPositive(m_axis-1, m_axisf)){ /* use zero based axis index internally */
 					m_istrig = 1;
 					result = true;
 				}else{
@@ -150,41 +154,28 @@ bool SCA_JoystickSensor::Evaluate(CValue* event)
 					}
 				}
 			}
-			else if(m_axisf == 3){
-				if(js->aDownAxisIsPositive(m_axis)){
-					m_istrig = 1;
-					result = true;
-				}else{
-					if(m_istrig){
-						m_istrig = 0;
-						result = true;
-					}
-				}
-			}
-			else if(m_axisf == 2){
-				if(js->aLeftAxisIsPositive(m_axis)){
-					m_istrig = 1;
-					result = true;
-				}else{
-					if(m_istrig){
-						m_istrig = 0;
-						result = true;
-					}
-				}
-			}
-			else if(m_axisf == 0){
-				if(js->aRightAxisIsPositive(m_axis)){
-					m_istrig = 1;
+			break;
+		}
+	case KX_JOYSENSORMODE_AXIS_SINGLE:
+		{
+			/* Like KX_JOYSENSORMODE_AXIS but dont pair up axis */
+			if (!js->IsTrigAxis() && !reset) /* No events from SDL? - dont bother */
+				return false;
+			
+			/* No need for 'm_bAllEvents' check here since were only checking 1 axis */
+			js->cSetPrecision(m_precision);
+			if(js->aAxisIsPositive(m_axis-1)){ /* use zero based axis index internally */
+				m_istrig = 1;
+				result = true;
+			}else{
+				if(m_istrig){
+					m_istrig = 0;
 					result = true;
-				}else{
-					if(m_istrig){
-						m_istrig = 0;
-						result = true;
-					}
 				}
 			}
 			break;
 		}
+		
 	case KX_JOYSENSORMODE_BUTTON:
 		{
 		/* what is what!
@@ -275,12 +266,17 @@ bool SCA_JoystickSensor::isValid(SCA_JoystickSensor::KX_JOYSENSORMODE m)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_JoystickSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"SCA_JoystickSensor",
-		sizeof(SCA_JoystickSensor),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -333,50 +329,28 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = {
 	KX_PYATTRIBUTE_INT_RW("button",0,100,false,SCA_JoystickSensor,m_button),
 	KX_PYATTRIBUTE_INT_LIST_RW_CHECK("axis",0,3,true,SCA_JoystickSensor,m_axis,2,CheckAxis),
 	KX_PYATTRIBUTE_INT_LIST_RW_CHECK("hat",0,12,true,SCA_JoystickSensor,m_hat,2,CheckHat),
-	// dummy attributes will just be read-only in py_setattro
-	// you still need to defined them in py_getattro
-	KX_PYATTRIBUTE_DUMMY("axisPosition"),
-	KX_PYATTRIBUTE_DUMMY("numAxis"),
-	KX_PYATTRIBUTE_DUMMY("numButtons"),
-	KX_PYATTRIBUTE_DUMMY("numHats"),
-	KX_PYATTRIBUTE_DUMMY("connected"),
+	KX_PYATTRIBUTE_RO_FUNCTION("axisValues",	SCA_JoystickSensor, pyattr_get_axis_values),
+	KX_PYATTRIBUTE_RO_FUNCTION("axisSingle", SCA_JoystickSensor, pyattr_get_axis_single),
+	KX_PYATTRIBUTE_RO_FUNCTION("numAxis",		SCA_JoystickSensor, pyattr_get_num_axis),
+	KX_PYATTRIBUTE_RO_FUNCTION("numButtons",	SCA_JoystickSensor, pyattr_get_num_buttons),
+	KX_PYATTRIBUTE_RO_FUNCTION("numHats",		SCA_JoystickSensor, pyattr_get_num_hats),
+	KX_PYATTRIBUTE_RO_FUNCTION("connected",		SCA_JoystickSensor, pyattr_get_connected),
+	//KX_PYATTRIBUTE_TODO("events"),
 	{ NULL }	//Sentinel
 };
 
-PyObject* SCA_JoystickSensor::py_getattro(PyObject *attr) {
-	SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
-	char *attr_str= PyString_AsString(attr);
-	
-	if (!strcmp(attr_str, "axisPosition")) {
-		if(joy)
-			return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21());
-		else
-			return Py_BuildValue("[iiii]", 0, 0, 0, 0);
-	}
-	if (!strcmp(attr_str, "numAxis")) {
-		return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 );
-	}
-	if (!strcmp(attr_str, "numButtons")) {
-		return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 );
-	}
-	if (!strcmp(attr_str, "numHats")) {
-		return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 );
-	}
-	if (!strcmp(attr_str, "connected")) {
-		return PyBool_FromLong( joy ? joy->Connected() : 0 );
-	}
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
+PyObject* SCA_JoystickSensor::py_getattro(PyObject *attr)
+{
 	py_getattro_up(SCA_ISensor);
 }
 
+PyObject* SCA_JoystickSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 int SCA_JoystickSensor::py_setattro(PyObject *attr, PyObject *value) 
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_ISensor::py_setattro(attr, value);
+	py_setattro_up(SCA_ISensor);
 }
 
 
@@ -384,7 +358,7 @@ int SCA_JoystickSensor::py_setattro(PyObject *attr, PyObject *value)
 const char SCA_JoystickSensor::GetIndex_doc[] = 
 "getIndex\n"
 "\tReturns the joystick index to use.\n";
-PyObject* SCA_JoystickSensor::PyGetIndex( PyObject* self ) {
+PyObject* SCA_JoystickSensor::PyGetIndex( ) {
 	ShowDeprecationWarning("getIndex()", "the index property");
 	return PyInt_FromLong(m_joyindex);
 }
@@ -394,7 +368,7 @@ PyObject* SCA_JoystickSensor::PyGetIndex( PyObject* self ) {
 const char SCA_JoystickSensor::SetIndex_doc[] = 
 "setIndex\n"
 "\tSets the joystick index to use.\n";
-PyObject* SCA_JoystickSensor::PySetIndex( PyObject* self, PyObject* value ) {
+PyObject* SCA_JoystickSensor::PySetIndex( PyObject* value ) {
 	ShowDeprecationWarning("setIndex()", "the index property");
 	int index = PyInt_AsLong( value ); /* -1 on error, will raise an error in this case */
 	if (index < 0 || index >= JOYINDEX_MAX) {
@@ -410,7 +384,7 @@ PyObject* SCA_JoystickSensor::PySetIndex( PyObject* self, PyObject* value ) {
 const char SCA_JoystickSensor::GetAxis_doc[] = 
 "getAxis\n"
 "\tReturns the current axis this sensor reacts to.\n";
-PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) {
+PyObject* SCA_JoystickSensor::PyGetAxis( ) {
 	ShowDeprecationWarning("getAxis()", "the axis property");
 	return Py_BuildValue("[ii]",m_axis, m_axisf);
 }
@@ -420,11 +394,11 @@ PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) {
 const char SCA_JoystickSensor::SetAxis_doc[] = 
 "setAxis\n"
 "\tSets the current axis this sensor reacts to.\n";
-PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) {
+PyObject* SCA_JoystickSensor::PySetAxis( PyObject* args ) {
 	ShowDeprecationWarning("setAxis()", "the axis property");
 	
 	int axis,axisflag;
-	if(!PyArg_ParseTuple(args, "ii", &axis, &axisflag)){
+	if(!PyArg_ParseTuple(args, "ii:setAxis", &axis, &axisflag)){
 		return NULL;
 	}
 	m_axis = axis;
@@ -437,13 +411,18 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) {
 const char SCA_JoystickSensor::GetAxisValue_doc[] = 
 "getAxisValue\n"
 "\tReturns a list of the values for the current state of each axis.\n";
-PyObject* SCA_JoystickSensor::PyGetAxisValue( PyObject* self) {
+PyObject* SCA_JoystickSensor::PyGetAxisValue( ) {
 	ShowDeprecationWarning("getAxisValue()", "the axisPosition property");
 	SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
-	if(joy)
-		return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21());
-	else
-		return Py_BuildValue("[iiii]", 0, 0, 0, 0);
+	
+	int axis_index= joy->GetNumberOfAxes();
+	PyObject *list= PyList_New(axis_index);
+	
+	while(axis_index--) {
+		PyList_SET_ITEM(list, axis_index, PyInt_FromLong(joy->GetAxisPosition(axis_index)));
+	}
+	
+	return list;
 }
 
 
@@ -451,7 +430,7 @@ PyObject* SCA_JoystickSensor::PyGetAxisValue( PyObject* self) {
 const char SCA_JoystickSensor::GetThreshold_doc[] = 
 "getThreshold\n"
 "\tReturns the threshold of the axis.\n";
-PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) {
+PyObject* SCA_JoystickSensor::PyGetThreshold( ) {
 	ShowDeprecationWarning("getThreshold()", "the threshold property");
 	return PyInt_FromLong(m_precision);
 }
@@ -461,10 +440,10 @@ PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) {
 const char SCA_JoystickSensor::SetThreshold_doc[] = 
 "setThreshold\n"
 "\tSets the threshold of the axis.\n";
-PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) {
+PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* args ) {
 	ShowDeprecationWarning("setThreshold()", "the threshold property");
 	int thresh;
-	if(!PyArg_ParseTuple(args, "i", &thresh)){
+	if(!PyArg_ParseTuple(args, "i:setThreshold", &thresh)){
 		return NULL;
 	}
 	m_precision = thresh;
@@ -475,7 +454,7 @@ PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) {
 const char SCA_JoystickSensor::GetButton_doc[] = 
 "getButton\n"
 "\tReturns the current button this sensor is checking.\n";
-PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) {
+PyObject* SCA_JoystickSensor::PyGetButton( ) {
 	ShowDeprecationWarning("getButton()", "the button property");
 	return PyInt_FromLong(m_button);
 }
@@ -484,7 +463,7 @@ PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) {
 const char SCA_JoystickSensor::SetButton_doc[] = 
 "setButton\n"
 "\tSets the button the sensor reacts to.\n";
-PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* value ) {
+PyObject* SCA_JoystickSensor::PySetButton( PyObject* value ) {
 	ShowDeprecationWarning("setButton()", "the button property");
 	int button = PyInt_AsLong(value);
 	if(button==-1 && PyErr_Occurred()) {
@@ -499,16 +478,16 @@ PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* value ) {
 const char SCA_JoystickSensor::GetButtonValue_doc[] = 
 "getButtonValue\n"
 "\tReturns a list containing the indicies of the current pressed state of each button.\n";
-PyObject* SCA_JoystickSensor::PyGetButtonValue( PyObject* self) {
+PyObject* SCA_JoystickSensor::PyGetButtonValue( ) {
 	ShowDeprecationWarning("getButtonValue()", "getButtonActiveList");
-	return PyGetButtonActiveList(self);
+	return PyGetButtonActiveList( );
 }
 
 /* get button active list  -------------------------------------------------- */
 const char SCA_JoystickSensor::GetButtonActiveList_doc[] = 
 "getButtonActiveList\n"
 "\tReturns a list containing the indicies of the button currently pressed.\n";
-PyObject* SCA_JoystickSensor::PyGetButtonActiveList( PyObject* self) {
+PyObject* SCA_JoystickSensor::PyGetButtonActiveList( ) {
 	SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
 	PyObject *ls = PyList_New(0);
 	PyObject *value;
@@ -530,12 +509,11 @@ PyObject* SCA_JoystickSensor::PyGetButtonActiveList( PyObject* self) {
 const char SCA_JoystickSensor::GetButtonStatus_doc[] = 
 "getButtonStatus(buttonIndex)\n"
 "\tReturns a bool of the current pressed state of the specified button.\n";
-PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* self, PyObject* args ) {
+PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* args ) {
 	SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
-	PyObject *value;
 	int index;
 	
-	if(!PyArg_ParseTuple(args, "i", &index)){
+	if(!PyArg_ParseTuple(args, "i:getButtonStatus", &index)){
 		return NULL;
 	}
 	if(joy && index >= 0 && index < joy->GetNumberOfButtons()) {
@@ -548,7 +526,7 @@ PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* self, PyObject* args
 const char SCA_JoystickSensor::GetHat_doc[] = 
 "getHat\n"
 "\tReturns the current direction of the hat.\n";
-PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) {
+PyObject* SCA_JoystickSensor::PyGetHat( ) {
 	ShowDeprecationWarning("getHat()", "the hat property");
 	return Py_BuildValue("[ii]",m_hat, m_hatf);
 }
@@ -558,10 +536,10 @@ PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) {
 const char SCA_JoystickSensor::SetHat_doc[] = 
 "setHat\n"
 "\tSets the hat the sensor reacts to.\n";
-PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) {
+PyObject* SCA_JoystickSensor::PySetHat( PyObject* args ) {
 	ShowDeprecationWarning("setHat()", "the hat property");
 	int hat,hatflag;
-	if(!PyArg_ParseTuple(args, "ii", &hat, &hatflag)){
+	if(!PyArg_ParseTuple(args, "ii:setHat", &hat, &hatflag)){
 		return NULL;
 	}
 	m_hat = hat;
@@ -574,7 +552,7 @@ PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) {
 const char SCA_JoystickSensor::NumberOfAxes_doc[] = 
 "getNumAxes\n"
 "\tReturns the number of axes .\n";
-PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) {
+PyObject* SCA_JoystickSensor::PyNumberOfAxes( ) {
 	ShowDeprecationWarning("getNumAxes()", "the numAxis property");
 	SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
 	// when the joystick is null their is 0 exis still. dumb but scripters should use isConnected()
@@ -585,7 +563,7 @@ PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) {
 const char SCA_JoystickSensor::NumberOfButtons_doc[] = 
 "getNumButtons\n"
 "\tReturns the number of buttons .\n";
-PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) {
+PyObject* SCA_JoystickSensor::PyNumberOfButtons( ) {
 	ShowDeprecationWarning("getNumButtons()", "the numButtons property");
 	SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
 	return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 );
@@ -595,7 +573,7 @@ PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) {
 const char SCA_JoystickSensor::NumberOfHats_doc[] = 
 "getNumHats\n"
 "\tReturns the number of hats .\n";
-PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) {
+PyObject* SCA_JoystickSensor::PyNumberOfHats( ) {
 	ShowDeprecationWarning("getNumHats()", "the numHats property");
 	SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
 	return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 );
@@ -604,8 +582,65 @@ PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) {
 const char SCA_JoystickSensor::Connected_doc[] = 
 "getConnected\n"
 "\tReturns True if a joystick is connected at this joysticks index.\n";
-PyObject* SCA_JoystickSensor::PyConnected( PyObject* self ) {
+PyObject* SCA_JoystickSensor::PyConnected( ) {
 	ShowDeprecationWarning("getConnected()", "the connected property");
 	SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
 	return PyBool_FromLong( joy ? joy->Connected() : 0 );
 }
+
+
+PyObject* SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
+	SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
+	
+	int axis_index= joy->GetNumberOfAxes();
+	PyObject *list= PyList_New(axis_index);
+	
+	while(axis_index--) {
+		PyList_SET_ITEM(list, axis_index, PyInt_FromLong(joy->GetAxisPosition(axis_index)));
+	}
+	
+	return list;
+}
+
+PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
+	SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
+	
+	if(self->m_joymode != KX_JOYSENSORMODE_AXIS_SINGLE) {
+		PyErr_SetString(PyExc_TypeError, "val = sensor.axisSingle: Joystick Sensor, not 'Single Axis' type");
+		return NULL;
+	}
+	
+	return PyInt_FromLong(joy->GetAxisPosition(self->m_axis-1));
+}
+
+PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
+	SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
+	return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 );
+}
+
+PyObject* SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
+	SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
+	return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 );
+}
+
+PyObject* SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
+	SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
+	return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 );
+}
+
+PyObject* SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
+	SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex);
+	return PyBool_FromLong( joy ? joy->Connected() : 0 );
+}
diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h
index ccdd2107b218e5028753559a4a40a2ce876b7d4f..e8185d1911e54652e23fa7ac6c8997ea04969753 100644
--- a/source/gameengine/GameLogic/SCA_JoystickSensor.h
+++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h
@@ -93,6 +93,7 @@ class SCA_JoystickSensor :public SCA_ISensor
 		KX_JOYSENSORMODE_AXIS,
 		KX_JOYSENSORMODE_BUTTON,
 		KX_JOYSENSORMODE_HAT,
+		KX_JOYSENSORMODE_AXIS_SINGLE,
 		KX_JOYSENSORMODE_MAX
 	};
 	bool isValid(KX_JOYSENSORMODE);
@@ -109,7 +110,7 @@ public:
 	virtual ~SCA_JoystickSensor();
 	virtual CValue* GetReplica();
 	
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool IsPositiveTrigger();
 	virtual void Init();
 	
@@ -122,6 +123,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	/* Joystick Index */
@@ -148,6 +150,14 @@ public:
 	KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats);
 	KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected);
 
+	static PyObject*	pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	
+
 	/* attribute check */
 	static int CheckAxis(void *self, const PyAttributeDef*)
 	{
diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp
index 6a96442b124337be7bd620678a9fd50a5e6641a4..279adab94d87901bf1f05da3dbf925fb6719d3ac 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp
@@ -62,12 +62,11 @@ void SCA_KeyboardManager::NextFrame()
 {
 	//const SCA_InputEvent& event =	GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)=0;
   //	cerr << "SCA_KeyboardManager::NextFrame"<< endl;
-	set<SCA_ISensor*>::iterator it;
-	for (it=m_sensors.begin(); it != m_sensors.end(); it++)
+	SG_DList::iterator<SCA_ISensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
 	{
-		(*it)->Activate(m_logicmanager,NULL);
+		(*it)->Activate(m_logicmanager);
 	}
-
 }
 
 bool SCA_KeyboardManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
index fc1b5be354049f9f89be7a05ac5e16e67f22c71b..f8ee8ed8b414c23382108cedde31c8967a3d8ac1 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -85,7 +85,7 @@ CValue* SCA_KeyboardSensor::GetReplica()
 {
 	SCA_KeyboardSensor* replica = new SCA_KeyboardSensor(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	replica->Init();
 	return replica;
 }
@@ -118,7 +118,7 @@ bool SCA_KeyboardSensor::TriggerOnAllKeys()
 
 
 
-bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
+bool SCA_KeyboardSensor::Evaluate()
 {
 	bool result    = false;
 	bool reset     = m_reset && m_level;
@@ -148,7 +148,7 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
 		bool justreleased = false;
 		bool active = false;
 
-		for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+		for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
 		{
 			const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
 			switch (inevent.m_status) 
@@ -195,6 +195,9 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
 					}
 				}
 			}
+			if (m_tap)
+				// special case for tap mode: only generate event for new activation
+				result = false;
 		}
 
 
@@ -352,148 +355,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
 	}
 	
 }
-
-/**
- * Determine whether this character can be printed. We cannot use
- * the library functions here, because we need to test our own
- * keycodes. */
-bool SCA_KeyboardSensor::IsPrintable(int keyIndex)
-{
-	/* only print 
-	 * - numerals: KX_ZEROKEY to KX_NINEKEY
-	 * - alphas:   KX_AKEY to KX_ZKEY. 
-	 * - specials: KX_RETKEY, KX_PADASTERKEY, KX_PADCOMMAKEY to KX_PERIODKEY,
-	 *             KX_TABKEY , KX_SEMICOLONKEY to KX_RIGHTBRACKETKEY, 
-	 *             KX_PAD2 to KX_PADPLUSKEY
-	 * - delete and backspace: also printable in the sense that they modify 
-	 *                         the string
-	 * - retkey: should this be printable?
-	 * - virgule: prints a space... don't know which key that's supposed
-	 *   to be...
-	 */
-	if ( ((keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
-		  && (keyIndex <= SCA_IInputDevice::KX_NINEKEY))
-		 || ((keyIndex >= SCA_IInputDevice::KX_AKEY) 
-			 && (keyIndex <= SCA_IInputDevice::KX_ZKEY)) 
-		 || (keyIndex == SCA_IInputDevice::KX_SPACEKEY) 
-/*  			 || (keyIndex == KX_RETKEY)  */
-		 || (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) 
-		 || (keyIndex == SCA_IInputDevice::KX_TABKEY) 
-		 || ((keyIndex >= SCA_IInputDevice::KX_COMMAKEY) 
-			 && (keyIndex <= SCA_IInputDevice::KX_PERIODKEY)) 
-		 || ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
-			 && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) 
-		 || ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
-			 && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) 
-		 || (keyIndex == SCA_IInputDevice::KX_DELKEY)
-		 || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY)		 		 
-		)
-	{
-		return true;
-	} else {
-		return false;
-	}
-}
-
-// this code looks ugly, please use an ordinary hashtable
-
-char SCA_KeyboardSensor::ToCharacter(int keyIndex, bool shifted)
-{
-	/* numerals */
-	if ( (keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
-		 && (keyIndex <= SCA_IInputDevice::KX_NINEKEY) ) {
-		if (shifted) {
-			char numshift[] = ")!@#$%^&*(";
-			return numshift[keyIndex - '0']; 
-		} else {
-			return keyIndex - SCA_IInputDevice::KX_ZEROKEY + '0'; 
-		}
-	}
-	
-	/* letters... always lowercase... is that desirable? */
-	if ( (keyIndex >= SCA_IInputDevice::KX_AKEY) 
-		 && (keyIndex <= SCA_IInputDevice::KX_ZKEY) ) {
-		if (shifted) {
-			return keyIndex - SCA_IInputDevice::KX_AKEY + 'A'; 
-		} else {
-			return keyIndex - SCA_IInputDevice::KX_AKEY + 'a'; 
-		}
-	}
-	
-	if (keyIndex == SCA_IInputDevice::KX_SPACEKEY) {
-		return ' ';
-	}
-	
-/*  			 || (keyIndex == SCA_IInputDevice::KX_RETKEY)  */
-	
-	if (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) {
-		return '*';
-	}
-	
-	if (keyIndex == SCA_IInputDevice::KX_TABKEY) {
-		return '\t';
-	}
-	
-	/* comma to period */
-	char commatoperiod[] = ",-.";
-	char commatoperiodshifted[] = "<_>";
-	if (keyIndex == SCA_IInputDevice::KX_COMMAKEY) {
-		if (shifted) {
-			return commatoperiodshifted[0];
-		} else {
-			return commatoperiod[0];
-		}
-	}
-	if (keyIndex == SCA_IInputDevice::KX_MINUSKEY) {
-		if (shifted) {
-			return commatoperiodshifted[1];
-		} else {
-			return commatoperiod[1];
-		}
-	}
-	if (keyIndex == SCA_IInputDevice::KX_PERIODKEY) {
-		if (shifted) {
-			return commatoperiodshifted[2];
-		} else {
-			return commatoperiod[2];
-		}
-	}
-	
-	/* semicolon to rightbracket */
-	char semicolontorightbracket[] = ";\'` /\\=[]";
-	char semicolontorightbracketshifted[] = ":\"~ \?|+{}";
-	if ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
-		&& (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) {
-		if (shifted) {
-			return semicolontorightbracketshifted[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
-		} else {
-			return semicolontorightbracket[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
-		}
-	}
-	
-	/* keypad2 to padplus */
-	char pad2topadplus[] = "246813579. 0- +";
-	if ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
-		&& (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) { 
-		return pad2topadplus[keyIndex - SCA_IInputDevice::KX_PAD2];
-	}
-
-	return '!';
-}
 	
-/**
- * Tests whether this is a delete key.
- */	
-bool SCA_KeyboardSensor::IsDelete(int keyIndex)
-{
-	if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
-		 || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY) ) {
-		return true;
-	} else {
-		return false;
-	}
-}
-
 /**
  * Tests whether shift is pressed
  */	
@@ -528,7 +390,7 @@ void SCA_KeyboardSensor::LogKeystrokes(void)
 		int index = 0;
 		/* Check on all keys whether they were pushed. This does not
          * untangle the ordering, so don't type too fast :) */
-		for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+		for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
 		{
 			const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
 			if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED) //NO_INPUTSTATUS)
@@ -553,7 +415,7 @@ void SCA_KeyboardSensor::LogKeystrokes(void)
 const char SCA_KeyboardSensor::GetKey_doc[] = 
 "getKey()\n"
 "\tReturn the code of the key this sensor is listening to.\n" ;
-PyObject* SCA_KeyboardSensor::PyGetKey(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetKey()
 {
 	ShowDeprecationWarning("getKey()", "the key property");
 	return PyInt_FromLong(m_hotkey);
@@ -564,12 +426,12 @@ const char SCA_KeyboardSensor::SetKey_doc[] =
 "setKey(keycode)\n"
 "\t- keycode: any code from GameKeys\n"
 "\tSet the key this sensor should listen to.\n" ;
-PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PySetKey(PyObject* args)
 {
 	ShowDeprecationWarning("setKey()", "the key property");
 	int keyCode;
 	
-	if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+	if(!PyArg_ParseTuple(args, "i:setKey", &keyCode)) {
 		return NULL;
 	}
 
@@ -585,7 +447,7 @@ const char SCA_KeyboardSensor::GetHold1_doc[] =
 "getHold1()\n"
 "\tReturn the code of the first key modifier to the key this \n"
 "\tsensor is listening to.\n" ;
-PyObject* SCA_KeyboardSensor::PyGetHold1(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetHold1()
 {
 	ShowDeprecationWarning("getHold1()", "the hold1 property");
 	return PyInt_FromLong(m_qual);
@@ -596,12 +458,12 @@ const char SCA_KeyboardSensor::SetHold1_doc[] =
 "setHold1(keycode)\n"
 "\t- keycode: any code from GameKeys\n"
 "\tSet the first modifier to the key this sensor should listen to.\n" ;
-PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* args)
 {
 	ShowDeprecationWarning("setHold1()", "the hold1 property");
 	int keyCode;
 
-	if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+	if(!PyArg_ParseTuple(args, "i:setHold1", &keyCode)) {
 		return NULL;
 	}
 	
@@ -617,7 +479,7 @@ const char SCA_KeyboardSensor::GetHold2_doc[] =
 "getHold2()\n"
 "\tReturn the code of the second key modifier to the key this \n"
 "\tsensor is listening to.\n" ;
-PyObject* SCA_KeyboardSensor::PyGetHold2(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetHold2()
 {
 	ShowDeprecationWarning("getHold2()", "the hold2 property");
 	return PyInt_FromLong(m_qual2);
@@ -628,12 +490,12 @@ const char SCA_KeyboardSensor::SetHold2_doc[] =
 "setHold2(keycode)\n"
 "\t- keycode: any code from GameKeys\n"
 "\tSet the first modifier to the key this sensor should listen to.\n" ;
-PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* args)
 {
 	ShowDeprecationWarning("setHold2()", "the hold2 property");
 	int keyCode;
 
-	if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+	if(!PyArg_ParseTuple(args, "i:setHold2", &keyCode)) {
 		return NULL;
 	}
 	
@@ -649,9 +511,9 @@ const char SCA_KeyboardSensor::GetPressedKeys_doc[] =
 "getPressedKeys()\n"
 "\tGet a list of pressed keys that have either been pressed, or just released this frame.\n" ;
 
-PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetPressedKeys()
 {
-	ShowDeprecationWarning("getPressedKeys()", "getEventList()");
+	ShowDeprecationWarning("getPressedKeys()", "events");
 
 	SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
 
@@ -663,26 +525,25 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, P
 		
 		int index = 0;
 		
-		for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+		for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
 		{
 			const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
 			if ((inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
 				|| (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED))
 			{
-				if (index < num)
-				{
-					PyObject* keypair = PyList_New(2);
-					PyList_SetItem(keypair,0,PyInt_FromLong(i));
-					PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
-					PyList_SetItem(resultlist,index,keypair);
-					index++;
-				}
+				PyObject* keypair = PyList_New(2);
+				PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+				PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
+				PyList_SET_ITEM(resultlist,index,keypair);
+				index++;
+				
+				if (index >= num) /* should not happen */
+					break; 
 			}
-		}	
-		if (index>0) return resultlist;
+		}
 	}
 	
-	Py_RETURN_NONE;
+	return resultlist;
 }
 
 
@@ -691,11 +552,11 @@ const char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] =
 "getCurrentlyPressedKeys()\n"
 "\tGet a list of keys that are currently pressed.\n" ;
 
-PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys()
 {
-ShowDeprecationWarning("getCurrentlyPressedKeys()", "getEventList()");
+	ShowDeprecationWarning("getCurrentlyPressedKeys()", "events");
 
-SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+	SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
 
 	int num = inputdev->GetNumActiveEvents();
 	PyObject* resultlist = PyList_New(num);
@@ -704,73 +565,49 @@ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
 	{
 		int index = 0;
 		
-		for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+		for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
 		{
 			const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
 			if ( (inevent.m_status == SCA_InputEvent::KX_ACTIVE)
 				 || (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED))
 			{
-				if (index < num)
-				{
-					PyObject* keypair = PyList_New(2);
-					PyList_SetItem(keypair,0,PyInt_FromLong(i));
-					PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
-					PyList_SetItem(resultlist,index,keypair);
-					index++;
-				}
+				PyObject* keypair = PyList_New(2);
+				PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+				PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
+				PyList_SET_ITEM(resultlist,index,keypair);
+				index++;
+				
+				if (index >= num) /* should never happen */
+					break;
 			}
 		}
-
-		/* why?*/
-		if (index > 0) return resultlist;
 	}
 
-	Py_RETURN_NONE;
-}
-//<---- Deprecated
-
-KX_PYMETHODDEF_DOC_NOARGS(SCA_KeyboardSensor, getEventList,
-"getEventList()\n"
-"\tGet the list of the keyboard events in this frame.\n")
-{
-	SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
-
-	PyObject* resultlist = PyList_New(0);
-	
-	for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
-	{
-		const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
-		if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
-		{
-			PyObject* keypair = PyList_New(2);
-			PyList_SetItem(keypair,0,PyInt_FromLong(i));
-			PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
-			PyList_Append(resultlist,keypair);
-		}
-	}	
 	return resultlist;
 }
 
+//<---- Deprecated
+
 KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus,
 "getKeyStatus(keycode)\n"
 "\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n")
 {
-	if (PyInt_Check(value))
-	{
-		int keycode = PyInt_AsLong(value);
-		
-		if ((keycode < SCA_IInputDevice::KX_BEGINKEY)
-			|| (keycode > SCA_IInputDevice::KX_ENDKEY)){
-			PyErr_SetString(PyExc_AttributeError, "invalid keycode specified!");
-			return NULL;
-		}
-		
-		SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
-		const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode);
-		return PyInt_FromLong(inevent.m_status);
+	if (!PyInt_Check(value)) {
+		PyErr_SetString(PyExc_ValueError, "sensor.getKeyStatus(int): Keyboard Sensor, expected an int");
+		return NULL;
 	}
 	
-	Py_RETURN_NONE;
+	int keycode = PyInt_AsLong(value);
+	
+	if ((keycode < SCA_IInputDevice::KX_BEGINKEY)
+		|| (keycode > SCA_IInputDevice::KX_ENDKEY)){
+		PyErr_SetString(PyExc_AttributeError, "sensor.getKeyStatus(int): Keyboard Sensor, invalid keycode specified!");
+		return NULL;
+	}
+	
+	SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+	const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode);
+	return PyInt_FromLong(inevent.m_status);
 }
 
 /* ------------------------------------------------------------------------- */
@@ -778,12 +615,17 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus,
 /* ------------------------------------------------------------------------- */
 
 PyTypeObject SCA_KeyboardSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_KeyboardSensor",
-	sizeof(SCA_KeyboardSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -806,21 +648,21 @@ PyParentObject SCA_KeyboardSensor::Parents[] = {
 
 PyMethodDef SCA_KeyboardSensor::Methods[] = {
 	//Deprecated functions ------>
-	{"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, (PY_METHODCHAR)GetKey_doc},
+	{"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_NOARGS, (PY_METHODCHAR)GetKey_doc},
 	{"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, (PY_METHODCHAR)SetKey_doc},
-	{"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, (PY_METHODCHAR)GetHold1_doc},
+	{"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_NOARGS, (PY_METHODCHAR)GetHold1_doc},
 	{"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, (PY_METHODCHAR)SetHold1_doc},
-	{"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, (PY_METHODCHAR)GetHold2_doc},
+	{"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_NOARGS, (PY_METHODCHAR)GetHold2_doc},
 	{"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, (PY_METHODCHAR)SetHold2_doc},
-	{"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetPressedKeys_doc},
-	{"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetCurrentlyPressedKeys_doc},
+	{"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_NOARGS, (PY_METHODCHAR)GetPressedKeys_doc},
+	{"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_NOARGS, (PY_METHODCHAR)GetCurrentlyPressedKeys_doc},
 	//<----- Deprecated
-	KX_PYMETHODTABLE_NOARGS(SCA_KeyboardSensor, getEventList),
 	KX_PYMETHODTABLE_O(SCA_KeyboardSensor, getKeyStatus),
 	{NULL,NULL} //Sentinel
 };
 
 PyAttributeDef SCA_KeyboardSensor::Attributes[] = {
+	KX_PYATTRIBUTE_RO_FUNCTION("events", SCA_KeyboardSensor, pyattr_get_events),
 	KX_PYATTRIBUTE_BOOL_RW("useAllKeys",SCA_KeyboardSensor,m_bAllKeys),
 	KX_PYATTRIBUTE_INT_RW("key",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_hotkey),
 	KX_PYATTRIBUTE_SHORT_RW("hold1",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual),
@@ -830,19 +672,188 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = {
 	{ NULL }	//Sentinel
 };
 
-PyObject*
-SCA_KeyboardSensor::py_getattro(PyObject *attr)
+PyObject* SCA_KeyboardSensor::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
   py_getattro_up(SCA_ISensor);
 }
 
+PyObject* SCA_KeyboardSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 int SCA_KeyboardSensor::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_ISensor::py_setattro(attr, value);
+	py_setattro_up(SCA_ISensor);
+}
+
+
+PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_KeyboardSensor* self= static_cast<SCA_KeyboardSensor*>(self_v);
+	
+	SCA_IInputDevice* inputdev = self->m_pKeyboardMgr->GetInputDevice();
+
+	PyObject* resultlist = PyList_New(0);
+	
+	for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
+	{
+		const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
+		if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
+		{
+			PyObject* keypair = PyList_New(2);
+			PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+			PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
+			PyList_Append(resultlist,keypair);
+		}
+	}	
+	return resultlist;
+}
+
+
+/* Accessed from python */
+
+// this code looks ugly, please use an ordinary hashtable
+
+char ToCharacter(int keyIndex, bool shifted)
+{
+	/* numerals */
+	if ( (keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
+		 && (keyIndex <= SCA_IInputDevice::KX_NINEKEY) ) {
+		if (shifted) {
+			char numshift[] = ")!@#$%^&*(";
+			return numshift[keyIndex - '0']; 
+		} else {
+			return keyIndex - SCA_IInputDevice::KX_ZEROKEY + '0'; 
+		}
+	}
+	
+	/* letters... always lowercase... is that desirable? */
+	if ( (keyIndex >= SCA_IInputDevice::KX_AKEY) 
+		 && (keyIndex <= SCA_IInputDevice::KX_ZKEY) ) {
+		if (shifted) {
+			return keyIndex - SCA_IInputDevice::KX_AKEY + 'A'; 
+		} else {
+			return keyIndex - SCA_IInputDevice::KX_AKEY + 'a'; 
+		}
+	}
+	
+	if (keyIndex == SCA_IInputDevice::KX_SPACEKEY) {
+		return ' ';
+	}
+	if (keyIndex == SCA_IInputDevice::KX_RETKEY || keyIndex == SCA_IInputDevice::KX_PADENTER) {
+		return '\n';
+	}
+	
+	
+	if (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) {
+		return '*';
+	}
+	
+	if (keyIndex == SCA_IInputDevice::KX_TABKEY) {
+		return '\t';
+	}
+	
+	/* comma to period */
+	char commatoperiod[] = ",-.";
+	char commatoperiodshifted[] = "<_>";
+	if (keyIndex == SCA_IInputDevice::KX_COMMAKEY) {
+		if (shifted) {
+			return commatoperiodshifted[0];
+		} else {
+			return commatoperiod[0];
+		}
+	}
+	if (keyIndex == SCA_IInputDevice::KX_MINUSKEY) {
+		if (shifted) {
+			return commatoperiodshifted[1];
+		} else {
+			return commatoperiod[1];
+		}
+	}
+	if (keyIndex == SCA_IInputDevice::KX_PERIODKEY) {
+		if (shifted) {
+			return commatoperiodshifted[2];
+		} else {
+			return commatoperiod[2];
+		}
+	}
+	
+	/* semicolon to rightbracket */
+	char semicolontorightbracket[] = ";\'`/\\=[]";
+	char semicolontorightbracketshifted[] = ":\"~\?|+{}";
+	if ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
+		&& (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) {
+		if (shifted) {
+			return semicolontorightbracketshifted[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
+		} else {
+			return semicolontorightbracket[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
+		}
+	}
+	
+	/* keypad2 to padplus */
+	char pad2topadplus[] = "246813579. 0- +";
+	if ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
+		&& (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) { 
+		return pad2topadplus[keyIndex - SCA_IInputDevice::KX_PAD2];
+	}
+
+	return '!';
+}
+
+
+
+/**
+ * Determine whether this character can be printed. We cannot use
+ * the library functions here, because we need to test our own
+ * keycodes. */
+bool IsPrintable(int keyIndex)
+{
+	/* only print 
+	 * - numerals: KX_ZEROKEY to KX_NINEKEY
+	 * - alphas:   KX_AKEY to KX_ZKEY. 
+	 * - specials: KX_RETKEY, KX_PADASTERKEY, KX_PADCOMMAKEY to KX_PERIODKEY,
+	 *             KX_TABKEY , KX_SEMICOLONKEY to KX_RIGHTBRACKETKEY, 
+	 *             KX_PAD2 to KX_PADPLUSKEY
+	 * - delete and backspace: also printable in the sense that they modify 
+	 *                         the string
+	 * - retkey: should this be printable?
+	 * - virgule: prints a space... don't know which key that's supposed
+	 *   to be...
+	 */
+	if ( ((keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
+		  && (keyIndex <= SCA_IInputDevice::KX_NINEKEY))
+		 || ((keyIndex >= SCA_IInputDevice::KX_AKEY) 
+			 && (keyIndex <= SCA_IInputDevice::KX_ZKEY)) 
+		 || (keyIndex == SCA_IInputDevice::KX_SPACEKEY) 
+		 || (keyIndex == SCA_IInputDevice::KX_RETKEY)
+		 || (keyIndex == SCA_IInputDevice::KX_PADENTER)
+		 || (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) 
+		 || (keyIndex == SCA_IInputDevice::KX_TABKEY) 
+		 || ((keyIndex >= SCA_IInputDevice::KX_COMMAKEY) 
+			 && (keyIndex <= SCA_IInputDevice::KX_PERIODKEY)) 
+		 || ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
+			 && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) 
+		 || ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
+			 && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) 
+		 || (keyIndex == SCA_IInputDevice::KX_DELKEY)
+		 || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY)
+		)
+	{
+		return true;
+	} else {
+		return false;
+	}
+}
+
+/**
+ * Tests whether this is a delete key.
+ */	
+bool IsDelete(int keyIndex)
+{
+	if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
+		 || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY) ) {
+		return true;
+	} else {
+		return false;
+	}
 }
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
index c579b6a82f814d7a8ebacb037f183df3b046468f..033225cd9bea7eb26e16251db3fc0ee51f85b279 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h
@@ -81,22 +81,6 @@ class SCA_KeyboardSensor : public SCA_ISensor
 	 */
 	void AddToTargetProp(int keyIndex);
 
-	/**
-	 * Determine whether this character can be printed. We cannot use
-	 * the library functions here, because we need to test our own
-	 * keycodes. */
-	bool IsPrintable(int keyIndex);
-
-	/**
-	 * Transform keycodes to something printable.
-	 */
-	char ToCharacter(int keyIndex, bool shifted);
-
-	/**
-	 * Tests whether this is a delete key.
-	 */	
-	bool IsDelete(int keyIndex);
-
 	/**
 	 * Tests whether shift is pressed.
 	 */
@@ -118,7 +102,7 @@ public:
 
 
 	short int GetHotkey();
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool IsPositiveTrigger();
 	bool	TriggerOnAllKeys();
 
@@ -127,32 +111,55 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	//Deprecated functions ----->
 	/** 1. GetKey : check which key this sensor looks at */
-	KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetKey);
+	KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,GetKey);
 	/** 2. SetKey: change the key to look at */
-	KX_PYMETHOD_DOC(SCA_KeyboardSensor,SetKey);
+	KX_PYMETHOD_DOC_VARARGS(SCA_KeyboardSensor,SetKey);
 	/** 3. GetHold1 : set the first bucky bit */
-	KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetHold1);
+	KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,GetHold1);
 	/** 4. SetHold1: change the first bucky bit */
-	KX_PYMETHOD_DOC(SCA_KeyboardSensor,SetHold1);
+	KX_PYMETHOD_DOC_VARARGS(SCA_KeyboardSensor,SetHold1);
 	/** 5. GetHold2 : set the second bucky bit */
-	KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetHold2);
+	KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,GetHold2);
 	/** 6. SetHold2: change the second bucky bit */
-	KX_PYMETHOD_DOC(SCA_KeyboardSensor,SetHold2);
+	KX_PYMETHOD_DOC_VARARGS(SCA_KeyboardSensor,SetHold2);
 	/** 9. GetPressedKeys: */
-	KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetPressedKeys); 
+	KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,GetPressedKeys); 
 	/** 9. GetCurrrentlyPressedKeys: */
-	KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetCurrentlyPressedKeys); 
+	KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,GetCurrentlyPressedKeys); 
 	// <------
 	
 	// KeyEvents: 
 	KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,getEventList); 
 	// KeyStatus: 
 	KX_PYMETHOD_DOC_O(SCA_KeyboardSensor,getKeyStatus);
+	
+	static PyObject*	pyattr_get_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 };
 
+
+/**
+ * Transform keycodes to something printable.
+ */
+char ToCharacter(int keyIndex, bool shifted);
+
+/**
+ * Determine whether this character can be printed. We cannot use
+ * the library functions here, because we need to test our own
+ * keycodes. */
+bool IsPrintable(int keyIndex);
+
+/**
+ * Tests whether this is a delete key.
+ */	
+bool IsDelete(int keyIndex);
+
+
 #endif //__KX_KEYBOARDSENSOR
 
+
+
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp
index b584b37180ff53f9f6dbb25c2756cfbb43e7aed8..74370f89cf277608d7794d86825651cf3d1bedb2 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.cpp
+++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp
@@ -49,37 +49,14 @@ SCA_LogicManager::SCA_LogicManager()
 
 SCA_LogicManager::~SCA_LogicManager()
 {
-	/* AddRef() is not used when the objects are added to m_mapStringToGameObjects
-	   so Release() should not be used either. The memory leak big is fixed
-	   in BL_ConvertBlenderObjects()
-
-	int numgameobj = m_mapStringToGameObjects.size();
-	for (int i = 0; i < numgameobj; i++)
-	{
-		CValue** gameobjptr = m_mapStringToGameObjects.at(i);
-		assert(gameobjptr);
-		if (gameobjptr)
-			(*gameobjptr)->Release();
-    
-	}
-	*/
-	/*for (int i=0;i<m_sensorcontrollermap.size();i++)
-	{
-		vector<SCA_IController*>* controllerarray = *(m_sensorcontrollermap[i]);
-		delete controllerarray;
-	}
-	*/
-	for (vector<SCA_EventManager*>::iterator it = m_eventmanagers.begin();!(it==m_eventmanagers.end());it++)
+	for (vector<SCA_EventManager*>::iterator it = m_eventmanagers.begin();!(it==m_eventmanagers.end());++it)
 	{
 		delete (*it);
 	}
 	m_eventmanagers.clear();
-	m_sensorcontrollermapje.clear();
-	m_removedActuators.clear();
-	m_activeActuators.clear();
+	assert(m_activeActuators.Empty());
 }
 
-
 /*
 // this kind of fixes bug 398 but breakes games, so better leave it out for now.
 // a removed object's gameobject (and logicbricks and stuff) didn't get released
@@ -171,12 +148,7 @@ void* SCA_LogicManager::FindBlendObjByGameMeshName(const STR_String& gamemeshnam
 
 void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor)
 {
-	controllerlist contlist = m_sensorcontrollermapje[sensor];
-	for (controllerlist::const_iterator c= contlist.begin();!(c==contlist.end());c++)
-	{
-		(*c)->UnlinkSensor(sensor);
-	}
-    m_sensorcontrollermapje.erase(sensor);
+	sensor->UnlinkAllControllers();
 	sensor->UnregisterToManager();
 }
 
@@ -184,35 +156,22 @@ void SCA_LogicManager::RemoveController(SCA_IController* controller)
 {
 	controller->UnlinkAllSensors();
 	controller->UnlinkAllActuators();
-	std::map<SCA_ISensor*,controllerlist>::iterator sit;
-	for (sit = m_sensorcontrollermapje.begin();!(sit==m_sensorcontrollermapje.end());++sit)
-	{
-		(*sit).second.remove(controller);
-	}
+	controller->Deactivate();
 }
 
 
-void SCA_LogicManager::RemoveDestroyedActuator(SCA_IActuator* actuator)
+void SCA_LogicManager::RemoveActuator(SCA_IActuator* actuator)
 {
-	m_removedActuators.push_back(SmartActuatorPtr(actuator,0));
-	// take care that no controller can use this actuator again !
-
-	std::map<SCA_ISensor*,controllerlist>::const_iterator sit;
-	for (sit = m_sensorcontrollermapje.begin();!(sit==m_sensorcontrollermapje.end());++sit)
-	{
-		controllerlist contlist = (*sit).second;
-		for (list<SCA_IController*>::const_iterator c= contlist.begin();!(c==contlist.end());c++)
-		{
-			(*c)->UnlinkActuator(actuator);
-		}
-	}
+	actuator->UnlinkAllControllers();
+	actuator->Deactivate();
+	actuator->SetActive(false);
 }
 
 
 
 void SCA_LogicManager::RegisterToSensor(SCA_IController* controller,SCA_ISensor* sensor)
 {
-    m_sensorcontrollermapje[sensor].push_back(controller);
+	sensor->LinkToController(controller);
 	controller->LinkToSensor(sensor);
 }
 
@@ -220,6 +179,7 @@ void SCA_LogicManager::RegisterToSensor(SCA_IController* controller,SCA_ISensor*
 
 void SCA_LogicManager::RegisterToActuator(SCA_IController* controller,SCA_IActuator* actua)
 {
+	actua->LinkToController(controller);
 	controller->LinkToActuator(actua);
 }
 
@@ -230,88 +190,60 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime)
 	for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); !(ie==m_eventmanagers.end()); ie++)
 		(*ie)->NextFrame(curtime, fixedtime);
 
-	// for this frame, look up for activated sensors, and build the collection of triggered controllers
-	// int numsensors = this->m_activatedsensors.size(); /*unused*/
-
-	for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin();
-	!(is==m_activatedsensors.end());is++)
+	for(SG_QList* obj = (SG_QList*)m_triggeredControllerSet.Remove();
+		obj != NULL;
+		obj = (SG_QList*)m_triggeredControllerSet.Remove())
 	{
-		SCA_ISensor* sensor = *is;
-                controllerlist contlist = m_sensorcontrollermapje[sensor];
-        	for (list<SCA_IController*>::const_iterator c= contlist.begin();
-			!(c==contlist.end());c++)
+		for(SCA_IController* contr = (SCA_IController*)obj->QRemove();
+			contr != NULL;
+			contr = (SCA_IController*)obj->QRemove())
 		{
-				SCA_IController* contr = *c;//controllerarray->at(c);
-				if (contr->IsActive())
-				{
-					m_triggeredControllerSet.insert(SmartControllerPtr(contr,0));
-					// So that the controller knows which sensor has activited it.
-					// Only needed for the python controller though.
-					if (contr->GetType() == &SCA_PythonController::Type)
-					{
-						SCA_PythonController* pythonController = (SCA_PythonController*)contr;
-						pythonController->AddTriggeredSensor(sensor);
-					}
-				}
+			contr->Trigger(this);
+			contr->ClrJustActivated();
 		}
-		//sensor->SetActive(false);
 	}
-
-	
-	// int numtriggered = triggeredControllerSet.size(); /*unused*/
-	for (set<SmartControllerPtr>::iterator tit=m_triggeredControllerSet.begin();
-	!(tit==m_triggeredControllerSet.end());tit++)
-	{
-		(*tit)->Trigger(this);
-	}
-	m_triggeredControllerSet.clear();
 }
 
 
 
 void SCA_LogicManager::UpdateFrame(double curtime, bool frame)
 {
-	vector<SmartActuatorPtr>::iterator ra;
-	for (ra = m_removedActuators.begin(); !(ra == m_removedActuators.end()); ra++)
-	{
-		m_activeActuators.erase(*ra);
-		(*ra)->SetActive(false);
-	}
-	m_removedActuators.clear();
-	
-	// About to run actuators, but before update the sensors for those which depends on actuators
 	for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); !(ie==m_eventmanagers.end()); ie++)
 		(*ie)->UpdateFrame();
 
-	for (set<SmartActuatorPtr>::iterator ia = m_activeActuators.begin();!(ia==m_activeActuators.end());ia++)
+	SG_DList::iterator<SG_QList> io(m_activeActuators);
+	for (io.begin(); !io.end(); ++io)
 	{
-		//SCA_IActuator* actua = *ia;
-		if (!(*ia)->Update(curtime, frame))
-		{
-			//*ia = m_activeactuators.back();
-			m_removedActuators.push_back(*ia);
-			
-			(*ia)->SetActive(false);
-			//m_activeactuators.pop_back();
-		} else if ((*ia)->IsNoLink())
+		SG_QList::iterator<SCA_IActuator> ia(*(*io));
+		for (ia.begin(); !ia.end(); ++ia)
 		{
-			// This actuator has no more links but it still active
-			// make sure it will get a negative event on next frame to stop it
-			// Do this check after Update() rather than before to make sure
-			// that all the actuators that are activated at same time than a state
-			// actuator have a chance to execute. 
-			CValue* event = new CBoolValue(false);
-			(*ia)->RemoveAllEvents();
-			(*ia)->AddEvent(event);
+			SCA_IActuator* actua = *ia;
+			if (!actua->Update(curtime, frame))
+			{
+				// cannot deactive the actuator now as it will disturb the list
+				m_removedActuators.AddBack(actua);
+				actua->SetActive(false);
+			} else if (actua->IsNoLink())
+			{
+				// This actuator has no more links but it still active
+				// make sure it will get a negative event on next frame to stop it
+				// Do this check after Update() rather than before to make sure
+				// that all the actuators that are activated at same time than a state
+				// actuator have a chance to execute. 
+				bool event = false;
+				actua->RemoveAllEvents();
+				actua->AddEvent(event);
+			}
 		}
 	}
-	
-	for ( ra = m_removedActuators.begin(); !(ra == m_removedActuators.end()); ra++)
+
+	for (SCA_IActuator* act = (SCA_IActuator*)m_removedActuators.Remove();
+		act != NULL;
+		act = (SCA_IActuator*)m_removedActuators.Remove())
 	{
-		m_activeActuators.erase(*ra);
-		(*ra)->SetActive(false);
+		act->Deactivate();
+		act->SetActive(false);
 	}
-	m_removedActuators.clear();
 }
 
 
@@ -360,39 +292,17 @@ void SCA_LogicManager::RegisterActionName(const STR_String& actname,void* action
 
 void SCA_LogicManager::EndFrame()
 {
-	for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin();
-	!(is==m_activatedsensors.end());is++)
-	{
-		SCA_ISensor* sensor = *is;
-		sensor->SetActive(false);
-	}
-	m_activatedsensors.clear();
-
 	for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin();
 	!(ie==m_eventmanagers.end());ie++)
 	{
 		(*ie)->EndFrame();
 	}
-
-
 }
 
 
-
-void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor)
-{
-	// each frame, only add sensor once, and to avoid a seek, or bloated container
-	// hold a flag in each sensor, with the 'framenr'
-	if (!sensor->IsActive())
-	{
-		sensor->SetActive(true);
-		m_activatedsensors.push_back(sensor);
-	}
-}
-
 void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor)
 {
-	m_triggeredControllerSet.insert(SmartControllerPtr(controller,0));
+	controller->Activate(m_triggeredControllerSet);
 	// so that the controller knows which sensor has activited it
 	// only needed for python controller
 	if (controller->GetType() == &SCA_PythonController::Type)
@@ -403,14 +313,11 @@ void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_I
 }
 
 
-void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event)
+void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,bool event)
 {
-	if (!actua->IsActive())
-	{
-		actua->SetActive(true);
-		m_activeActuators.insert(SmartActuatorPtr(actua,0));
-	}
-	actua->AddEvent(event->AddRef());
+	actua->SetActive(true);
+	actua->Activate(m_activeActuators);
+	actua->AddEvent(event);
 }
 
 
@@ -432,109 +339,3 @@ SCA_EventManager* SCA_LogicManager::FindEventManager(int eventmgrtype)
 	}
 	return eventmgr;
 }
-
-
-
-SmartActuatorPtr::SmartActuatorPtr(const SmartActuatorPtr& other)
-{
-	this->m_actuator = other.m_actuator;
-	this->m_actuator->AddRef();
-}
-
-
-
-SmartActuatorPtr::SmartActuatorPtr(SCA_IActuator* actua,int dummy)
-: m_actuator(actua)
-{
-	actua->AddRef();
-}
-
-
-
-SmartActuatorPtr::~SmartActuatorPtr()
-{
-	m_actuator->Release();
-}
-
-
-
-bool SmartActuatorPtr::operator <(const SmartActuatorPtr& other) const
-{
-	
-	return m_actuator->LessComparedTo(*other);
-}
-
-
-
-bool SmartActuatorPtr::operator ==(const SmartActuatorPtr& other) const
-{
-	bool result2 = other->LessComparedTo(m_actuator);
-	return (m_actuator->LessComparedTo(*other) && result2);
-}
-
-
-
-SCA_IActuator*	SmartActuatorPtr::operator->() const
-{
-	return m_actuator;
-}
-
-
-
-SCA_IActuator*	 SmartActuatorPtr::operator*() const
-{
-	return m_actuator;
-}
-
-
-
-SmartControllerPtr::SmartControllerPtr(const SmartControllerPtr& copy)
-{
-	this->m_controller = copy.m_controller;
-	this->m_controller->AddRef();
-}
-
-
-
-SmartControllerPtr::SmartControllerPtr(SCA_IController* contr,int dummy)
-: m_controller(contr)
-{
-	m_controller->AddRef();
-}
-
-
-
-SmartControllerPtr::~SmartControllerPtr()
-{
-	m_controller->Release();
-}
-
-
-
-bool	SmartControllerPtr::operator <(const SmartControllerPtr& other) const
-{
-	return m_controller->LessComparedTo(*other);
-}
-
-
-
-bool	SmartControllerPtr::operator ==(const SmartControllerPtr& other) const
-{
-	return (m_controller->LessComparedTo(*other) && other->LessComparedTo(m_controller));
-}
-
-
-
-SCA_IController*	SmartControllerPtr::operator->() const
-{
-	return m_controller;
-}
-
-
-
-SCA_IController* 	SmartControllerPtr::operator*() const
-{
-	return m_controller;
-}
-
-
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h
index 50383879d8f0f4ed8f79009f20b239f9b339a0e6..0d610c9cc464ece189cd0c94544f9ed399a79fc4 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.h
+++ b/source/gameengine/GameLogic/SCA_LogicManager.h
@@ -43,11 +43,13 @@
 #include "GEN_Map.h"
 #include "STR_HashedString.h"
 #include "Value.h"
+#include "SG_QList.h"
 
 #include "KX_HashedPtr.h"
 
 using namespace std;
-typedef list<class SCA_IController*> controllerlist;
+typedef std::list<class SCA_IController*> controllerlist;
+typedef std::map<class SCA_ISensor*,controllerlist > sensormap_t;
 
 /** 
  * This manager handles sensor, controllers and actuators.
@@ -64,44 +66,17 @@ typedef list<class SCA_IController*> controllerlist;
 
 #include "SCA_ILogicBrick.h"
 
-// todo: make this into a template, but first I want to think about what exactly to put in
-class	SmartActuatorPtr
-{
-	SCA_IActuator*	m_actuator;
-public:
-	SmartActuatorPtr(SCA_IActuator* actua,int dummy);
-	SmartActuatorPtr(const SmartActuatorPtr& other);
-	virtual ~SmartActuatorPtr();
-	bool operator <(const SmartActuatorPtr& other) const;
-	bool operator ==(const SmartActuatorPtr& other) const;
-	SCA_IActuator*	operator->() const;
-	SCA_IActuator* operator*() const;
-
-};
-
-class	SmartControllerPtr
-{
-	SCA_IController*	m_controller;
-public:
-	SmartControllerPtr(const SmartControllerPtr& copy);
-	SmartControllerPtr(SCA_IController* contr,int dummy);
-	virtual ~SmartControllerPtr();
-	bool	operator <(const SmartControllerPtr& other) const;
-	bool	operator ==(const SmartControllerPtr& other) const;
-	SCA_IController*	operator->() const;
-	SCA_IController* 	operator*() const; 
-
-};
 
 class SCA_LogicManager
 {
 	vector<class SCA_EventManager*>		m_eventmanagers;
 	
-	vector<class SCA_ISensor*>			m_activatedsensors;
-	set<class SmartActuatorPtr>			m_activeActuators;
-	set<class SmartControllerPtr>		m_triggeredControllerSet;
-
-	map<SCA_ISensor*,controllerlist >	m_sensorcontrollermapje;
+	// SG_DList: Head of objects having activated actuators
+	//           element: SCA_IObject::m_activeActuators
+	SG_DList							m_activeActuators;
+	// SG_DList: Head of objects having activated controllers
+	//           element: SCA_IObject::m_activeControllers
+	SG_DList							m_triggeredControllerSet;
 
 	// need to find better way for this
 	// also known as FactoryManager...
@@ -112,10 +87,12 @@ class SCA_LogicManager
 	GEN_Map<STR_HashedString,void*>		m_map_gamemeshname_to_blendobj;
 	GEN_Map<CHashedPtr,void*>			m_map_blendobj_to_gameobj;
 
-	vector<SmartActuatorPtr>			m_removedActuators;
+	// head of actuators being deactivated during the logic update
+	SG_DList							m_removedActuators;
 public:
 	SCA_LogicManager();
 	virtual ~SCA_LogicManager();
+
 	//void	SetKeyboardManager(SCA_KeyboardManager* keyboardmgr) { m_keyboardmgr=keyboardmgr;}
 	void	RegisterEventManager(SCA_EventManager* eventmgr);
 	void	RegisterToSensor(SCA_IController* controller,
@@ -126,8 +103,7 @@ public:
 	void	BeginFrame(double curtime, double fixedtime);
 	void	UpdateFrame(double curtime, bool frame);
 	void	EndFrame();
-	void	AddActivatedSensor(SCA_ISensor* sensor);
-	void	AddActiveActuator(SCA_IActuator* sensor,class CValue* event);
+	void	AddActiveActuator(SCA_IActuator* sensor,bool event);
 	void	AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor);
 	SCA_EventManager*	FindEventManager(int eventmgrtype);
 	
@@ -138,7 +114,7 @@ public:
 	*/
 	void	RemoveSensor(SCA_ISensor* sensor);
 	void	RemoveController(SCA_IController* controller);
-	void	RemoveDestroyedActuator(SCA_IActuator* actuator);
+	void	RemoveActuator(SCA_IActuator* actuator);
 	
 
 	// for the scripting... needs a FactoryManager later (if we would have time... ;)
diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp
index ca875dad07c833a26a924582b3f194a637c6d83f..d407647cec32844b798bef22e1a1b785d5f65c27 100644
--- a/source/gameengine/GameLogic/SCA_MouseManager.cpp
+++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp
@@ -75,8 +75,8 @@ void SCA_MouseManager::NextFrame()
 {
 	if (m_mousedevice)
 	{
-		set<SCA_ISensor*>::iterator it;
-		for (it=m_sensors.begin(); it!=m_sensors.end(); it++)
+		SG_DList::iterator<SCA_ISensor> it(m_sensors);
+		for (it.begin();!it.end();++it)
 		{
 			SCA_MouseSensor* mousesensor = (SCA_MouseSensor*)(*it);
 			// (0,0) is the Upper Left corner in our local window
@@ -93,7 +93,7 @@ void SCA_MouseManager::NextFrame()
 				mousesensor->setX(mx);
 				mousesensor->setY(my);
 				
-				mousesensor->Activate(m_logicmanager,NULL);
+				mousesensor->Activate(m_logicmanager);
 			}
 		}
 	}
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
index c5f6fdabbe876a9cb3065a857d6f7274ccca7678..c5e1c3c0441f9086bc8412ea844f2e45b699c567 100644
--- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
@@ -111,7 +111,7 @@ CValue* SCA_MouseSensor::GetReplica()
 {
 	SCA_MouseSensor* replica = new SCA_MouseSensor(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	replica->Init();
 
 	return replica;
@@ -144,7 +144,7 @@ SCA_IInputDevice::KX_EnumInputs SCA_MouseSensor::GetHotKey()
 
 
 
-bool SCA_MouseSensor::Evaluate(CValue* event)
+bool SCA_MouseSensor::Evaluate()
 {
 	bool result = false;
 	bool reset = m_reset && m_level;
@@ -252,9 +252,7 @@ const char SCA_MouseSensor::GetXPosition_doc[] =
 "\tReturns the x-coordinate of the mouse sensor, in frame coordinates.\n"
 "\tThe lower-left corner is the origin. The coordinate is given in\n"
 "\tpixels\n";
-PyObject* SCA_MouseSensor::PyGetXPosition(PyObject* self, 
-										 PyObject* args, 
-										 PyObject* kwds) {
+PyObject* SCA_MouseSensor::PyGetXPosition() {
 	ShowDeprecationWarning("getXPosition()", "the position property");
 	return PyInt_FromLong(m_x);
 }
@@ -265,9 +263,7 @@ const char SCA_MouseSensor::GetYPosition_doc[] =
 "\tReturns the y-coordinate of the mouse sensor, in frame coordinates.\n"
 "\tThe lower-left corner is the origin. The coordinate is given in\n"
 "\tpixels\n";
-PyObject* SCA_MouseSensor::PyGetYPosition(PyObject* self, 
-										 PyObject* args, 
-										 PyObject* kwds) {
+PyObject* SCA_MouseSensor::PyGetYPosition() {
 	ShowDeprecationWarning("getYPosition()", "the position property");
 	return PyInt_FromLong(m_y);
 }
@@ -275,7 +271,7 @@ PyObject* SCA_MouseSensor::PyGetYPosition(PyObject* self,
 
 KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus,
 "getButtonStatus(button)\n"
-"\tGet the given button's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n")
+"\tGet the given button's status (KX_INPUT_NONE, KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED).\n")
 {
 	if (PyInt_Check(value))
 	{
@@ -283,7 +279,7 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus,
 		
 		if ((button < SCA_IInputDevice::KX_LEFTMOUSE)
 			|| (button > SCA_IInputDevice::KX_RIGHTMOUSE)){
-			PyErr_SetString(PyExc_ValueError, "invalid button specified!");
+			PyErr_SetString(PyExc_ValueError, "sensor.getButtonStatus(int): Mouse Sensor, invalid button specified!");
 			return NULL;
 		}
 		
@@ -300,12 +296,17 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus,
 /* ------------------------------------------------------------------------- */
 
 PyTypeObject SCA_MouseSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_MouseSensor",
-	sizeof(SCA_MouseSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -343,18 +344,16 @@ PyAttributeDef SCA_MouseSensor::Attributes[] = {
 
 PyObject* SCA_MouseSensor::py_getattro(PyObject *attr) 
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_ISensor);
 }
 
+PyObject* SCA_MouseSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 int SCA_MouseSensor::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_ISensor::py_setattro(attr, value);
+	py_setattro_up(SCA_ISensor);
 }
 
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h
index 73410569cc2e6bf897f513ff1e4cb1a821d0baeb..6d6302b514ab413ffe6a6ddc3a2d89c9376b01aa 100644
--- a/source/gameengine/GameLogic/SCA_MouseSensor.h
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.h
@@ -97,7 +97,7 @@ class SCA_MouseSensor : public SCA_ISensor
 
 	virtual ~SCA_MouseSensor();
 	virtual CValue* GetReplica();
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual void Init();
 	virtual bool IsPositiveTrigger();
 	short int GetModeKey();
@@ -110,13 +110,14 @@ class SCA_MouseSensor : public SCA_ISensor
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	//Deprecated functions ----->
 	/* read x-coordinate */
-	KX_PYMETHOD_DOC(SCA_MouseSensor,GetXPosition);
+	KX_PYMETHOD_DOC_NOARGS(SCA_MouseSensor,GetXPosition);
 	/* read y-coordinate */
-	KX_PYMETHOD_DOC(SCA_MouseSensor,GetYPosition);
+	KX_PYMETHOD_DOC_NOARGS(SCA_MouseSensor,GetYPosition);
 	//<----- deprecated
 	
 	// get button status
diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp
index bddd5f4d3abafd45b88710ba50062ae7a6720824..d27aea5e6f74a99f40476c97e3b1e57711194e05 100644
--- a/source/gameengine/GameLogic/SCA_NANDController.cpp
+++ b/source/gameengine/GameLogic/SCA_NANDController.cpp
@@ -66,26 +66,19 @@ void SCA_NANDController::Trigger(SCA_LogicManager* logicmgr)
 	!(is==m_linkedsensors.end());is++)
 	{
 		SCA_ISensor* sensor = *is;
-		if (!sensor->IsPositiveTrigger())
+		if (!sensor->GetState())
 		{
 			sensorresult = true;
 			break;
 		}
 	}
 	
-	CValue* newevent = new CBoolValue(sensorresult);
-
 	for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
 	!(i==m_linkedactuators.end());i++)
 	{
-		SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
-		logicmgr->AddActiveActuator(actua,newevent);
+		SCA_IActuator* actua = *i;
+		logicmgr->AddActiveActuator(actua,sensorresult);
 	}
-
-	// every actuator that needs the event, has a it's own reference to it now so
-	// release it (so to be clear: if there is no actuator, it's deleted right now)
-	newevent->Release();
-
 }
 
 
@@ -94,7 +87,7 @@ CValue* SCA_NANDController::GetReplica()
 {
 	CValue* replica = new SCA_NANDController(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -107,12 +100,17 @@ CValue* SCA_NANDController::GetReplica()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_NANDController::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_NANDController",
-	sizeof(SCA_NANDController),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -145,4 +143,8 @@ PyObject* SCA_NANDController::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_IController);
 }
 
+PyObject* SCA_NANDController::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IController);
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h
index 11600914a1a212413b313ff52a958a92a6cd63f9..0ae0ff19745ab6e5ca4c1cbae3529a292d540e24 100644
--- a/source/gameengine/GameLogic/SCA_NANDController.h
+++ b/source/gameengine/GameLogic/SCA_NANDController.h
@@ -49,6 +49,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 
 };
 
diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp
index 3ee073523c3dd56027a4f42227644c2fa280b8b5..6c9141636b2b284f70b941f5ee17a734519d97ce 100644
--- a/source/gameengine/GameLogic/SCA_NORController.cpp
+++ b/source/gameengine/GameLogic/SCA_NORController.cpp
@@ -66,26 +66,19 @@ void SCA_NORController::Trigger(SCA_LogicManager* logicmgr)
 	!(is==m_linkedsensors.end());is++)
 	{
 		SCA_ISensor* sensor = *is;
-		if (sensor->IsPositiveTrigger())
+		if (sensor->GetState())
 		{
 			sensorresult = false;
 			break;
 		}
 	}
 	
-	CValue* newevent = new CBoolValue(sensorresult);
-
 	for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
 	!(i==m_linkedactuators.end());i++)
 	{
-		SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
-		logicmgr->AddActiveActuator(actua,newevent);
+		SCA_IActuator* actua = *i;
+		logicmgr->AddActiveActuator(actua,sensorresult);
 	}
-
-	// every actuator that needs the event, has a it's own reference to it now so
-	// release it (so to be clear: if there is no actuator, it's deleted right now)
-	newevent->Release();
-
 }
 
 
@@ -94,7 +87,7 @@ CValue* SCA_NORController::GetReplica()
 {
 	CValue* replica = new SCA_NORController(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -107,12 +100,17 @@ CValue* SCA_NORController::GetReplica()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_NORController::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_NORController",
-	sizeof(SCA_NORController),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -145,4 +143,8 @@ PyObject* SCA_NORController::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_IController);
 }
 
+PyObject* SCA_NORController::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IController);
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h
index fc814e28d37285dae3f581d5ade1f65e9f7045f9..06cbb70a489597cbfdab6b89c8797cb8ea4cc79e 100644
--- a/source/gameengine/GameLogic/SCA_NORController.h
+++ b/source/gameengine/GameLogic/SCA_NORController.h
@@ -49,6 +49,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject*		py_getattro_dict();
 
 };
 
diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp
index 91d5e56d4f365a33f9fd54d385d82abdfa7eb516..42c0a67d657f7095b6c9dc803e8e0ec1a8dc8150 100644
--- a/source/gameengine/GameLogic/SCA_ORController.cpp
+++ b/source/gameengine/GameLogic/SCA_ORController.cpp
@@ -60,7 +60,7 @@ CValue* SCA_ORController::GetReplica()
 {
 	CValue* replica = new SCA_ORController(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -76,21 +76,16 @@ void SCA_ORController::Trigger(SCA_LogicManager* logicmgr)
 	while ( (!sensorresult) && (!(is==m_linkedsensors.end())) )
 	{
 		sensor = *is;
-		if (sensor->IsPositiveTrigger()) sensorresult = true;
+		if (sensor->GetState()) sensorresult = true;
 		is++;
 	}
 	
-	CValue* newevent = new CBoolValue(sensorresult);
-
 	for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
 	!(i==m_linkedactuators.end());i++)
 	{
-		SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
-		logicmgr->AddActiveActuator(actua,newevent);
+		SCA_IActuator* actua = *i;
+		logicmgr->AddActiveActuator(actua,sensorresult);
 	}
-
-
-	newevent->Release();
 }
 
 /* ------------------------------------------------------------------------- */
@@ -99,12 +94,17 @@ void SCA_ORController::Trigger(SCA_LogicManager* logicmgr)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_ORController::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_ORController",
-	sizeof(SCA_ORController),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -138,4 +138,8 @@ PyObject* SCA_ORController::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_IController);
 }
 
+PyObject* SCA_ORController::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IController);
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h
index fdc81486e741143e2abb1d7fd4355907be55d392..66f772c739edf46e35633cade6773f5645b034db 100644
--- a/source/gameengine/GameLogic/SCA_ORController.h
+++ b/source/gameengine/GameLogic/SCA_ORController.h
@@ -50,6 +50,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 };
 
 #endif //__KX_ORCONTROLLER
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
index e1f303430ec16bab41dc269a05ea5e54118c02c8..33dc83506f38eaf1e9f846f87e45bc9f0f16a593 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
@@ -77,11 +77,25 @@ bool SCA_PropertyActuator::Update()
 	CParser parser;
 	parser.SetContext( propowner->AddRef());
 	
-	CExpression* userexpr = parser.ProcessText(m_exprtxt);
-	if (userexpr)
+	CExpression* userexpr= NULL;
+	
+	if (m_type==KX_ACT_PROP_TOGGLE)
 	{
-		
-
+		/* dont use */
+		CValue* newval;
+		CValue* oldprop = propowner->GetProperty(m_propname);
+		if (oldprop)
+		{
+			newval = new CBoolValue((oldprop->GetNumber()==0.0) ? true:false);
+			oldprop->SetValue(newval);
+		} else
+		{	/* as not been assigned, evaluate as false, so assign true */
+			newval = new CBoolValue(true);
+			propowner->SetProperty(m_propname,newval);
+		}
+		newval->Release();
+	}
+	else if ((userexpr = parser.ProcessText(m_exprtxt))) {
 		switch (m_type)
 		{
 
@@ -135,6 +149,7 @@ bool SCA_PropertyActuator::Update()
 				}
 				break;
 			}
+		/* case KX_ACT_PROP_TOGGLE: */ /* accounted for above, no need for userexpr */
 		default:
 			{
 
@@ -171,11 +186,6 @@ GetReplica() {
 	SCA_PropertyActuator* replica = new SCA_PropertyActuator(*this);
 
 	replica->ProcessReplica();
-
-	// this will copy properties and so on...
-
-	CValue::AddDataToReplica(replica);
-
 	return replica;
 
 };
@@ -218,12 +228,17 @@ void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_PropertyActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_PropertyActuator",
-	sizeof(SCA_PropertyActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -257,21 +272,20 @@ PyMethodDef SCA_PropertyActuator::Methods[] = {
 PyAttributeDef SCA_PropertyActuator::Attributes[] = {
 	KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty),
 	KX_PYATTRIBUTE_STRING_RW("value",0,100,false,SCA_PropertyActuator,m_exprtxt),
+	KX_PYATTRIBUTE_INT_RW("type", KX_ACT_PROP_NODEF+1, KX_ACT_PROP_MAX-1, false, SCA_PropertyActuator, m_type), /* ATTR_TODO add constents to game logic dict */
 	{ NULL }	//Sentinel
 };
 
 PyObject* SCA_PropertyActuator::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* SCA_PropertyActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int SCA_PropertyActuator::py_setattro(PyObject *attr, PyObject *value) {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 /* 1. setProperty                                                        */
@@ -280,12 +294,12 @@ const char SCA_PropertyActuator::SetProperty_doc[] =
 "\t- name: string\n"
 "\tSet the property on which to operate. If there is no property\n"
 "\tof this name, the call is ignored.\n";
-PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_PropertyActuator::PySetProperty(PyObject* args, PyObject* kwds)
 {
 	ShowDeprecationWarning("setProperty()", "the 'property' property");
 	/* Check whether the name exists first ! */
 	char *nameArg;
-	if (!PyArg_ParseTuple(args, "s", &nameArg)) {
+	if (!PyArg_ParseTuple(args, "s:setProperty", &nameArg)) {
 		return NULL;
 	}
 
@@ -305,7 +319,7 @@ PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, Py
 const char SCA_PropertyActuator::GetProperty_doc[] = 
 "getProperty(name)\n"
 "\tReturn the property on which the actuator operates.\n";
-PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* args, PyObject* kwds)
 {
 	ShowDeprecationWarning("getProperty()", "the 'property' property");
 	return PyString_FromString(m_propname);
@@ -318,11 +332,11 @@ const char SCA_PropertyActuator::SetValue_doc[] =
 "\tSet the value with which the actuator operates. If the value\n"
 "\tis not compatible with the type of the property, the subsequent\n"
 "\t action is ignored.\n";
-PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_PropertyActuator::PySetValue(PyObject* args, PyObject* kwds)
 {
 	ShowDeprecationWarning("setValue()", "the value property");
 	char *valArg;
-	if(!PyArg_ParseTuple(args, "s", &valArg)) {
+	if(!PyArg_ParseTuple(args, "s:setValue", &valArg)) {
 		return NULL;		
 	}
 	
@@ -335,7 +349,7 @@ PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObj
 const char SCA_PropertyActuator::GetValue_doc[] = 
 "getValue()\n"
 "\tReturns the value with which the actuator operates.\n";
-PyObject* SCA_PropertyActuator::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_PropertyActuator::PyGetValue(PyObject* args, PyObject* kwds)
 {
 	ShowDeprecationWarning("getValue()", "the value property");
 	return PyString_FromString(m_exprtxt);
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h
index 6a975716ed0504529d00c86398e60c4bc925a7cd..a8df08dfc6ecaad776317eb3925c272d6c72451f 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.h
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h
@@ -43,6 +43,7 @@ class SCA_PropertyActuator : public SCA_IActuator
 		KX_ACT_PROP_ASSIGN,
 		KX_ACT_PROP_ADD,
 		KX_ACT_PROP_COPY,
+		KX_ACT_PROP_TOGGLE,
 		KX_ACT_PROP_MAX
 	};
 	
@@ -86,6 +87,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject*  py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	// python wrapped methods
diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp
index e5e3f9cced5756265066ec7dcbb275469a3954ba..764465309df93c5234c0dd0e622cdf1705e937c1 100644
--- a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp
@@ -50,8 +50,9 @@ SCA_PropertyEventManager::~SCA_PropertyEventManager()
 void SCA_PropertyEventManager::NextFrame()
 {
 	// check for changed properties
-	for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++)
+	SG_DList::iterator<SCA_ISensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
 	{
-		(*it)->Activate(m_logicmgr,NULL);
+		(*it)->Activate(m_logicmgr);
 	}
 }
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
index 659823f6fbaa292549dff4c13c349dd110d714fe..2632cbd3dac7eaa898f08193d3912e327fc13bee 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -37,6 +37,7 @@
 #include "StringValue.h"
 #include "SCA_EventManager.h"
 #include "SCA_LogicManager.h"
+#include "BoolValue.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -111,7 +112,7 @@ CValue* SCA_PropertySensor::GetReplica()
 {
 	SCA_PropertySensor* replica = new SCA_PropertySensor(*this);
 	// m_range_expr must be recalculated on replica!
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	replica->Init();
 
 	replica->m_range_expr = NULL;
@@ -152,7 +153,7 @@ SCA_PropertySensor::~SCA_PropertySensor()
 
 
 
-bool SCA_PropertySensor::Evaluate(CValue* event)
+bool SCA_PropertySensor::Evaluate()
 {
 	bool result = CheckPropertyCondition();
 	bool reset = m_reset && m_level;
@@ -182,17 +183,14 @@ bool	SCA_PropertySensor::CheckPropertyCondition()
 			CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
 			if (!orgprop->IsError())
 			{
-				STR_String testprop = orgprop->GetText();
+				const STR_String& testprop = orgprop->GetText();
 				// Force strings to upper case, to avoid confusion in
 				// bool tests. It's stupid the prop's identity is lost
 				// on the way here...
-				if ((testprop == "TRUE") || (testprop == "FALSE")) {
-					STR_String checkprop = m_checkpropval;
-					checkprop.Upper();
-					result = (testprop == checkprop);
-				} else {
-					result = (orgprop->GetText() == m_checkpropval);
+				if ((&testprop == &CBoolValue::sTrueString) || (&testprop == &CBoolValue::sFalseString)) {
+					m_checkpropval.Upper();
 				}
+				result = (testprop == m_checkpropval);
 			}
 			orgprop->Release();
 
@@ -232,8 +230,8 @@ bool	SCA_PropertySensor::CheckPropertyCondition()
 					CValue* vallie = m_range_expr->Calculate();
 					if (vallie)
 					{
-						STR_String errtext = vallie->GetText();
-						if (errtext == "TRUE")
+						const STR_String& errtext = vallie->GetText();
+						if (&errtext == &CBoolValue::sTrueString)
 						{
 							result = true;
 						} else
@@ -295,9 +293,8 @@ CValue* SCA_PropertySensor::FindIdentifier(const STR_String& identifiername)
 
 int SCA_PropertySensor::validValueForProperty(void *self, const PyAttributeDef*)
 {
-	bool result = true;
 	/*  There is no type checking at this moment, unfortunately...           */
-	return result;
+	return 0;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -306,12 +303,17 @@ int SCA_PropertySensor::validValueForProperty(void *self, const PyAttributeDef*)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_PropertySensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_PropertySensor",
-	sizeof(SCA_PropertySensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -334,11 +336,11 @@ PyParentObject SCA_PropertySensor::Parents[] = {
 
 PyMethodDef SCA_PropertySensor::Methods[] = {
 	//Deprecated functions ------>
-	{"getType", (PyCFunction) SCA_PropertySensor::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc},
+	{"getType", (PyCFunction) SCA_PropertySensor::sPyGetType, METH_NOARGS, (PY_METHODCHAR)GetType_doc},
 	{"setType", (PyCFunction) SCA_PropertySensor::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc},
-	{"getProperty", (PyCFunction) SCA_PropertySensor::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
+	{"getProperty", (PyCFunction) SCA_PropertySensor::sPyGetProperty, METH_NOARGS, (PY_METHODCHAR)GetProperty_doc},
 	{"setProperty", (PyCFunction) SCA_PropertySensor::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
-	{"getValue", (PyCFunction) SCA_PropertySensor::sPyGetValue, METH_VARARGS, (PY_METHODCHAR)GetValue_doc},
+	{"getValue", (PyCFunction) SCA_PropertySensor::sPyGetValue, METH_NOARGS, (PY_METHODCHAR)GetValue_doc},
 	{"setValue", (PyCFunction) SCA_PropertySensor::sPySetValue, METH_VARARGS, (PY_METHODCHAR)SetValue_doc},
 	//<----- Deprecated
 	{NULL,NULL} //Sentinel
@@ -353,24 +355,22 @@ PyAttributeDef SCA_PropertySensor::Attributes[] = {
 
 
 PyObject* SCA_PropertySensor::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
-	py_getattro_up(SCA_ISensor); /* implicit return! */
+	py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_PropertySensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
 }
 
 int SCA_PropertySensor::py_setattro(PyObject *attr, PyObject *value) {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_ISensor::py_setattro(attr, value);
+	py_setattro_up(SCA_ISensor);
 }
 
 /* 1. getType */
 const char SCA_PropertySensor::GetType_doc[] = 
 "getType()\n"
 "\tReturns the type of check this sensor performs.\n";
-PyObject* SCA_PropertySensor::PyGetType(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_PropertySensor::PyGetType()
 {
 	ShowDeprecationWarning("getType()", "the type property");
 	return PyInt_FromLong(m_checktype);
@@ -383,12 +383,12 @@ const char SCA_PropertySensor::SetType_doc[] =
 "\t        KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED,\n"
 "\t        or KX_PROPSENSOR_EXPRESSION.\n"
 "\tSet the type of check to perform.\n";
-PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject* kwds) 
+PyObject* SCA_PropertySensor::PySetType(PyObject* args) 
 {
 	ShowDeprecationWarning("setType()", "the type property");
 	int typeArg;
 	
-	if (!PyArg_ParseTuple(args, "i", &typeArg)) {
+	if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) {
 		return NULL;
 	}
 	
@@ -404,7 +404,7 @@ PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject
 const char SCA_PropertySensor::GetProperty_doc[] = 
 "getProperty()\n"
 "\tReturn the property with which the sensor operates.\n";
-PyObject* SCA_PropertySensor::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) 
+PyObject* SCA_PropertySensor::PyGetProperty() 
 {
 	ShowDeprecationWarning("getProperty()", "the 'property' property");
 	return PyString_FromString(m_checkpropname);
@@ -416,14 +416,14 @@ const char SCA_PropertySensor::SetProperty_doc[] =
 "\t- name: string\n"
 "\tSets the property with which to operate. If there is no property\n"
 "\tof this name, the call is ignored.\n";
-PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) 
+PyObject* SCA_PropertySensor::PySetProperty(PyObject* args) 
 {
 	ShowDeprecationWarning("setProperty()", "the 'property' property");
 	/* We should query whether the name exists. Or should we create a prop   */
 	/* on the fly?                                                           */
 	char *propNameArg = NULL;
 
-	if (!PyArg_ParseTuple(args, "s", &propNameArg)) {
+	if (!PyArg_ParseTuple(args, "s:setProperty", &propNameArg)) {
 		return NULL;
 	}
 
@@ -441,7 +441,7 @@ PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyOb
 const char SCA_PropertySensor::GetValue_doc[] = 
 "getValue()\n"
 "\tReturns the value with which the sensor operates.\n";
-PyObject* SCA_PropertySensor::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds) 
+PyObject* SCA_PropertySensor::PyGetValue() 
 {
 	ShowDeprecationWarning("getValue()", "the value property");
 	return PyString_FromString(m_checkpropval);
@@ -454,19 +454,19 @@ const char SCA_PropertySensor::SetValue_doc[] =
 "\tSet the value with which the sensor operates. If the value\n"
 "\tis not compatible with the type of the property, the subsequent\n"
 "\t action is ignored.\n";
-PyObject* SCA_PropertySensor::PySetValue(PyObject* self, PyObject* args, PyObject* kwds) 
+PyObject* SCA_PropertySensor::PySetValue(PyObject* args) 
 {
 	ShowDeprecationWarning("setValue()", "the value property");
 	/* Here, we need to check whether the value is 'valid' for this property.*/
 	/* We know that the property exists, or is NULL.                         */
 	char *propValArg = NULL;
 
-	if(!PyArg_ParseTuple(args, "s", &propValArg)) {
+	if(!PyArg_ParseTuple(args, "s:setValue", &propValArg)) {
 		return NULL;
 	}
 	STR_String oldval = m_checkpropval;
 	m_checkpropval = propValArg;
-	if (validValueForProperty(self, NULL)) {
+	if (validValueForProperty(m_proxy, NULL)) {
 		m_checkpropval = oldval;
 		return NULL;
 	}	
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h
index 076c1ae51ecef5f7432d11d234fe987c7108add5..538ecd65949eb13c8249c6c53f3e50cb3c3247d2 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.h
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.h
@@ -81,7 +81,7 @@ public:
 	void	PrecalculateRangeExpression();
 	bool	CheckPropertyCondition();
 
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool	IsPositiveTrigger();
 	virtual CValue*		FindIdentifier(const STR_String& identifiername);
 
@@ -90,20 +90,21 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	/* 1. getType */
-	KX_PYMETHOD_DOC(SCA_PropertySensor,GetType);
+	KX_PYMETHOD_DOC_NOARGS(SCA_PropertySensor,GetType);
 	/* 2. setType */
-	KX_PYMETHOD_DOC(SCA_PropertySensor,SetType);
+	KX_PYMETHOD_DOC_VARARGS(SCA_PropertySensor,SetType);
 	/* 3. setProperty */
-	KX_PYMETHOD_DOC(SCA_PropertySensor,SetProperty);
+	KX_PYMETHOD_DOC_VARARGS(SCA_PropertySensor,SetProperty);
 	/* 4. getProperty */
-	KX_PYMETHOD_DOC(SCA_PropertySensor,GetProperty);
+	KX_PYMETHOD_DOC_NOARGS(SCA_PropertySensor,GetProperty);
 	/* 5. getValue */
-	KX_PYMETHOD_DOC(SCA_PropertySensor,GetValue);
+	KX_PYMETHOD_DOC_NOARGS(SCA_PropertySensor,GetValue);
 	/* 6. setValue */
-	KX_PYMETHOD_DOC(SCA_PropertySensor,SetValue);
+	KX_PYMETHOD_DOC_VARARGS(SCA_PropertySensor,SetValue);
 	/**
 	 * Test whether this is a sensible value (type check)
 	 */
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index 2d200e0a2380adb5f24777843509d8b3c0af199e..212366e65265eed82fb8229df18788b7403bdbd3 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -48,12 +48,18 @@ SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL;
 
 
 SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj,
+										   int mode,
 										   PyTypeObject* T)
 	: SCA_IController(gameobj, T),
 	m_bytecode(NULL),
+	m_function(NULL),
+	m_function_argc(0),
 	m_bModified(true),
+	m_debug(false),
+	m_mode(mode),
 	m_pythondictionary(NULL)
 {
+	
 }
 
 /*
@@ -74,15 +80,12 @@ int			SCA_PythonController::Release()
 
 SCA_PythonController::~SCA_PythonController()
 {
-	if (m_bytecode)
-	{
-		//
-		//printf("released python byte script\n");
-		Py_DECREF(m_bytecode);
-	}
+	//printf("released python byte script\n");
 	
-	if (m_pythondictionary)
-	{
+	Py_XDECREF(m_bytecode);
+	Py_XDECREF(m_function);
+	
+	if (m_pythondictionary) {
 		// break any circular references in the dictionary
 		PyDict_Clear(m_pythondictionary);
 		Py_DECREF(m_pythondictionary);
@@ -94,8 +97,12 @@ SCA_PythonController::~SCA_PythonController()
 CValue* SCA_PythonController::GetReplica()
 {
 	SCA_PythonController* replica = new SCA_PythonController(*this);
-	// Copy the compiled bytecode if possible.
+	
+	/* why is this needed at all??? - m_bytecode is NULL'd below so this doesnt make sense
+	 * but removing it crashes blender (with YoFrankie). so leave in for now - Campbell */
 	Py_XINCREF(replica->m_bytecode);
+	
+	Py_XINCREF(replica->m_function); // this is ok since its not set to NULL
 	replica->m_bModified = replica->m_bytecode == NULL;
 	
 	// The replica->m_pythondictionary is stolen - replace with a copy.
@@ -110,7 +117,7 @@ CValue* SCA_PythonController::GetReplica()
 	*/
 	
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -150,14 +157,15 @@ int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor)
 	return 0;
 }
 
-#if 0
-static const char* sPyGetCurrentController__doc__;
-#endif
-
-
-PyObject* SCA_PythonController::sPyGetCurrentController(PyObject* self)
+/* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */
+PyObject* SCA_PythonController::sPyGetCurrentController(PyObject *self)
 {
-	return m_sCurrentController->AddRef();
+	if(m_sCurrentController==NULL)
+	{
+		PyErr_SetString(PyExc_SystemError, "GameLogic.getCurrentController(), this function is being run outside the python controllers context, or blenders internal state is corrupt.");
+		return NULL;
+	}
+	return m_sCurrentController->GetProxy();
 }
 
 SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value)
@@ -170,16 +178,16 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value)
 	if (PyString_Check(value)) {
 		/* get the actuator from the name */
 		char *name= PyString_AsString(value);
-		for(it = lacts.begin(); it!= lacts.end(); it++) {
+		for(it = lacts.begin(); it!= lacts.end(); ++it) {
 			if( name == (*it)->GetName() ) {
 				return *it;
 			}
 		}
 	}
-	else {
-		/* Expecting an actuator type */
-		for(it = lacts.begin(); it!= lacts.end(); it++) {
-			if( static_cast<SCA_IActuator*>(value) == (*it) ) {
+	else if (BGE_PROXY_CHECK_TYPE(value)) {
+		PyObjectPlus *value_plus= BGE_PROXY_REF(value);
+		for(it = lacts.begin(); it!= lacts.end(); ++it) {
+			if( static_cast<SCA_IActuator*>(value_plus) == (*it) ) {
 				return *it;
 			}
 		}
@@ -187,49 +195,46 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value)
 	
 	/* set the exception */
 	PyObject *value_str = PyObject_Repr(value); /* new ref */
-	PyErr_Format(PyExc_ValueError, "'%s' not in this controllers actuator list", PyString_AsString(value_str));
+	PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", PyString_AsString(value_str));
 	Py_DECREF(value_str);
 	
 	return false;
 }
 
-#if 0
-static const char* sPyAddActiveActuator__doc__;
-#endif
-
-PyObject* SCA_PythonController::sPyAddActiveActuator(
-	  
-		PyObject* self, 
-		PyObject* args)
+/* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */
+PyObject* SCA_PythonController::sPyAddActiveActuator(PyObject* self, PyObject* args)
 {
+	ShowDeprecationWarning("GameLogic.addActiveActuator(act, bool)", "controller.activate(act) or controller.deactivate(act)");
 	
 	PyObject* ob1;
 	int activate;
-	if (!PyArg_ParseTuple(args, "Oi", &ob1,&activate))
+	if (!PyArg_ParseTuple(args, "Oi:addActiveActuator", &ob1,&activate))
 		return NULL;
 	
 	SCA_IActuator* actu = LinkedActuatorFromPy(ob1);
 	if(actu==NULL)
 		return NULL;
 	
-	CValue* boolval = new CBoolValue(activate!=0);
+	bool boolval = (activate!=0);
 	m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu,boolval);
-	boolval->Release();
 	Py_RETURN_NONE;
 }
 
-
 const char* SCA_PythonController::sPyGetCurrentController__doc__ = "getCurrentController()";
 const char* SCA_PythonController::sPyAddActiveActuator__doc__= "addActiveActuator(actuator,bool)";
-const char SCA_PythonController::GetActuators_doc[] = "getActuator";
 
 PyTypeObject SCA_PythonController::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"SCA_PythonController",
-		sizeof(SCA_PythonController),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -252,57 +257,128 @@ PyMethodDef SCA_PythonController::Methods[] = {
 	{"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O},
 	{"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O},
 	
-	{"getActuators", (PyCFunction) SCA_PythonController::sPyGetActuators, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetActuators_doc},
-	{"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc},
-	{"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc},
-	{"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, (PY_METHODCHAR)SCA_PythonController::GetSensor_doc},
 	//Deprecated functions ------>
 	{"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O},
 	{"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS},
-	{"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_NOARGS},
 	//<----- Deprecated
 	{NULL,NULL} //Sentinel
 };
 
 PyAttributeDef SCA_PythonController::Attributes[] = {
+	KX_PYATTRIBUTE_RW_FUNCTION("script", SCA_PythonController, pyattr_get_script, pyattr_set_script),
 	{ NULL }	//Sentinel
 };
 
-bool SCA_PythonController::Compile()
+void SCA_PythonController::ErrorPrint(const char *error_msg)
 {
+	// didn't compile, so instead of compile, complain
+	// something is wrong, tell the user what went wrong
+	printf("%s - controller \"%s\":\n", error_msg, GetName().Ptr());
+	//PyRun_SimpleString(m_scriptText.Ptr());
+	PyErr_Print();
+	
+	/* Added in 2.48a, the last_traceback can reference Objects for example, increasing
+	 * their user count. Not to mention holding references to wrapped data.
+	 * This is especially bad when the PyObject for the wrapped data is free'd, after blender 
+	 * has alredy dealocated the pointer */
+	PySys_SetObject( (char *)"last_traceback", NULL);
+	PyErr_Clear(); /* just to be sure */
+}
+
+bool SCA_PythonController::Compile()
+{	
 	//printf("py script modified '%s'\n", m_scriptName.Ptr());
+	m_bModified= false;
 	
 	// if a script already exists, decref it before replace the pointer to a new script
-	if (m_bytecode)
-	{
+	if (m_bytecode) {
 		Py_DECREF(m_bytecode);
 		m_bytecode=NULL;
 	}
+	
 	// recompile the scripttext into bytecode
 	m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input);
-	m_bModified=false;
 	
-	if (m_bytecode)
-	{
-		
+	if (m_bytecode) {
 		return true;
+	} else {
+		ErrorPrint("Python error compiling script");
+		return false;
 	}
-	else {
-		// didn't compile, so instead of compile, complain
-		// something is wrong, tell the user what went wrong
-		printf("Python compile error from controller \"%s\": \n", GetName().Ptr());
-		//PyRun_SimpleString(m_scriptText.Ptr());
-		PyErr_Print();
-		
-		/* Added in 2.48a, the last_traceback can reference Objects for example, increasing
-		 * their user count. Not to mention holding references to wrapped data.
-		 * This is especially bad when the PyObject for the wrapped data is free'd, after blender 
-		 * has alredy dealocated the pointer */
-		PySys_SetObject( (char *)"last_traceback", Py_None);
-		PyErr_Clear(); /* just to be sure */
+}
+
+bool SCA_PythonController::Import()
+{
+	//printf("py module modified '%s'\n", m_scriptName.Ptr());
+	m_bModified= false;
+	
+	/* incase we re-import */
+	Py_XDECREF(m_function);
+	m_function= NULL;
+	
+	vector<STR_String> py_function_path = m_scriptText.Explode('.');
+	
+	if(py_function_path.size() < 2) {
+		printf("Python module name formatting error \"%s\":\n\texpected \"SomeModule.Func\", got \"%s\"\n", GetName().Ptr(), m_scriptText.Ptr());
+		return false;
+	}
+	
+	PyObject *mod = PyImport_ImportModule((char *)py_function_path[0].Ptr());
+	if(mod && m_debug) {
+		Py_DECREF(mod); /* getting a new one so dont hold a ref to the old one */
+		mod= PyImport_ReloadModule(mod);
+	}
+	
+	if(mod==NULL) {
+		ErrorPrint("Python module not found");
+		return false;
+	}
+	/* 'mod' will be DECREF'd as 'base' 
+	 * 'm_function' will be left holding a reference that the controller owns */
+	
+	PyObject *base= mod;
+	
+	for(unsigned int i=1; i < py_function_path.size(); i++) {
+		m_function = PyObject_GetAttrString(base, py_function_path[i].Ptr());
+		Py_DECREF(base);
+		base = m_function; /* for the next loop if there is on */
 		
+		if(m_function==NULL) {
+			PyErr_Clear(); /* print our own error below */
+			break;
+		}
+	}
+	
+	if(m_function==NULL) {
+		printf("Python module error \"%s\":\n \"%s\" module found but function missing\n", GetName().Ptr(), m_scriptText.Ptr());
 		return false;
 	}
+	
+	if(!PyCallable_Check(m_function)) {
+		Py_DECREF(m_function);
+		printf("Python module function error \"%s\":\n \"%s\" not callable\n", GetName().Ptr(), m_scriptText.Ptr());
+		return false;
+	}
+	
+	m_function_argc = 0; /* rare cases this could be a function that isnt defined in python, assume zero args */
+	if (PyFunction_Check(m_function)) {
+		PyObject *py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(m_function), "co_argcount");
+		if(py_arg_count) {
+			m_function_argc = PyLong_AsLong(py_arg_count);
+			Py_DECREF(py_arg_count);
+		}
+		else {
+			PyErr_Clear(); /* unlikely to fail but just incase */
+		}
+	}
+	
+	if(m_function_argc > 1) {
+		Py_DECREF(m_function);
+		printf("Python module function has \"%s\":\n \"%s\" takes %d args, should be zero or 1 controller arg\n", GetName().Ptr(), m_scriptText.Ptr(), m_function_argc);
+		return false;
+	}
+	
+	return true;
 }
 
 void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
@@ -310,16 +386,18 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
 	m_sCurrentController = this;
 	m_sCurrentLogicManager = logicmgr;
 	
-	if (m_bModified)
+	PyObject *excdict=		NULL;
+	PyObject* resultobj=	NULL;
+	
+	switch(m_mode) {
+	case SCA_PYEXEC_SCRIPT:
 	{
-		if (Compile()==false) // sets m_bModified to false
+		if (m_bModified)
+			if (Compile()==false) // sets m_bModified to false
+				return;
+		if (!m_bytecode)
 			return;
-	}
-	if (!m_bytecode) {
-		return;
-	}
 		
-	
 		/*
 		 * This part here with excdict is a temporary patch
 		 * to avoid python/gameengine crashes when python
@@ -338,10 +416,36 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
 		 * should always ensure excdict is cleared).
 		 */
 
-	PyObject *excdict= PyDict_Copy(m_pythondictionary);
-	PyObject* resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode,
-		excdict, excdict);
-
+		excdict= PyDict_Copy(m_pythondictionary);
+		resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode, excdict, excdict);
+		/* PyRun_SimpleString(m_scriptText.Ptr()); */
+		break;
+	}
+	case SCA_PYEXEC_MODULE:
+	{
+		if (m_bModified || m_debug)
+			if (Import()==false) // sets m_bModified to false
+				return;
+		if (!m_function)
+			return;
+		
+		PyObject *args= NULL;
+		
+		if(m_function_argc==1) {
+			args = PyTuple_New(1);
+			PyTuple_SET_ITEM(args, 0, GetProxy());
+		}
+		
+		resultobj = PyObject_CallObject(m_function, args);
+		Py_XDECREF(args);
+		break;
+	}
+	
+	} /* end switch */
+	
+	
+	
+	/* Free the return value and print the error */
 	if (resultobj)
 	{
 		Py_DECREF(resultobj);
@@ -349,24 +453,26 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
 	else
 	{
 		// something is wrong, tell the user what went wrong
-		printf("Python script error from controller \"%s\": \n", GetName().Ptr());
+		printf("Python script error from controller \"%s\":\n", GetName().Ptr());
 		PyErr_Print();
 		
 		/* Added in 2.48a, the last_traceback can reference Objects for example, increasing
 		 * their user count. Not to mention holding references to wrapped data.
 		 * This is especially bad when the PyObject for the wrapped data is free'd, after blender 
 		 * has alredy dealocated the pointer */
-		PySys_SetObject( (char *)"last_traceback", Py_None);
+		PySys_SetObject( (char *)"last_traceback", NULL);
 		PyErr_Clear(); /* just to be sure */
-		
-		//PyRun_SimpleString(m_scriptText.Ptr());
 	}
-
-	// clear after PyErrPrint - seems it can be using
-	// something in this dictionary and crash?
-	PyDict_Clear(excdict);
-	Py_DECREF(excdict);
-	m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end());
+	
+	if(excdict) /* Only for SCA_PYEXEC_SCRIPT types */
+	{
+		/* clear after PyErrPrint - seems it can be using
+		 * something in this dictionary and crash? */
+		PyDict_Clear(excdict);
+		Py_DECREF(excdict);
+	}	
+	
+	m_triggeredSensors.clear();
 	m_sCurrentController = NULL;
 }
 
@@ -374,155 +480,47 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
 
 PyObject* SCA_PythonController::py_getattro(PyObject *attr)
 {
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str,"state")) {
-		return PyInt_FromLong(m_statemask);
-	}
-	if (!strcmp(attr_str,"script")) {
-		return PyString_FromString(m_scriptText);
-	}
 	py_getattro_up(SCA_IController);
 }
 
+PyObject* SCA_PythonController::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IController);
+}
+
 int SCA_PythonController::py_setattro(PyObject *attr, PyObject *value)
 {
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str,"state")) {
-		PyErr_SetString(PyExc_AttributeError, "state is read only");
-		return 1;
-	}
-	if (!strcmp(attr_str,"script")) {
-		char *scriptArg = PyString_AsString(value);
-		
-		if (scriptArg==NULL) {
-			PyErr_SetString(PyExc_TypeError, "expected a string (script name)");
-			return -1;
-		}
-	
-		/* set scripttext sets m_bModified to true, 
-			so next time the script is needed, a reparse into byte code is done */
-		this->SetScriptText(scriptArg);
-		
-		return 1;
-	}
-	return SCA_IController::py_setattro(attr, value);
+	py_setattro_up(SCA_IController);
 }
 
-PyObject* SCA_PythonController::PyActivate(PyObject* self, PyObject *value)
+PyObject* SCA_PythonController::PyActivate(PyObject *value)
 {
 	SCA_IActuator* actu = LinkedActuatorFromPy(value);
 	if(actu==NULL)
 		return NULL;
 	
-	CValue* boolval = new CBoolValue(true);
-	m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval);
-	boolval->Release();
+	m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, true);
 	Py_RETURN_NONE;
 }
 
-PyObject* SCA_PythonController::PyDeActivate(PyObject* self, PyObject *value)
+PyObject* SCA_PythonController::PyDeActivate(PyObject *value)
 {
 	SCA_IActuator* actu = LinkedActuatorFromPy(value);
 	if(actu==NULL)
 		return NULL;
 	
-	CValue* boolval = new CBoolValue(false);
-	m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval);
-	boolval->Release();
+	m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, false);
 	Py_RETURN_NONE;
 }
 
-PyObject* SCA_PythonController::PyGetActuators(PyObject* self)
-{
-	PyObject* resultlist = PyList_New(m_linkedactuators.size());
-	for (unsigned int index=0;index<m_linkedactuators.size();index++)
-	{
-		PyList_SET_ITEM(resultlist,index,m_linkedactuators[index]->AddRef());
-	}
-
-	return resultlist;
-}
-
-const char SCA_PythonController::GetSensor_doc[] = 
-"GetSensor (char sensorname) return linked sensor that is named [sensorname]\n";
-PyObject*
-SCA_PythonController::PyGetSensor(PyObject* self, PyObject* value)
-{
-
-	char *scriptArg = PyString_AsString(value);
-	if (scriptArg==NULL) {
-		PyErr_SetString(PyExc_TypeError, "expected a string (sensor name)");
-		return NULL;
-	}
-	
-	for (unsigned int index=0;index<m_linkedsensors.size();index++)
-	{
-		SCA_ISensor* sensor = m_linkedsensors[index];
-		STR_String realname = sensor->GetName();
-		if (realname == scriptArg)
-		{
-			return sensor->AddRef();
-		}
-	}
-	
-	char emsg[96];
-	PyOS_snprintf( emsg, sizeof( emsg ), "Unable to find requested sensor \"%s\"", scriptArg );
-	PyErr_SetString(PyExc_AttributeError, emsg);
-	return NULL;
-}
-
-
-
-const char SCA_PythonController::GetActuator_doc[] = 
-"GetActuator (char sensorname) return linked actuator that is named [actuatorname]\n";
-PyObject*
-SCA_PythonController::PyGetActuator(PyObject* self, PyObject* value)
-{
-
-	char *scriptArg = PyString_AsString(value);
-	if (scriptArg==NULL) {
-		PyErr_SetString(PyExc_TypeError, "expected a string (actuator name)");
-		return NULL;
-	}
-	
-	for (unsigned int index=0;index<m_linkedactuators.size();index++)
-	{
-		SCA_IActuator* actua = m_linkedactuators[index];
-		if (actua->GetName() == scriptArg)
-		{
-			return actua->AddRef();
-		}
-	}
-	
-	char emsg[96];
-	PyOS_snprintf( emsg, sizeof( emsg ), "Unable to find requested actuator \"%s\"", scriptArg );
-	PyErr_SetString(PyExc_AttributeError, emsg);
-	return NULL;
-}
-
-
-const char SCA_PythonController::GetSensors_doc[]   = "getSensors returns a list of all attached sensors";
-PyObject*
-SCA_PythonController::PyGetSensors(PyObject* self)
-{
-	PyObject* resultlist = PyList_New(m_linkedsensors.size());
-	for (unsigned int index=0;index<m_linkedsensors.size();index++)
-	{
-		PyList_SET_ITEM(resultlist,index,m_linkedsensors[index]->AddRef());
-	}
-	
-	return resultlist;
-}
-
 /* 1. getScript */
-PyObject* SCA_PythonController::PyGetScript(PyObject* self)
+PyObject* SCA_PythonController::PyGetScript()
 {
 	ShowDeprecationWarning("getScript()", "the script property");
 	return PyString_FromString(m_scriptText);
 }
 
 /* 2. setScript */
-PyObject* SCA_PythonController::PySetScript(PyObject* self, PyObject* value)
+PyObject* SCA_PythonController::PySetScript(PyObject* value)
 {
 	char *scriptArg = PyString_AsString(value);
 	
@@ -541,11 +539,29 @@ PyObject* SCA_PythonController::PySetScript(PyObject* self, PyObject* value)
 	Py_RETURN_NONE;
 }
 
-/* 1. getScript */
-PyObject* SCA_PythonController::PyGetState(PyObject* self)
+PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-	ShowDeprecationWarning("getState()", "the state property");
-	return PyInt_FromLong(m_statemask);
+	SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v);
+	return PyString_FromString(self->m_scriptText);
 }
 
+int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v);
+	
+	char *scriptArg = PyString_AsString(value);
+	
+	if (scriptArg==NULL) {
+		PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text");
+		return -1;
+	}
+
+	/* set scripttext sets m_bModified to true, 
+		so next time the script is needed, a reparse into byte code is done */
+	self->SetScriptText(scriptArg);
+		
+	return 0;
+}
+
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h
index 3348071c00fdd12d64828c569b675a06f598bdb8..0c2af79c3a31f38cceede4ffef70e1d94aa2e465 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.h
+++ b/source/gameengine/GameLogic/SCA_PythonController.h
@@ -42,23 +42,37 @@ class SCA_IObject;
 class SCA_PythonController : public SCA_IController
 {
 	Py_Header;
-	struct _object *		m_bytecode;
+	struct _object *		m_bytecode; /* SCA_PYEXEC_SCRIPT only */
+	PyObject*				m_function; /* SCA_PYEXEC_MODULE only */
+	int						m_function_argc;
 	bool					m_bModified;
+	bool					m_debug;	/* use with SCA_PYEXEC_MODULE for reloading every logic run */
+	int						m_mode;
 
+	
  protected:
 	STR_String				m_scriptText;
 	STR_String				m_scriptName;
-	PyObject*				m_pythondictionary;
+	PyObject*				m_pythondictionary;	/* for SCA_PYEXEC_SCRIPT only */
+	PyObject*				m_pythonfunction;	/* for SCA_PYEXEC_MODULE only */
+ 
 	std::vector<class SCA_ISensor*>		m_triggeredSensors;
+ 
+ public:
+	enum SCA_PyExecMode
+	{
+		SCA_PYEXEC_SCRIPT = 0,
+		SCA_PYEXEC_MODULE,
+		SCA_PYEXEC_MAX
+	};
 
- public: 
 	static SCA_PythonController* m_sCurrentController; // protected !!!
 
 	//for debugging
 	//virtual	CValue*		AddRef();
 	//virtual int			Release();												// Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
 
-	SCA_PythonController(SCA_IObject* gameobj,PyTypeObject* T = &Type);
+	SCA_PythonController(SCA_IObject* gameobj, int mode, PyTypeObject* T = &Type);
 	virtual ~SCA_PythonController();
 
 	virtual CValue* GetReplica();
@@ -67,10 +81,14 @@ class SCA_PythonController : public SCA_IController
 	void	SetScriptText(const STR_String& text);
 	void	SetScriptName(const STR_String& name);
 	void	SetDictionary(PyObject*	pythondictionary);
+	void	SetDebug(bool debug) { m_debug = debug; }
 	void	AddTriggeredSensor(class SCA_ISensor* sensor)
 		{ m_triggeredSensors.push_back(sensor); }
 	int		IsTriggered(class SCA_ISensor* sensor);
 	bool	Compile();
+	bool	Import();
+	void	ErrorPrint(const char *error_msg);
+	
 
 	static const char* sPyGetCurrentController__doc__;
 	static PyObject* sPyGetCurrentController(PyObject* self);
@@ -78,19 +96,20 @@ class SCA_PythonController : public SCA_IController
 	static PyObject* sPyAddActiveActuator(PyObject* self, 
 										  PyObject* args);
 	static SCA_IActuator* LinkedActuatorFromPy(PyObject *value);
+		
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 		
 	KX_PYMETHOD_O(SCA_PythonController,Activate);
 	KX_PYMETHOD_O(SCA_PythonController,DeActivate);
-	KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetSensors);
-	KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetActuators);
-	KX_PYMETHOD_DOC_O(SCA_PythonController,GetSensor);
-	KX_PYMETHOD_DOC_O(SCA_PythonController,GetActuator);
 	KX_PYMETHOD_O(SCA_PythonController,SetScript);
 	KX_PYMETHOD_NOARGS(SCA_PythonController,GetScript);
-	KX_PYMETHOD_NOARGS(SCA_PythonController,GetState);
+
+	
+	static PyObject*	pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 	
 
 };
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
index 7af116fad992b1f5cc17d031e9fadf374cabafe1..2db871c77cfd2b0cdaf2f024629161e5652e4fb8 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
@@ -78,8 +78,6 @@ CValue* SCA_RandomActuator::GetReplica()
 	SCA_RandomActuator* replica = new SCA_RandomActuator(*this);
 	// replication just copy the m_base pointer => common random generator
 	replica->ProcessReplica();
-	CValue::AddDataToReplica(replica);
-
 	return replica;
 }
 
@@ -312,12 +310,17 @@ void SCA_RandomActuator::enforceConstraints() {
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_RandomActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_RandomActuator",
-	sizeof(SCA_RandomActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -341,12 +344,12 @@ PyParentObject SCA_RandomActuator::Parents[] = {
 PyMethodDef SCA_RandomActuator::Methods[] = {
 	//Deprecated functions ------>
 	{"setSeed",         (PyCFunction) SCA_RandomActuator::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc},
-	{"getSeed",         (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_VARARGS, (PY_METHODCHAR)GetSeed_doc},
-	{"getPara1",        (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_VARARGS, (PY_METHODCHAR)GetPara1_doc},
-	{"getPara2",        (PyCFunction) SCA_RandomActuator::sPyGetPara2, METH_VARARGS, (PY_METHODCHAR)GetPara2_doc},
-	{"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_VARARGS, (PY_METHODCHAR)GetDistribution_doc},
+	{"getSeed",         (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_NOARGS, (PY_METHODCHAR)GetSeed_doc},
+	{"getPara1",        (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_NOARGS, (PY_METHODCHAR)GetPara1_doc},
+	{"getPara2",        (PyCFunction) SCA_RandomActuator::sPyGetPara2, METH_NOARGS, (PY_METHODCHAR)GetPara2_doc},
+	{"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_NOARGS, (PY_METHODCHAR)GetDistribution_doc},
 	{"setProperty",     (PyCFunction) SCA_RandomActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
-	{"getProperty",     (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
+	{"getProperty",     (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_NOARGS, (PY_METHODCHAR)GetProperty_doc},
 	//<----- Deprecated
 	KX_PYMETHODTABLE(SCA_RandomActuator, setBoolConst),
 	KX_PYMETHODTABLE_NOARGS(SCA_RandomActuator, setBoolUniform),
@@ -386,24 +389,22 @@ int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_
 		act->m_base->SetSeed(ival);
 		return 0;
 	} else {
-		PyErr_SetString(PyExc_TypeError, "expected an integer");
+		PyErr_SetString(PyExc_TypeError, "actuator.seed = int: Random Actuator, expected an integer");
 		return 1;
 	}
 }
 
 PyObject* SCA_RandomActuator::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* SCA_RandomActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int SCA_RandomActuator::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 /* 1. setSeed                                                            */
@@ -413,10 +414,10 @@ const char SCA_RandomActuator::SetSeed_doc[] =
 "\tSet the initial seed of the generator. Equal seeds produce\n"
 "\tequal series. If the seed is 0, the generator will produce\n"
 "\tthe same value on every call.\n";
-PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomActuator::PySetSeed(PyObject* args) {
 	ShowDeprecationWarning("setSeed()", "the seed property");
 	long seedArg;
-	if(!PyArg_ParseTuple(args, "i", &seedArg)) {
+	if(!PyArg_ParseTuple(args, "i:setSeed", &seedArg)) {
 		return NULL;
 	}
 	
@@ -429,7 +430,8 @@ const char SCA_RandomActuator::GetSeed_doc[] =
 "getSeed()\n"
 "\tReturns the initial seed of the generator. Equal seeds produce\n"
 "\tequal series.\n";
-PyObject* SCA_RandomActuator::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomActuator::PyGetSeed()
+{
 	ShowDeprecationWarning("getSeed()", "the seed property");
 	return PyInt_FromLong(m_base->GetSeed());
 }
@@ -440,7 +442,8 @@ const char SCA_RandomActuator::GetPara1_doc[] =
 "\tReturns the first parameter of the active distribution. Refer\n"
 "\tto the documentation of the generator types for the meaning\n"
 "\tof this value.";
-PyObject* SCA_RandomActuator::PyGetPara1(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomActuator::PyGetPara1()
+{
 	ShowDeprecationWarning("getPara1()", "the para1 property");
 	return PyFloat_FromDouble(m_parameter1);
 }
@@ -451,7 +454,8 @@ const char SCA_RandomActuator::GetPara2_doc[] =
 "\tReturns the first parameter of the active distribution. Refer\n"
 "\tto the documentation of the generator types for the meaning\n"
 "\tof this value.";
-PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomActuator::PyGetPara2()
+{
 	ShowDeprecationWarning("getPara2()", "the para2 property");
 	return PyFloat_FromDouble(m_parameter2);
 }
@@ -460,7 +464,8 @@ PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObjec
 const char SCA_RandomActuator::GetDistribution_doc[] = 
 "getDistribution()\n"
 "\tReturns the type of the active distribution.\n";
-PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomActuator::PyGetDistribution()
+{
 	ShowDeprecationWarning("getDistribution()", "the distribution property");
 	return PyInt_FromLong(m_distribution);
 }
@@ -471,10 +476,10 @@ const char SCA_RandomActuator::SetProperty_doc[] =
 "\t- name: string\n"
 "\tSet the property to which the random value is assigned. If the \n"
 "\tgenerator and property types do not match, the assignment is ignored.\n";
-PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomActuator::PySetProperty(PyObject* args) {
 	ShowDeprecationWarning("setProperty()", "the 'property' property");
 	char *nameArg;
-	if (!PyArg_ParseTuple(args, "s", &nameArg)) {
+	if (!PyArg_ParseTuple(args, "s:setProperty", &nameArg)) {
 		return NULL;
 	}
 
@@ -494,7 +499,8 @@ const char SCA_RandomActuator::GetProperty_doc[] =
 "getProperty(name)\n"
 "\tReturn the property to which the random value is assigned. If the \n"
 "\tgenerator and property types do not match, the assignment is ignored.\n";
-PyObject* SCA_RandomActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomActuator::PyGetProperty()
+{
 	ShowDeprecationWarning("getProperty()", "the 'property' property");
 	return PyString_FromString(m_propname);
 }
@@ -506,7 +512,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setBoolConst,
 "\tSet this generator to produce a constant boolean value.\n") 
 {
 	int paraArg;
-	if(!PyArg_ParseTuple(args, "i", &paraArg)) {
+	if(!PyArg_ParseTuple(args, "i:setBoolConst", &paraArg)) {
 		return NULL;
 	}
 	
@@ -532,7 +538,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setBoolBernouilli,
 "\tReturn false value * 100%% of the time.\n")
 {
 	float paraArg;
-	if(!PyArg_ParseTuple(args, "f", &paraArg)) {
+	if(!PyArg_ParseTuple(args, "f:setBoolBernouilli", &paraArg)) {
 		return NULL;
 	}
 	
@@ -548,7 +554,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setIntConst,
 "\tAlways return value\n") 
 {
 	int paraArg;
-	if(!PyArg_ParseTuple(args, "i", &paraArg)) {
+	if(!PyArg_ParseTuple(args, "i:setIntConst", &paraArg)) {
 		return NULL;
 	}
 	
@@ -566,7 +572,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setIntUniform,
 "\tupper_bound. The boundaries are included.\n")
 {
 	int paraArg1, paraArg2;
-	if(!PyArg_ParseTuple(args, "ii", &paraArg1, &paraArg2)) {
+	if(!PyArg_ParseTuple(args, "ii:setIntUniform", &paraArg1, &paraArg2)) {
 		return NULL;
 	}
 	
@@ -585,7 +591,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setIntPoisson,
 "\tnumber of tries needed to achieve succes.\n")
 {
 	float paraArg;
-	if(!PyArg_ParseTuple(args, "f", &paraArg)) {
+	if(!PyArg_ParseTuple(args, "f:setIntPoisson", &paraArg)) {
 		return NULL;
 	}
 	
@@ -601,7 +607,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatConst,
 "\tAlways return value\n")
 {
 	float paraArg;
-	if(!PyArg_ParseTuple(args, "f", &paraArg)) {
+	if(!PyArg_ParseTuple(args, "f:setFloatConst", &paraArg)) {
 		return NULL;
 	}
 	
@@ -619,7 +625,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatUniform,
 "\tupper_bound.\n")
 {
 	float paraArg1, paraArg2;
-	if(!PyArg_ParseTuple(args, "ff", &paraArg1, &paraArg2)) {
+	if(!PyArg_ParseTuple(args, "ff:setFloatUniform", &paraArg1, &paraArg2)) {
 		return NULL;
 	}
 	
@@ -638,7 +644,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatNormal,
 "\tdeviation from the mean is characterized by standard_deviation.\n")
 {
 	float paraArg1, paraArg2;
-	if(!PyArg_ParseTuple(args, "ff", &paraArg1, &paraArg2)) {
+	if(!PyArg_ParseTuple(args, "ff:setFloatNormal", &paraArg1, &paraArg2)) {
 		return NULL;
 	}
 	
@@ -656,7 +662,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatNegativeExponential,
 "\tis characterized by half_life.\n")
 {
 	float paraArg;
-	if(!PyArg_ParseTuple(args, "f", &paraArg)) {
+	if(!PyArg_ParseTuple(args, "f:setFloatNegativeExponential", &paraArg)) {
 		return NULL;
 	}
 	
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h
index fbafbb69c017b6c5b75a9d4c99436374afa211ff..310e8a7fbf9adf8cf56efaf366cb33dd1f579025 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.h
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.h
@@ -97,19 +97,20 @@ class SCA_RandomActuator : public SCA_IActuator
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	static PyObject* pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
 	static int pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 
 	// Deprecated methods ----->
-	KX_PYMETHOD_DOC(SCA_RandomActuator,SetSeed);
-	KX_PYMETHOD_DOC(SCA_RandomActuator,GetSeed);
-	KX_PYMETHOD_DOC(SCA_RandomActuator,GetPara1);
-	KX_PYMETHOD_DOC(SCA_RandomActuator,GetPara2);
-	KX_PYMETHOD_DOC(SCA_RandomActuator,GetDistribution);
-	KX_PYMETHOD_DOC(SCA_RandomActuator,SetProperty);
-	KX_PYMETHOD_DOC(SCA_RandomActuator,GetProperty);
+	KX_PYMETHOD_DOC_VARARGS(SCA_RandomActuator,SetSeed);
+	KX_PYMETHOD_DOC_NOARGS(SCA_RandomActuator,GetSeed);
+	KX_PYMETHOD_DOC_NOARGS(SCA_RandomActuator,GetPara1);
+	KX_PYMETHOD_DOC_NOARGS(SCA_RandomActuator,GetPara2);
+	KX_PYMETHOD_DOC_NOARGS(SCA_RandomActuator,GetDistribution);
+	KX_PYMETHOD_DOC_VARARGS(SCA_RandomActuator,SetProperty);
+	KX_PYMETHOD_DOC_NOARGS(SCA_RandomActuator,GetProperty);
 	// <-----
 
 	KX_PYMETHOD_DOC_VARARGS(SCA_RandomActuator, setBoolConst);
diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp
index 156478d866d577ac2027760d2bfaa507bccd1548..976597aa8122afbc4b7dc0183f3afbe23babc8a8 100644
--- a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp
@@ -50,9 +50,10 @@ SCA_RandomEventManager::SCA_RandomEventManager(class SCA_LogicManager* logicmgr)
 
 void SCA_RandomEventManager::NextFrame()
 {
-	for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+	SG_DList::iterator<SCA_ISensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
 	{
-		(*i)->Activate(m_logicmgr, NULL);
+		(*it)->Activate(m_logicmgr);
 	}
 }
 
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
index 84a9ef95e843333a708edb95d6b87978a79326eb..1581a29480ec411922487a47a1f496c997ac7d11 100644
--- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
@@ -76,7 +76,7 @@ CValue* SCA_RandomSensor::GetReplica()
 	CValue* replica = new SCA_RandomSensor(*this);
 	// replication copies m_basegenerator pointer => share same generator
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -89,7 +89,7 @@ bool SCA_RandomSensor::IsPositiveTrigger()
 }
 
 
-bool SCA_RandomSensor::Evaluate(CValue* event)
+bool SCA_RandomSensor::Evaluate()
 {
     /* Random generator is the generator from Line 25 of Table 1 in          */
     /* [KNUTH 1981, The Art of Computer Programming Vol. 2                   */
@@ -127,12 +127,17 @@ bool SCA_RandomSensor::Evaluate(CValue* event)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_RandomSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_RandomSensor",
-	sizeof(SCA_RandomSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -154,46 +159,31 @@ PyParentObject SCA_RandomSensor::Parents[] = {
 };
 
 PyMethodDef SCA_RandomSensor::Methods[] = {
+	//Deprecated functions ----->
 	{"setSeed",     (PyCFunction) SCA_RandomSensor::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc},
-	{"getSeed",     (PyCFunction) SCA_RandomSensor::sPyGetSeed, METH_VARARGS, (PY_METHODCHAR)GetSeed_doc},
-	{"getLastDraw", (PyCFunction) SCA_RandomSensor::sPyGetLastDraw, METH_VARARGS, (PY_METHODCHAR)GetLastDraw_doc},
+	{"getSeed",     (PyCFunction) SCA_RandomSensor::sPyGetSeed, METH_NOARGS, (PY_METHODCHAR)GetSeed_doc},
+	{"getLastDraw", (PyCFunction) SCA_RandomSensor::sPyGetLastDraw, METH_NOARGS, (PY_METHODCHAR)GetLastDraw_doc},
+	//<----- Deprecated
 	{NULL,NULL} //Sentinel
 };
 
 PyAttributeDef SCA_RandomSensor::Attributes[] = {
 	KX_PYATTRIBUTE_BOOL_RO("lastDraw",SCA_RandomSensor,m_lastdraw),
+	KX_PYATTRIBUTE_RW_FUNCTION("seed", SCA_RandomSensor, pyattr_get_seed, pyattr_set_seed),
 	{NULL} //Sentinel
 };
 
 PyObject* SCA_RandomSensor::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
-	
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str,"seed")) {
-		return PyInt_FromLong(m_basegenerator->GetSeed());
-	}
 	py_getattro_up(SCA_ISensor);
 }
 
+PyObject* SCA_RandomSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 int SCA_RandomSensor::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str,"seed")) {
-		if (PyInt_Check(value))	{
-			int ival = PyInt_AsLong(value);
-			m_basegenerator->SetSeed(ival);
-			return 0;
-		} else {
-			PyErr_SetString(PyExc_TypeError, "expected an integer");
-			return 1;
-		}
-	}
-	return SCA_ISensor::py_setattro(attr, value);
+	py_setattro_up(SCA_ISensor);
 }
 
 /* 1. setSeed                                                            */
@@ -203,10 +193,10 @@ const char SCA_RandomSensor::SetSeed_doc[] =
 "\tSet the initial seed of the generator. Equal seeds produce\n"
 "\tequal series. If the seed is 0, the generator will produce\n"
 "\tthe same value on every call.\n";
-PyObject* SCA_RandomSensor::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomSensor::PySetSeed(PyObject* args) {
 	ShowDeprecationWarning("setSeed()", "the seed property");
 	long seedArg;
-	if(!PyArg_ParseTuple(args, "i", &seedArg)) {
+	if(!PyArg_ParseTuple(args, "i:setSeed", &seedArg)) {
 		return NULL;
 	}
 	
@@ -220,7 +210,7 @@ const char SCA_RandomSensor::GetSeed_doc[] =
 "getSeed()\n"
 "\tReturns the initial seed of the generator. Equal seeds produce\n"
 "\tequal series.\n";
-PyObject* SCA_RandomSensor::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomSensor::PyGetSeed() {
 	ShowDeprecationWarning("getSeed()", "the seed property");
 	return PyInt_FromLong(m_basegenerator->GetSeed());
 }
@@ -229,9 +219,27 @@ PyObject* SCA_RandomSensor::PyGetSeed(PyObject* self, PyObject* args, PyObject*
 const char SCA_RandomSensor::GetLastDraw_doc[] = 
 "getLastDraw()\n"
 "\tReturn the last value that was drawn.\n";
-PyObject* SCA_RandomSensor::PyGetLastDraw(PyObject* self, PyObject* args, PyObject* kwds) {
+PyObject* SCA_RandomSensor::PyGetLastDraw() {
 	ShowDeprecationWarning("getLastDraw()", "the lastDraw property");
 	return PyInt_FromLong(m_lastdraw);
 }
 
+
+PyObject* SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	SCA_RandomSensor* self= static_cast<SCA_RandomSensor*>(self_v);
+	return PyInt_FromLong(self->m_basegenerator->GetSeed());
+}
+
+int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	SCA_RandomSensor* self= static_cast<SCA_RandomSensor*>(self_v);
+	if (!PyInt_Check(value)) {
+		PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer");
+		return -1;
+	}
+	self->m_basegenerator->SetSeed(PyInt_AsLong(value));
+	return 0;
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h
index 39d072dd3161758d91452fb35eb3efcfbb203f3c..27b41841f0bdb2f7a1d67008ee77aef7c1b7ebb7 100644
--- a/source/gameengine/GameLogic/SCA_RandomSensor.h
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.h
@@ -52,7 +52,7 @@ public:
   					PyTypeObject* T=&Type);
 	virtual ~SCA_RandomSensor();
 	virtual CValue* GetReplica();
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool IsPositiveTrigger();
 	virtual void Init();
 
@@ -61,14 +61,18 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	/* 1. setSeed                                                            */
-	KX_PYMETHOD_DOC(SCA_RandomSensor,SetSeed);
+	KX_PYMETHOD_DOC_VARARGS(SCA_RandomSensor,SetSeed);
 	/* 2. getSeed                                                            */
-	KX_PYMETHOD_DOC(SCA_RandomSensor,GetSeed);
-	/* 3. getSeed                                                            */
-	KX_PYMETHOD_DOC(SCA_RandomSensor,GetLastDraw);
+	KX_PYMETHOD_DOC_NOARGS(SCA_RandomSensor,GetSeed);
+	/* 3. getLastDraw                                                        */
+	KX_PYMETHOD_DOC_NOARGS(SCA_RandomSensor,GetLastDraw);
+	
+	static PyObject*	pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 
 };
 
diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
index b7fadd3d62cdd600fba78745bbf2220d03746e80..911ea772bef88c147edf6a1b1b673f06d1d35075 100644
--- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp
@@ -52,7 +52,7 @@ SCA_TimeEventManager::SCA_TimeEventManager(SCA_LogicManager* logicmgr)
 SCA_TimeEventManager::~SCA_TimeEventManager()
 {
 	for (vector<CValue*>::iterator it = m_timevalues.begin();
-			!(it == m_timevalues.end()); it++)
+			!(it == m_timevalues.end()); ++it)
 	{
 		(*it)->Release();
 	}	
@@ -80,7 +80,7 @@ void SCA_TimeEventManager::NextFrame(double curtime, double fixedtime)
 		
 		// update sensors, but ... need deltatime !
 		for (vector<CValue*>::iterator it = m_timevalues.begin();
-		!(it == m_timevalues.end()); it++)
+		!(it == m_timevalues.end()); ++it)
 		{
 			float newtime = (*it)->GetNumber() + fixedtime;
 			floatval->SetFloat(newtime);
@@ -104,7 +104,7 @@ void SCA_TimeEventManager::AddTimeProperty(CValue* timeval)
 void SCA_TimeEventManager::RemoveTimeProperty(CValue* timeval)
 {
 	for (vector<CValue*>::iterator it = m_timevalues.begin();
-			!(it == m_timevalues.end()); it++)
+			!(it == m_timevalues.end()); ++it)
 	{
 		if ((*it) == timeval)
 		{
diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp
index 10757e1c9355768fad7f4586fa501aec5aed0e2f..aee8e26c21a34f5ab962ecff15e3faa22716c889 100644
--- a/source/gameengine/GameLogic/SCA_XNORController.cpp
+++ b/source/gameengine/GameLogic/SCA_XNORController.cpp
@@ -66,7 +66,7 @@ void SCA_XNORController::Trigger(SCA_LogicManager* logicmgr)
 	!(is==m_linkedsensors.end());is++)
 	{
 		SCA_ISensor* sensor = *is;
-		if (sensor->IsPositiveTrigger())
+		if (sensor->GetState())
 		{
 			if (sensorresult == false)
 			{
@@ -77,19 +77,12 @@ void SCA_XNORController::Trigger(SCA_LogicManager* logicmgr)
 		}
 	}
 
-	CValue* newevent = new CBoolValue(sensorresult);
-
 	for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
 	!(i==m_linkedactuators.end());i++)
 	{
-		SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
-		logicmgr->AddActiveActuator(actua,newevent);
+		SCA_IActuator* actua = *i;
+		logicmgr->AddActiveActuator(actua,sensorresult);
 	}
-
-	// every actuator that needs the event, has a it's own reference to it now so
-	// release it (so to be clear: if there is no actuator, it's deleted right now)
-	newevent->Release();
-
 }
 
 
@@ -98,7 +91,7 @@ CValue* SCA_XNORController::GetReplica()
 {
 	CValue* replica = new SCA_XNORController(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -111,12 +104,17 @@ CValue* SCA_XNORController::GetReplica()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_XNORController::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_XNORController",
-	sizeof(SCA_XNORController),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -149,4 +147,8 @@ PyObject* SCA_XNORController::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_IController);
 }
 
+PyObject* SCA_XNORController::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IController);
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h
index c992d5f183485d6d2628650f3383d0cc2ba63fe1..4aad5763cb02629780600a994fd19c98d3317fae 100644
--- a/source/gameengine/GameLogic/SCA_XNORController.h
+++ b/source/gameengine/GameLogic/SCA_XNORController.h
@@ -49,6 +49,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 
 };
 
diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp
index d2290fe207a4a32b4737f680f080c04eeb9cfcde..5afb3a750f5662d5fc67116d2336a4f77fa16c1d 100644
--- a/source/gameengine/GameLogic/SCA_XORController.cpp
+++ b/source/gameengine/GameLogic/SCA_XORController.cpp
@@ -66,7 +66,7 @@ void SCA_XORController::Trigger(SCA_LogicManager* logicmgr)
 	!(is==m_linkedsensors.end());is++)
 	{
 		SCA_ISensor* sensor = *is;
-		if (sensor->IsPositiveTrigger())
+		if (sensor->GetState())
 		{
 			if (sensorresult == true)
 			{
@@ -77,19 +77,12 @@ void SCA_XORController::Trigger(SCA_LogicManager* logicmgr)
 		}
 	}
 	
-	CValue* newevent = new CBoolValue(sensorresult);
-
 	for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin();
 	!(i==m_linkedactuators.end());i++)
 	{
-		SCA_IActuator* actua = *i;//m_linkedactuators.at(i);
-		logicmgr->AddActiveActuator(actua,newevent);
+		SCA_IActuator* actua = *i;
+		logicmgr->AddActiveActuator(actua,sensorresult);
 	}
-
-	// every actuator that needs the event, has a it's own reference to it now so
-	// release it (so to be clear: if there is no actuator, it's deleted right now)
-	newevent->Release();
-
 }
 
 
@@ -98,7 +91,7 @@ CValue* SCA_XORController::GetReplica()
 {
 	CValue* replica = new SCA_XORController(*this);
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -111,12 +104,17 @@ CValue* SCA_XORController::GetReplica()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject SCA_XORController::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"SCA_XORController",
-	sizeof(SCA_XORController),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -149,4 +147,8 @@ PyObject* SCA_XORController::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_IController);
 }
 
+PyObject* SCA_XORController::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IController);
+}
+
 /* eof */
diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h
index 065b31fd90197ab74296d06d30fe1e73ac4042ac..feb9f2ed07c2a3e9f03f892dbdf8ab78c8df0fd2 100644
--- a/source/gameengine/GameLogic/SCA_XORController.h
+++ b/source/gameengine/GameLogic/SCA_XORController.h
@@ -49,6 +49,7 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 
 };
 
diff --git a/source/gameengine/GameLogic/SConscript b/source/gameengine/GameLogic/SConscript
index ebf225f728f46a96c76ad3a86c05300c787799ff..aadc415429878242e5128371e4ff1d16be52efa6 100644
--- a/source/gameengine/GameLogic/SConscript
+++ b/source/gameengine/GameLogic/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.cpp') + env.Glob('Joystick/*.cpp')
 
 incs = '. #/source/kernel/gen_system #/intern/string'
 incs += ' #/source/gameengine/Expressions #/intern/moto/include'
-incs += ' #/source/gameengine/Rasterizer'
+incs += ' #/source/gameengine/Rasterizer #/source/gameengine/SceneGraph'
 
 incs += ' ' + env['BF_PYTHON_INC']
 
diff --git a/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.cpp b/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.cpp
index 474df9276a744e1ff2edc889b11f0481e6eda80d..472ff58039249c87e39df10f56cb98a5d2dfd716 100644
--- a/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.cpp
@@ -42,7 +42,7 @@ void GPC_KeyboardDevice::NextFrame()
 
 	// Now convert justpressed key events into regular (active) keyevents
 	int previousTable = 1-m_currentTable;
-	for (int keyevent= KX_BEGINKEY; keyevent< KX_ENDKEY;keyevent++)
+	for (int keyevent= KX_BEGINKEY; keyevent<= KX_ENDKEY;keyevent++)
 	{
 		SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][keyevent];
 		if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED ||
@@ -69,7 +69,7 @@ bool GPC_KeyboardDevice::ConvertEvent(int incode, int val)
 	KX_EnumInputs kxevent = this->ToNative(incode);
 
 	// only process it, if it's a key
-	if (kxevent >= KX_BEGINKEY && kxevent < KX_ENDKEY)
+	if (kxevent >= KX_BEGINKEY && kxevent <= KX_ENDKEY)
 	{
 		int previousTable = 1-m_currentTable;
 
@@ -114,9 +114,7 @@ bool GPC_KeyboardDevice::ConvertEvent(int incode, int val)
 				}
 			}
 		}
-	} else if(kxevent==KX_ENDKEY) {
-		exit(1);
-	}	
+	}
 	return result;
 }
 
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
index eafdb8a96bb21031166b84da040505866e2cc6b0..1a0d985a864d80152a23e0d6a0bf04bb17639a17 100644
--- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
@@ -76,8 +76,8 @@ void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty)
 {
 	m_clientobject = NULL;
 	m_lastlightlayer = -1;
-	m_lastlighting = false;
 	m_lastauxinfo = NULL;
+	m_lastlighting = true; /* force disable in DisableOpenGLLights() */
 	DisableOpenGLLights();
 }
 
diff --git a/source/gameengine/GamePlayer/common/windows/Makefile b/source/gameengine/GamePlayer/common/windows/Makefile
index b0fb25f35b87f61ef9bca132270287f3b14eb1b0..f35642f965134e4ff57d617790107ecca3fb1416 100644
--- a/source/gameengine/GamePlayer/common/windows/Makefile
+++ b/source/gameengine/GamePlayer/common/windows/Makefile
@@ -50,6 +50,7 @@ CPPFLAGS += -I$(NAN_MOTO)/include
 CPPFLAGS += -I$(NAN_STRING)/include    
 CPPFLAGS += -I$(NAN_BMFONT)/include
 CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
+CPPFLAGS += -I$(NAN_GLEW)/include
 
 # Blender stuff
 CPPFLAGS += -I$(SRCHOME)/blender/blenkernel
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index beb74add94635bcdf4b6fa6712bd15b17445aec3..af8b94857b9d13f717e34b0a83cf26178c696f57 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -151,7 +151,7 @@ GPG_Application::~GPG_Application(void)
 
 
 
-bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene)
+bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene, int argc, char **argv)
 {
 	bool result = false;
 
@@ -163,6 +163,10 @@ bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene)
 		m_startScene = scene;
 		result = true;
 	}
+	
+	/* Python needs these */
+	m_argc= argc;
+	m_argv= argv;
 
 	return result;
 }
@@ -208,7 +212,7 @@ static LRESULT CALLBACK screenSaverWindowProc(HWND hwnd, UINT uMsg, WPARAM wPara
 
 BOOL CALLBACK findGhostWindowHWNDProc(HWND hwnd, LPARAM lParam)
 {
-	GHOST_IWindow *p = (GHOST_IWindow*) GetWindowLong(hwnd, GWL_USERDATA);
+	GHOST_IWindow *p = (GHOST_IWindow*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
 	BOOL ret = TRUE;
 	if (p == ghost_window_to_find)
 	{
@@ -292,8 +296,8 @@ bool GPG_Application::startScreenSaverFullScreen(
 		if (ghost_hwnd != NULL)
 		{
 			GetCursorPos(&scr_save_mouse_pos);
-			ghost_wnd_proc = (WNDPROC) GetWindowLong(ghost_hwnd, GWL_WNDPROC);
-			SetWindowLong(ghost_hwnd,GWL_WNDPROC, (LONG) screenSaverWindowProc);
+			ghost_wnd_proc = (WNDPROC) GetWindowLongPtr(ghost_hwnd, GWLP_WNDPROC);
+			SetWindowLongPtr(ghost_hwnd,GWLP_WNDPROC, (uintptr_t) screenSaverWindowProc);
 		}
 	}
 	return ret;
@@ -681,7 +685,7 @@ bool GPG_Application::startEngine(void)
 		
 		
 		// some python things
-		PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
+		PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest, m_maggie, m_argc, m_argv);
 		m_ketsjiengine->SetPythonDictionary(dictionaryobject);
 		initRasterizer(m_rasterizer, m_canvas);
 		PyObject *gameLogic = initGameLogic(m_ketsjiengine, startscene);
@@ -689,6 +693,8 @@ bool GPG_Application::startEngine(void)
 		initGameKeys();
 		initPythonConstraintBinding();
 		initMathutils();
+		initGeometry();
+		initBGL();
 #ifdef WITH_FFMPEG
         initVideoTexture();
 #endif
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h
index 38408f919b4217901466b8bed2d3cef6f12f6094..845686f5770c7417fe233e5cb26b7bd1f9c0f068 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.h
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h
@@ -58,7 +58,7 @@ public:
 	GPG_Application(GHOST_ISystem* system);
 	~GPG_Application(void);
 
-			bool SetGameEngineData(struct Main* maggie, struct Scene* scene);
+			bool SetGameEngineData(struct Main* maggie, struct Scene* scene, int argc, char** argv);
 			bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight,
 			const bool stereoVisual, const int stereoMode);
 			bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode);
@@ -154,5 +154,9 @@ protected:
 	 */
 	char* m_pyGlobalDictString;
 	int m_pyGlobalDictString_Length;
+	
+	/* argc and argv need to be passed on to python */
+	int		m_argc;
+	char**	m_argv;
 };
 
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index a41446ad88c4baccab263e625d4126b884c4cf58..7c47d2353a6befcbabf710d6bcb06f468387e392 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -206,6 +206,8 @@ void usage(const char* program)
 	printf("       blender_material               0         Enable material settings\n");
 	printf("       ignore_deprecation_warnings    1         Ignore deprecation warnings\n");
 	printf("\n");
+	printf("  - : all arguments after this are ignored, allowing python to access them from sys.argv\n");
+	printf("\n");
 	printf("example: %s -w 320 200 10 10 -g noaudio c:\\loadtest.blend\n", program);
 	printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program);
 }
@@ -293,6 +295,7 @@ static BlendFileData *load_game_data(char *progname, char *filename = NULL, char
 int main(int argc, char** argv)
 {
 	int i;
+	int argc_py_clamped= argc; /* use this so python args can be added after ' - ' */
 	bool error = false;
 	SYS_SystemHandle syshandle = SYS_GetSystem();
 	bool fullScreen = false;
@@ -393,6 +396,12 @@ int main(int argc, char** argv)
 #endif
 		if (argv[i][0] == '-')
 		{
+			/* ignore all args after " - ", allow python to have own args */
+			if (argv[i][1]=='\0') {
+				argc_py_clamped= i;
+				break;
+			}
+			
 			switch (argv[i][1])
 			{
 			case 'g':
@@ -596,7 +605,7 @@ int main(int argc, char** argv)
 				char pathname[FILE_MAXDIR + FILE_MAXFILE];
 				char *titlename;
 
-				get_filename(argc, argv, filename);
+				get_filename(argc_py_clamped, argv, filename);
 				if(filename[0])
 					BLI_convertstringcwd(filename);
 				
@@ -691,14 +700,14 @@ int main(int argc, char** argv)
 						}
 						
 						//					GPG_Application app (system, maggie, startscenename);
-						app.SetGameEngineData(maggie, scene);
+						app.SetGameEngineData(maggie, scene, argc, argv); /* this argc cant be argc_py_clamped, since python uses it */
 						
 						BLI_strncpy(pathname, maggie->name, sizeof(pathname));
 						BLI_strncpy(G.sce, maggie->name, sizeof(G.sce));
+						setGamePythonPath(G.sce);
 
 						if (firstTimeRunning)
 						{
-							setGamePythonPath(G.sce);
 							firstTimeRunning = false;
 
 							if (fullScreen)
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index 3df483b05987cba9105b2f3cc46e2c999f8a1f9a..a0a61d01bb29a158ac5f06fd4c2dbcf854d45639 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -20,41 +20,33 @@ BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lig
 :
 	mScene(scene),
 	mMat(ma),
-	mLightLayer(lightlayer)
+	mLightLayer(lightlayer),
+	mGPUMat(NULL)
 {
 	mBlenderScene = scene->GetBlenderScene();
 	mBlendMode = GPU_BLEND_SOLID;
 
-	if(mMat)
-		GPU_material_from_blender(mBlenderScene, mMat);
+	ReloadMaterial();
 }
 
 BL_BlenderShader::~BL_BlenderShader()
 {
-	if(mMat && GPU_material_from_blender(mBlenderScene, mMat))
-		GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat));
+	if(mGPUMat)
+		GPU_material_unbind(mGPUMat);
 }
 
-bool BL_BlenderShader::Ok()
+void BL_BlenderShader::ReloadMaterial()
 {
-	return VerifyShader();
-}
-
-bool BL_BlenderShader::VerifyShader()
-{
-	if(mMat)
-		return (GPU_material_from_blender(mBlenderScene, mMat) != 0);
-	else
-		return false;
+	mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL;
 }
 
 void BL_BlenderShader::SetProg(bool enable, double time)
 {
 	if(VerifyShader()) {
 		if(enable)
-			GPU_material_bind(GPU_material_from_blender(mBlenderScene, mMat), mLightLayer, mBlenderScene->lay, time);
+			GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time);
 		else
-			GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat));
+			GPU_material_unbind(mGPUMat);
 	}
 }
 
@@ -66,7 +58,7 @@ int BL_BlenderShader::GetAttribNum()
 	if(!VerifyShader())
 		return enabled;
 
-	GPU_material_vertex_attributes(GPU_material_from_blender(mBlenderScene, mMat), &attribs);
+	GPU_material_vertex_attributes(mGPUMat, &attribs);
 
     for(i = 0; i < attribs.totlayer; i++)
 		if(attribs.layer[i].glindex+1 > enabled)
@@ -89,7 +81,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat)
 	if(!VerifyShader())
 		return;
 	
-	gpumat = GPU_material_from_blender(mBlenderScene, mMat);
+	gpumat = mGPUMat;
 
 	if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
 		GPU_material_vertex_attributes(gpumat, &attribs);
@@ -131,7 +123,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
 	float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4];
 	GPUMaterial *gpumat;
 
-	gpumat = GPU_material_from_blender(mBlenderScene, mMat);
+	gpumat = mGPUMat;
 
 	if(!gpumat || !GPU_material_bound(gpumat))
 		return;
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h
index 5c1f59f94ade694e319e8bc791db6ede04299721..9af53bfc86323f3996ca8898ac00b6aa1608ea97 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.h
+++ b/source/gameengine/Ketsji/BL_BlenderShader.h
@@ -32,19 +32,28 @@ private:
 	struct Material	*mMat;
 	int				mLightLayer;
 	int				mBlendMode;
+	GPUMaterial     *mGPUMat;
 
-	bool			VerifyShader();
+	bool			VerifyShader() 
+	{
+		return (NULL != mGPUMat);
+	}
 
 public:
 	BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer);
 	virtual ~BL_BlenderShader();
 
-	bool				Ok();
+	bool				Ok()
+	{
+		// same as VerifyShared
+		return (NULL != mGPUMat);
+	}
 	void				SetProg(bool enable, double time=0.0);
 
 	int GetAttribNum();
 	void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat);
 	void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty);
+	void ReloadMaterial();
 	int GetBlendMode();
 
 	bool Equals(BL_BlenderShader *blshader);
diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp
index 7e3d6984f19dcf7723ab9f145c2ec12da9250312..c63b9d5530640b3d3af212735d09dfedc6ef86b2 100644
--- a/source/gameengine/Ketsji/BL_Material.cpp
+++ b/source/gameengine/Ketsji/BL_Material.cpp
@@ -27,6 +27,11 @@ int getNumTexChannels( Material *mat )
 }
 
 BL_Material::BL_Material()
+{
+	Initialize();
+}
+
+void BL_Material::Initialize()
 {
 	rgb[0] = 0;
 	rgb[1] = 0;
@@ -52,7 +57,7 @@ BL_Material::BL_Material()
 	mode = 0;
 	material = 0;
 	tface = 0;
-	material_index = 0;
+	materialindex = 0;
 	amb=0.5f;
 	num_enabled = 0;
 	num_users = 1;
diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h
index 0eaa234566c245a58faea5b709ce5883f5a38959..4f572f9589186dfc11303cc2f7f1a9ce123f8838 100644
--- a/source/gameengine/Ketsji/BL_Material.h
+++ b/source/gameengine/Ketsji/BL_Material.h
@@ -44,6 +44,7 @@ private:
 public:
 	// -----------------------------------
 	BL_Material();
+	void Initialize();
 
 	int IdMode;
 	unsigned int ras_mode;
@@ -54,6 +55,7 @@ public:
 	int tile,tilexrep[MAXTEX],tileyrep[MAXTEX];
 	STR_String matname;
 	STR_String mtexname[MAXTEX];
+	int materialindex;
 
 	float matcolor[4];
 	float speccolor[3];
@@ -68,8 +70,6 @@ public:
 	int	 mode;
 	int num_enabled;
 	
-	int material_index;
-
 	BL_Mapping	mapping[MAXTEX];
 	STR_String	imageId[MAXTEX];
 
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index 279721b48402c373f5ab67caae0749e9da07ee4e..c5c517c8a65390e35114a1d93e770f9c171338ec 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -734,6 +734,10 @@ PyObject* BL_Shader::py_getattro(PyObject *attr)
 	py_getattro_up(PyObjectPlus);
 }
 
+PyObject* BL_Shader::py_getattro_dict() {
+	py_getattro_dict_up(PyObjectPlus);
+}
+
 
 PyMethodDef BL_Shader::Methods[] = 
 {
@@ -772,12 +776,17 @@ PyAttributeDef BL_Shader::Attributes[] = {
 };
 
 PyTypeObject BL_Shader::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"BL_Shader",
-		sizeof(BL_Shader),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -807,7 +816,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProg
 	}
 	char *v,*f;
 	int apply=0;
-	if( PyArg_ParseTuple(args, "ssi", &v, &f, &apply) )
+	if( PyArg_ParseTuple(args, "ssi:setSource", &v, &f, &apply) )
 	{
 		vertProg = v;
 		fragProg = f;
@@ -858,7 +867,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
 		Py_RETURN_NONE;
 	}
 	if(mShader==0) {
-		PyErr_Format(PyExc_TypeError, "invalid shader object");
+		PyErr_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, invalid shader object");
 		return NULL;
 	}
 	int stat = 0;
@@ -890,7 +899,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
 
 	const char *uniform="";
 	int index=-1;
-	if(PyArg_ParseTuple(args, "si", &uniform, &index)) 
+	if(PyArg_ParseTuple(args, "si:setSampler", &uniform, &index)) 
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1) {
@@ -915,7 +924,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
 KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" )
 {
 	int pass = 1;
-	if(!PyArg_ParseTuple(args, "i", &pass))
+	if(!PyArg_ParseTuple(args, "i:setNumberOfPasses", &pass))
 		return NULL;
 
 	mPass = 1;
@@ -931,7 +940,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
 
 	const char *uniform="";
 	float value=0;
-	if(PyArg_ParseTuple(args, "sf", &uniform, &value ))
+	if(PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value ))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -955,7 +964,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
 	}
 	const char *uniform="";
 	float array[2]={ 0,0 };
-	if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] ))
+	if(PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] ))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -979,7 +988,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
 	}
 	const char *uniform="";
 	float array[3]={0,0,0};
-	if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2]))
+	if(PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2]))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -1004,7 +1013,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) "
 	}
 	const char *uniform="";
 	float array[4]={0,0,0,0};
-	if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3]))
+	if(PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3]))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -1028,7 +1037,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
 	}
 	const char *uniform="";
 	int value=0;
-	if(PyArg_ParseTuple(args, "si", &uniform, &value ))
+	if(PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value ))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -1052,7 +1061,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
 	}
 	const char *uniform="";
 	int array[2]={ 0,0 };
-	if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] ))
+	if(PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] ))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -1077,7 +1086,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
 
 	const char *uniform="";
 	int array[3]={0,0,0};
-	if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2]))
+	if(PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2]))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -1100,7 +1109,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) "
 	}
 	const char *uniform="";
 	int array[4]={0,0,0, 0};
-	if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] ))
+	if(PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] ))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -1125,7 +1134,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis
 	PyObject *listPtr =0;
 	float array_data[4] = {0.f,0.f,0.f,0.f};
 
-	if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
+	if(PyArg_ParseTuple(args, "sO:setUniformfv", &uniform, &listPtr))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
@@ -1175,7 +1184,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis
 					}break;
 				default:
 					{
-						PyErr_Format(PyExc_TypeError, "Invalid list size");
+						PyErr_SetString(PyExc_TypeError, "shader.setUniform4i(name, ix,iy,iz, iw): BL_Shader. invalid list size");
 						return NULL;
 					}break;
 				}
@@ -1185,7 +1194,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis
 	return NULL;
 }
 
-KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )")
+KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 or list3 or list4) )")
 {
 	if(mError) {
 		Py_RETURN_NONE;
@@ -1194,70 +1203,84 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3
 	PyObject *listPtr =0;
 	int array_data[4] = {0,0,0,0};
 
-	if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
+	if(!PyArg_ParseTuple(args, "sO:setUniformiv", &uniform, &listPtr))
+		return NULL;
+	
+	int loc = GetUniformLocation(uniform);
+	
+	if(loc == -1) {
+		PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, first string argument is not a valid uniform value");
+		return NULL;
+	}
+	
+	if(!PySequence_Check(listPtr)) {
+		PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument is not a sequence");
+		return NULL;
+	}
+	
+	unsigned int list_size = PySequence_Size(listPtr);
+	
+	for(unsigned int i=0; (i<list_size && i<4); i++)
 	{
-		int loc = GetUniformLocation(uniform);
-		if(loc != -1)
+		PyObject *item = PySequence_GetItem(listPtr, i);
+		array_data[i] = PyInt_AsLong(item);
+		Py_DECREF(item);
+	}
+	
+	if(PyErr_Occurred()) {
+		PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, one or more values in the list is not an int");
+		return NULL;
+	}
+	
+	/* Sanity checks done! */
+	
+	switch(list_size)
+	{
+	case 2:
 		{
-			if(PySequence_Check(listPtr))
-			{
-				unsigned int list_size = PySequence_Size(listPtr);
-				
-				for(unsigned int i=0; (i<list_size && i<4); i++)
-				{
-					PyObject *item = PySequence_GetItem(listPtr, i);
-					array_data[i] = PyInt_AsLong(item);
-					Py_DECREF(item);
-				}
-				switch(list_size)
-				{
-				case 2:
-					{
-						int array2[2] = { array_data[0],array_data[1]};
+			int array2[2] = { array_data[0],array_data[1]};
 #ifdef SORT_UNIFORMS
-						SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
+			SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
 #else
-						SetUniform(loc, array2, 2);						
+			SetUniform(loc, array2, 2);						
 #endif
-						Py_RETURN_NONE;
-					} break;
-				case 3:
-					{
-						int array3[3] = { array_data[0],array_data[1],array_data[2] };
+			Py_RETURN_NONE;
+		} break;
+	case 3:
+		{
+			int array3[3] = { array_data[0],array_data[1],array_data[2] };
 #ifdef SORT_UNIFORMS
-						SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
-						
+			SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
+			
 #else
-						SetUniform(loc, array3, 3);	
+			SetUniform(loc, array3, 3);	
 #endif
-						Py_RETURN_NONE;
-					}break;
-				case 4:
-					{
-						int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
+			Py_RETURN_NONE;
+		}break;
+	case 4:
+		{
+			int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
 #ifdef SORT_UNIFORMS
-						SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
-						
+			SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
+			
 #else
-						SetUniform(loc, array4, 4);	
+			SetUniform(loc, array4, 4);	
 #endif
-						Py_RETURN_NONE;
-					}break;
-				default:
-					{
-						PyErr_Format(PyExc_TypeError, "Invalid list size");
-						return NULL;
-					}break;
-				}
-			}
-		}
+			Py_RETURN_NONE;
+		}break;
+	default:
+		{
+			PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument, invalid list size, expected an int list between 2 and 4");
+			return NULL;
+		}break;
 	}
-	return NULL;
+	
+	Py_RETURN_NONE;
 }
 
 
 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
-"setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" )
+"setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)" )
 {
 	if(mError) {
 		Py_RETURN_NONE;
@@ -1273,33 +1296,38 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4,
 	const char *uniform="";
 	PyObject *matrix=0;
 	int transp=1; // MT_ is row major so transpose by default....
-	if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
-	{
-		int loc = GetUniformLocation(uniform);
-		if(loc != -1)
-		{
-			if (PyObject_IsMT_Matrix(matrix, 4))
-			{
-				MT_Matrix4x4 mat;
-				if (PyMatTo(matrix, mat))
-				{
+	
+	if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix4",&uniform, &matrix,&transp))
+		return NULL;
+
+	int loc = GetUniformLocation(uniform);
+	
+	if(loc == -1) {
+		PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, first string argument is not a valid uniform value");
+		return NULL;
+	}
+	
+	MT_Matrix4x4 mat;
+	
+	if (!PyMatTo(matrix, mat)) {
+		PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, second argument cannot be converted into a 4x4 matrix");
+		return NULL;
+	}
+	
+	/* Sanity checks done! */
+
 #ifdef SORT_UNIFORMS
-					mat.getValue(matr);
-					SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
+	mat.getValue(matr);
+	SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
 #else
-					SetUniform(loc,mat,(transp!=0));
+	SetUniform(loc,mat,(transp!=0));
 #endif
-					Py_RETURN_NONE;
-				}
-			}
-		}
-	}
-	return NULL;
+	Py_RETURN_NONE;
 }
 
 
 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
-"setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" )
+"setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)" )
 {
 	if(mError) {
 		Py_RETURN_NONE;
@@ -1314,29 +1342,32 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
 	const char *uniform="";
 	PyObject *matrix=0;
 	int transp=1; // MT_ is row major so transpose by default....
-	if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
-	{
-		int loc = GetUniformLocation(uniform);
-		if(loc != -1)
-		{
-			if (PyObject_IsMT_Matrix(matrix, 3))
-			{
-				MT_Matrix3x3 mat;
-				if (PyMatTo(matrix, mat))
-				{
+	if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3",&uniform, &matrix,&transp))
+		return NULL;
+	
+	int loc = GetUniformLocation(uniform);
+	
+	if(loc == -1) {
+		PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, first string argument is not a valid uniform value");
+		return NULL;
+	}
+	
+	
+	MT_Matrix3x3 mat;
+	
+	if (!PyMatTo(matrix, mat)) {
+		PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, second argument cannot be converted into a 3x3 matrix");
+		return NULL;
+	}
+	
+
 #ifdef SORT_UNIFORMS
-					mat.getValue(matr);
-					SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
+	mat.getValue(matr);
+	SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
 #else
-					SetUniform(loc,mat,(transp!=0));
+	SetUniform(loc,mat,(transp!=0));
 #endif
-					Py_RETURN_NONE;
-
-				}
-			}
-		}
-	}
-	return NULL;
+	Py_RETURN_NONE;
 }
 
 KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
@@ -1344,18 +1375,20 @@ KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
 	if(mError) {
 		Py_RETURN_NONE;
 	}
+	
 	int attr=0;
-	if(PyArg_ParseTuple(args, "i", &attr )) {
-		if(mShader==0) {
-			PyErr_Format(PyExc_ValueError, "invalid shader object");
-			return NULL;
-		}
-		mAttr=SHD_TANGENT;
-		glUseProgramObjectARB(mShader);
-		glBindAttribLocationARB(mShader, mAttr, "Tangent");
-		Py_RETURN_NONE;
+	
+	if(!PyArg_ParseTuple(args, "i:setAttrib", &attr ))
+		return NULL;
+	
+	if(mShader==0) {
+		PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object");
+		return NULL;
 	}
-	return NULL;
+	mAttr=SHD_TANGENT; /* What the heck is going on here - attr is just ignored??? - Campbell */
+	glUseProgramObjectARB(mShader);
+	glBindAttribLocationARB(mShader, mAttr, "Tangent");
+	Py_RETURN_NONE;
 }
 
 
@@ -1367,7 +1400,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
 
 	const char *uniform="";
 	int nloc=0;
-	if(PyArg_ParseTuple(args, "si",&uniform, &nloc))
+	if(PyArg_ParseTuple(args, "si:setUniformDef",&uniform, &nloc))
 	{
 		int loc = GetUniformLocation(uniform);
 		if(loc != -1)
diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h
index 490c0268a6d4810cbab7c825ba4569a0bdc95b60..7db40e778ae6b0a3c4cfab9b968dc032dc8bcc86 100644
--- a/source/gameengine/Ketsji/BL_Shader.h
+++ b/source/gameengine/Ketsji/BL_Shader.h
@@ -203,6 +203,8 @@ public:
 
 	// Python interface
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
+	virtual PyObject* py_repr(void) { return PyString_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); }
 
 	// -----------------------------------
 	KX_PYMETHOD_DOC( BL_Shader, setSource );
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index 58411f6d25e8197591ee7e6fdb0a53fb0744605e..abc2b44825e073e5dee7c037c43218901df0679c 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -28,13 +28,14 @@ FILE(GLOB SRC *.cpp)
 SET(SRC 
   ${SRC}
   ../../../source/blender/python/api2_2x/Mathutils.c
+  ../../../source/blender/python/api2_2x/Geometry.c
   ../../../source/blender/python/api2_2x/constant.c
   ../../../source/blender/python/api2_2x/euler.c
-  ../../../source/blender/python/api2_2x/gen_utils.c
   ../../../source/blender/python/api2_2x/matrix.c
-  ../../../source/blender/python/api2_2x/point.c
   ../../../source/blender/python/api2_2x/quat.c
   ../../../source/blender/python/api2_2x/vector.c
+  ../../../source/blender/python/api2_2x/bpy_internal_import.c
+  ../../../source/blender/python/api2_2x/BGL.c
 )
 
 SET(INC
@@ -66,7 +67,7 @@ SET(INC
   ../../../source/gameengine/Physics/Sumo
   ../../../source/gameengine/Physics/Sumo/Fuzzics/include 
   ../../../source/gameengine/Network/LoopBackNetwork
-  ../../../intern/SoundSystem 
+  ../../../intern/SoundSystem
   ../../../source/blender/misc 
   ../../../source/blender/blenloader
   ../../../source/blender/gpu
diff --git a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
index fa0ca378c6b486016e6c8805fcdfeda1a0fc04bc..999e7148039d11d9d91e48745b10333c08acd821 100644
--- a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
+++ b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
@@ -30,9 +30,11 @@ SET(INC
   .
   ../../../../source/kernel/gen_system
   ../../../../intern/string
+  ../../../../intern/moto/include
   ../../../../source/gameengine/Ketsji
   ../../../../source/gameengine/GameLogic
   ../../../../source/gameengine/Expressions
+  ../../../../source/gameengine/Scenegraph
   ../../../../source/gameengine/Network
   ${PYTHON_INC}
 )
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp
index eee8e9f6827106ca4361c6fbbdb84f95ca9a1685..738f64713b0e8a5c7ff98371cf17f0f654dbfca2 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp
@@ -61,12 +61,12 @@ void KX_NetworkEventManager::NextFrame()
 	// each frame, the logicmanager will call the network
 	// eventmanager to look for network events, and process it's
 	// 'network' sensors
-	set<class SCA_ISensor*>::iterator it;
-
-	for (it = m_sensors.begin(); !(it==m_sensors.end()); it++) {
+	SG_DList::iterator<SCA_ISensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
+	{
 //	    printf("KX_NetworkEventManager::proceed sensor %.2f\n", curtime);
 	    // process queue
-	    (*it)->Activate(m_logicmgr, NULL);
+	    (*it)->Activate(m_logicmgr);
 	}
 
 	// now a list of triggerer sensors has been built
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp
index a5fd8ebab6b672e9dec2f4b610ab1346e0b44e11..63773352d96c287f1c7b6bc0c50cc5adba7002ac 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp
@@ -75,7 +75,7 @@ bool KX_NetworkMessageActuator::Update()
 			m_toPropName,
 			GetParent()->GetName(),
 			m_subject,
-			GetParent()->GetPropertyText(m_body,""));
+			GetParent()->GetPropertyText(m_body));
 	} else
 	{
 		m_networkscene->SendMessage(
@@ -93,9 +93,6 @@ CValue* KX_NetworkMessageActuator::GetReplica()
 	    new KX_NetworkMessageActuator(*this);
 	replica->ProcessReplica();
 
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-
 	return replica;
 }
 
@@ -105,12 +102,17 @@ CValue* KX_NetworkMessageActuator::GetReplica()
 
 /* Integration hooks -------------------------------------------------- */
 PyTypeObject KX_NetworkMessageActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_NetworkMessageActuator",
-	sizeof(KX_NetworkMessageActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -154,30 +156,27 @@ PyAttributeDef KX_NetworkMessageActuator::Attributes[] = {
 };
 
 PyObject* KX_NetworkMessageActuator::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_NetworkMessageActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_NetworkMessageActuator::py_setattro(PyObject *attr, PyObject *value) {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 // Deprecated ----->
 // 1. SetToPropName
 PyObject* KX_NetworkMessageActuator::PySetToPropName(
-	PyObject* self,
 	PyObject* args,
 	PyObject* kwds)
 {
 	ShowDeprecationWarning("setToProp()", "the propName property");
     char* ToPropName;
 
-	if (PyArg_ParseTuple(args, "s", &ToPropName)) {
+	if (PyArg_ParseTuple(args, "s:setToPropName", &ToPropName)) {
 	     m_toPropName = ToPropName;
 	}
 	else {
@@ -189,14 +188,13 @@ PyObject* KX_NetworkMessageActuator::PySetToPropName(
 
 // 2. SetSubject
 PyObject* KX_NetworkMessageActuator::PySetSubject(
-	PyObject* self,
 	PyObject* args,
 	PyObject* kwds)
 {
 	ShowDeprecationWarning("setSubject()", "the subject property");
     char* Subject;
 
-	if (PyArg_ParseTuple(args, "s", &Subject)) {
+	if (PyArg_ParseTuple(args, "s:setSubject", &Subject)) {
 	     m_subject = Subject;
 	}
 	else {
@@ -208,14 +206,13 @@ PyObject* KX_NetworkMessageActuator::PySetSubject(
 
 // 3. SetBodyType
 PyObject* KX_NetworkMessageActuator::PySetBodyType(
-	PyObject* self,
 	PyObject* args,
 	PyObject* kwds)
 {
 	ShowDeprecationWarning("setBodyType()", "the usePropBody property");
     int BodyType;
 
-	if (PyArg_ParseTuple(args, "i", &BodyType)) {
+	if (PyArg_ParseTuple(args, "i:setBodyType", &BodyType)) {
 		m_bPropBody = (BodyType != 0);
 	}
 	else {
@@ -227,14 +224,13 @@ PyObject* KX_NetworkMessageActuator::PySetBodyType(
 
 // 4. SetBody
 PyObject* KX_NetworkMessageActuator::PySetBody(
-	PyObject* self,
 	PyObject* args,
 	PyObject* kwds)
 {
 	ShowDeprecationWarning("setBody()", "the body property");
     char* Body;
 
-	if (PyArg_ParseTuple(args, "s", &Body)) {
+	if (PyArg_ParseTuple(args, "s:setBody", &Body)) {
 	     m_body = Body;
 	}
 	else {
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h
index 850f825b8f375f050e847399bcc69b587e064e6d..cf92fd46fe0cdd55fb3efaa8c53971ab0bcd3c74 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h
@@ -62,6 +62,7 @@ public:
 	/* ------------------------------------------------------------ */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	// Deprecated ----->
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
index 7922c341659b57d8c71ed26e33d6362eece9a74a..8ddcd87b66ff6a9cbe36ad7a2807f22ac9cae78b 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
@@ -79,15 +79,13 @@ CValue* KX_NetworkMessageSensor::GetReplica() {
 	CValue* replica = new KX_NetworkMessageSensor(*this);
 
 	if (replica == NULL) return NULL;
-
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
 
 // Return true only for flank (UP and DOWN)
-bool KX_NetworkMessageSensor::Evaluate(CValue* event)
+bool KX_NetworkMessageSensor::Evaluate()
 {
 	bool result = false;
 	bool WasUp = m_IsUp;
@@ -104,8 +102,8 @@ bool KX_NetworkMessageSensor::Evaluate(CValue* event)
 		m_SubjectList = NULL;
 	}
 
-	STR_String toname=GetParent()->GetName();
-	STR_String subject = this->m_subject;
+	STR_String& toname=GetParent()->GetName();
+	STR_String& subject = this->m_subject;
 
 	vector<NG_NetworkMessage*> messages =
 		m_NetworkScene->FindMessages(toname,"",subject,true);
@@ -125,9 +123,9 @@ bool KX_NetworkMessageSensor::Evaluate(CValue* event)
 	for (mesit=messages.begin();mesit!=messages.end();mesit++)
 	{
 		// save the body
-		STR_String body = (*mesit)->GetMessageText();
+		const STR_String& body = (*mesit)->GetMessageText();
 		// save the subject
-		STR_String messub = (*mesit)->GetSubject();
+		const STR_String& messub = (*mesit)->GetSubject();
 #ifdef NAN_NET_DEBUG
 		if (body) {
 			cout << "body [" << body << "]\n";
@@ -168,12 +166,17 @@ bool KX_NetworkMessageSensor::IsPositiveTrigger()
 
 /* Integration hooks --------------------------------------------------- */
 PyTypeObject KX_NetworkMessageSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_NetworkMessageSensor",
-	sizeof(KX_NetworkMessageSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -224,16 +227,14 @@ PyAttributeDef KX_NetworkMessageSensor::Attributes[] = {
 };
 
 PyObject* KX_NetworkMessageSensor::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_ISensor);
 }
 
+PyObject* KX_NetworkMessageSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 int KX_NetworkMessageSensor::py_setattro(PyObject *attr, PyObject *value) {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
 	return SCA_ISensor::py_setattro(attr, value);
 }
 
@@ -241,9 +242,9 @@ PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYAT
 {
 	KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v);
 	if (self->m_BodyList) {
-		return ((PyObject*) self->m_BodyList->AddRef());
+		return self->m_BodyList->GetProxy();
 	} else {
-		return ((PyObject*) new CListValue());
+		return (new CListValue())->NewProxy(true);
 	}
 }
 
@@ -251,9 +252,9 @@ PyObject* KX_NetworkMessageSensor::pyattr_get_subjects(void *self_v, const KX_PY
 {
 	KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v);
 	if (self->m_SubjectList) {
-		return ((PyObject*) self->m_SubjectList->AddRef());
+		return self->m_SubjectList->GetProxy();
 	} else {
-		return ((PyObject*) new CListValue());
+		return (new CListValue())->NewProxy(true);
 	}
 }
 
@@ -263,12 +264,12 @@ const char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] =
 "\tsetSubjectFilterText(value)\n"
 "\tChange the message subject text that this sensor is listening to.\n";
 
-PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( PyObject* self, PyObject* value)
+PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(PyObject* value)
 {
 	ShowDeprecationWarning("setSubjectFilterText()", "subject");
 	char* Subject = PyString_AsString(value);
 	if (Subject==NULL) {
-		PyErr_SetString(PyExc_TypeError, "expected a string message");
+		PyErr_SetString(PyExc_TypeError, "sensor.tsetSubjectFilterText(string): KX_NetworkMessageSensor, expected a string message");
 		return NULL;
 	}
 	
@@ -281,7 +282,7 @@ const char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] =
 "\tgetFrameMessageCount()\n"
 "\tGet the number of messages received since the last frame.\n";
 
-PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( PyObject* )
+PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount()
 {
 	ShowDeprecationWarning("getFrameMessageCount()", "frameMessageCount");
 	return PyInt_FromLong(long(m_frame_message_count));
@@ -292,13 +293,13 @@ const char KX_NetworkMessageSensor::GetBodies_doc[] =
 "\tgetBodies()\n"
 "\tGet the list of message bodies.\n";
 
-PyObject* KX_NetworkMessageSensor::PyGetBodies( PyObject* )
+PyObject* KX_NetworkMessageSensor::PyGetBodies()
 {
 	ShowDeprecationWarning("getBodies()", "bodies");
 	if (m_BodyList) {
-		return ((PyObject*) m_BodyList->AddRef());
+		return m_BodyList->GetProxy();
 	} else {
-		return ((PyObject*) new CListValue());
+		return (new CListValue())->NewProxy(true);
 	}
 }
 
@@ -307,7 +308,7 @@ const char KX_NetworkMessageSensor::GetSubject_doc[] =
 "\tgetSubject()\n"
 "\tGet the subject: field of the message sensor.\n";
 
-PyObject* KX_NetworkMessageSensor::PyGetSubject( PyObject* )
+PyObject* KX_NetworkMessageSensor::PyGetSubject()
 {
 	ShowDeprecationWarning("getSubject()", "subject");
 	return PyString_FromString(m_subject ? m_subject : "");
@@ -318,13 +319,13 @@ const char KX_NetworkMessageSensor::GetSubjects_doc[] =
 "\tgetSubjects()\n"
 "\tGet list of message subjects.\n";
 
-PyObject* KX_NetworkMessageSensor::PyGetSubjects( PyObject* )
+PyObject* KX_NetworkMessageSensor::PyGetSubjects()
 {
 	ShowDeprecationWarning("getSubjects()", "subjects");
 	if (m_SubjectList) {
-		return ((PyObject*) m_SubjectList->AddRef());
+		return m_SubjectList->GetProxy();
 	} else {
-		return ((PyObject*) new CListValue());
+		return (new CListValue())->NewProxy(true);
 	}
 }
 // <----- Deprecated
\ No newline at end of file
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
index ac0e880d25c7c5fb6119f27690ded595c5b792bd..53183f3382681c5c32ca3768d9dd3049c1cd47df 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
@@ -63,7 +63,7 @@ public:
 	virtual ~KX_NetworkMessageSensor();
 
 	virtual CValue* GetReplica();
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool IsPositiveTrigger();
 	virtual void Init();
 	void EndFrame();
@@ -73,6 +73,7 @@ public:
 	/* ------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	// Deprecated ----->
diff --git a/source/gameengine/Ketsji/KXNetwork/Makefile b/source/gameengine/Ketsji/KXNetwork/Makefile
index ddcb03600d5bd15e38bbd434561237d8fb74b04f..365ed8fc9c38d152642327930b6302c7a43b136c 100644
--- a/source/gameengine/Ketsji/KXNetwork/Makefile
+++ b/source/gameengine/Ketsji/KXNetwork/Makefile
@@ -38,8 +38,10 @@ CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
 CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
 
 CPPFLAGS += -I$(NAN_STRING)/include    
+CPPFLAGS += -I$(NAN_MOTO)/include
 CPPFLAGS += -I../../Expressions
 CPPFLAGS += -I../../GameLogic
+CPPFLAGS += -I../../SceneGraph
 CPPFLAGS += -I../../Network
 CPPFLAGS += -I../../../kernel/gen_system
 CPPFLAGS += -I..
diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript
index 2476ed1f275a82cd63172d71ceb718e152de6f24..5d9dd1464b3770c65cb36b608419c13eceffbf6d 100644
--- a/source/gameengine/Ketsji/KXNetwork/SConscript
+++ b/source/gameengine/Ketsji/KXNetwork/SConscript
@@ -3,9 +3,9 @@ Import ('env')
 
 sources = env.Glob('*.cpp')
 
-incs = '. #source/kernel/gen_system #intern/string #source/gameengine/Ketsji'
+incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Ketsji'
 incs += ' #source/gameengine/GameLogic #source/gameengine/Expressions'
-incs += ' #source/gameengine/Network'
+incs += ' #source/gameengine/Network #source/gameengine/SceneGraph'
 
 incs += ' ' + env['BF_PYTHON_INC']
 
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index bd137196ac6add5737d2d2c5740debc9286f31ad..3b8917efe902524f68d8d108047076d776e7505e 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -43,35 +43,48 @@ BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL;
 //static PyObject *gTextureDict = 0;
 
 KX_BlenderMaterial::KX_BlenderMaterial(
-    KX_Scene *scene,
-	BL_Material *data,
-	bool skin,
-	int lightlayer,
 	PyTypeObject *T
 	)
 :	PyObjectPlus(T),
-	RAS_IPolyMaterial(
-		STR_String( data->texname[0] ),
-		STR_String( data->matname ), // needed for physics!
-		data->tile,
-		data->tilexrep[0],
-		data->tileyrep[0],
-		data->mode,
-		data->transp,
-		((data->ras_mode &ALPHA)!=0),
-		((data->ras_mode &ZSORT)!=0),
-		lightlayer
-	),
-	mMaterial(data),
+	RAS_IPolyMaterial(),
+	mMaterial(NULL),
 	mShader(0),
 	mBlenderShader(0),
-	mScene(scene),
+	mScene(NULL),
 	mUserDefBlend(0),
 	mModified(0),
 	mConstructed(false),
 	mPass(0)
+{
+}
 
+void KX_BlenderMaterial::Initialize(
+    KX_Scene *scene,
+	BL_Material *data,
+	bool skin,
+	int lightlayer)
 {
+	RAS_IPolyMaterial::Initialize(
+		data->texname[0],
+		data->matname,
+		data->materialindex,
+		data->tile,
+		data->tilexrep[0],
+		data->tileyrep[0],
+		data->mode,
+		data->transp,
+		((data->ras_mode &ALPHA)!=0),
+		((data->ras_mode &ZSORT)!=0),
+		lightlayer
+	);
+	mMaterial = data;
+	mShader = 0;
+	mBlenderShader = 0;
+	mScene = scene;
+	mUserDefBlend = 0;
+	mModified = 0;
+	mConstructed = false;
+	mPass = 0;
 	// --------------------------------
 	// RAS_IPolyMaterial variables... 
 	m_flag |= RAS_BLENDERMAT;
@@ -95,7 +108,6 @@ KX_BlenderMaterial::KX_BlenderMaterial(
 			 );
 	}
 	m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT));
-
 }
 
 KX_BlenderMaterial::~KX_BlenderMaterial()
@@ -106,7 +118,6 @@ KX_BlenderMaterial::~KX_BlenderMaterial()
 		OnExit();
 }
 
-
 MTFace* KX_BlenderMaterial::GetMTFace(void) const 
 {
 	// fonts on polys
@@ -120,6 +131,33 @@ unsigned int* KX_BlenderMaterial::GetMCol(void) const
 	return mMaterial->rgb;
 }
 
+void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
+{
+	if (mMaterial) {
+		*rgba++ = (unsigned char) (mMaterial->matcolor[0]*255.0);
+		*rgba++ = (unsigned char) (mMaterial->matcolor[1]*255.0);
+		*rgba++ = (unsigned char) (mMaterial->matcolor[2]*255.0);
+		*rgba++ = (unsigned char) (mMaterial->matcolor[3]*255.0);
+	} else
+		RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
+}
+
+Material *KX_BlenderMaterial::GetBlenderMaterial() const
+{
+	return mMaterial->material;
+}
+
+Scene* KX_BlenderMaterial::GetBlenderScene() const
+{
+	return mScene->GetBlenderScene();
+}
+
+void KX_BlenderMaterial::ReleaseMaterial()
+{
+	if (mBlenderShader)
+		mBlenderShader->ReloadMaterial();
+}
+
 void KX_BlenderMaterial::OnConstruction()
 {
 	if (mConstructed)
@@ -377,10 +415,12 @@ KX_BlenderMaterial::ActivatShaders(
 		}
 		else
 			rasty->SetLines(false);
+		ActivatGLMaterials(rasty);
+		ActivateTexGen(rasty);
 	}
 
-	ActivatGLMaterials(rasty);
-	ActivateTexGen(rasty);
+	//ActivatGLMaterials(rasty);
+	//ActivateTexGen(rasty);
 }
 
 void
@@ -469,10 +509,12 @@ KX_BlenderMaterial::ActivateMat(
 		}
 		else
 			rasty->SetLines(false);
+		ActivatGLMaterials(rasty);
+		ActivateTexGen(rasty);
 	}
 
-	ActivatGLMaterials(rasty);
-	ActivateTexGen(rasty);
+	//ActivatGLMaterials(rasty);
+	//ActivateTexGen(rasty);
 }
 
 bool 
@@ -601,8 +643,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
 
 			if (mode &USECUSTOMUV)
 			{
-				STR_String str = mMaterial->mapping[i].uvCoName;
-				if (!str.IsEmpty())
+				if (!mMaterial->mapping[i].uvCoName.IsEmpty())
 					ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV2, i);
 				continue;
 			}
@@ -673,6 +714,9 @@ void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras)
 		mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame);
 
 	if(!obj) return;
+	obj->Release(); /* FindValue() AddRef's */
+
+	obj->Release();
 
 	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
 	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
@@ -749,16 +793,24 @@ PyMethodDef KX_BlenderMaterial::Methods[] =
 };
 
 PyAttributeDef KX_BlenderMaterial::Attributes[] = {
+	//KX_PYATTRIBUTE_TODO("shader"),
+	//KX_PYATTRIBUTE_TODO("materialIndex"),
+	//KX_PYATTRIBUTE_TODO("blending"),
 	{ NULL }	//Sentinel
 };
 
 PyTypeObject KX_BlenderMaterial::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_BlenderMaterial",
-		sizeof(KX_BlenderMaterial),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -784,6 +836,10 @@ PyObject* KX_BlenderMaterial::py_getattro(PyObject *attr)
 	py_getattro_up(PyObjectPlus);
 }
 
+PyObject* KX_BlenderMaterial::py_getattro_dict() {
+	py_getattro_dict_up(PyObjectPlus);
+}
+
 int KX_BlenderMaterial::py_setattro(PyObject *attr, PyObject *pyvalue)
 {
 	return PyObjectPlus::py_setattro(attr, pyvalue);
@@ -827,8 +883,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
 			m_flag &= ~RAS_BLENDERGLSL;
 			mMaterial->SetSharedMaterial(true);
 			mScene->GetBucketManager()->ReleaseDisplayLists(this);
-			Py_INCREF(mShader);
-			return mShader;
+			return mShader->GetProxy();
 		}else
 		{
 			// decref all references to the object
@@ -836,18 +891,13 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
 			// We will then go back to fixed functionality
 			// for this material
 			if(mShader) {
-				if(mShader->ob_refcnt > 1) {
-					Py_DECREF(mShader);
-				}
-				else {
-					delete mShader;
-					mShader=0;
-				}
+				delete mShader; /* will handle python de-referencing */
+				mShader=0;
 			}
 		}
 		Py_RETURN_NONE;
 	}
-	PyErr_Format(PyExc_ValueError, "GLSL Error");
+	PyErr_SetString(PyExc_ValueError, "material.getShader(): KX_BlenderMaterial, GLSL Error");
 	return NULL;
 }
 
@@ -865,7 +915,7 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(void)
 
 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
 {
-	return PyInt_FromLong( mMaterial->material_index );
+	return PyInt_FromLong( GetMaterialIndex() );
 }
 
 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
@@ -897,7 +947,7 @@ static unsigned int GL_array[11] = {
 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.src, GameLogic.dest)")
 {
 	unsigned int b[2];
-	if(PyArg_ParseTuple(args, "ii", &b[0], &b[1]))
+	if(PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1]))
 	{
 		bool value_found[2] = {false, false};
 		for(int i=0; i<11; i++)
@@ -913,7 +963,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.sr
 			if(value_found[0] && value_found[1]) break;
 		}
 		if(!value_found[0] || !value_found[1]) {
-			PyErr_Format(PyExc_ValueError, "invalid enum.");
+			PyErr_SetString(PyExc_ValueError, "material.setBlending(int, int): KX_BlenderMaterial, invalid enum.");
 			return NULL;
 		}
 		mUserDefBlend = true;
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index 2d9dc8fd022be650d5c9394a2964856a5e36a867..52019ed2248739616df162a776393731f93f8c5b 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -24,11 +24,13 @@ class KX_BlenderMaterial :  public PyObjectPlus, public RAS_IPolyMaterial
 public:
 	// --------------------------------
 	KX_BlenderMaterial(
+		PyTypeObject*	T=&Type
+	);
+	void Initialize(
 		class KX_Scene*	scene,
 		BL_Material*	mat,
 		bool			skin,
-		int				lightlayer,
-		PyTypeObject*	T=&Type
+		int				lightlayer
 	);
 
 	virtual ~KX_BlenderMaterial();
@@ -73,7 +75,6 @@ public:
 	Image * getImage (unsigned int idx) { 
 		return (idx < MAXTEX && mMaterial) ? mMaterial->img[idx] : NULL; 
 	}
-
 	// for ipos
 	void UpdateIPO(
 		MT_Vector4 rgba, MT_Vector3 specrgb,
@@ -83,7 +84,9 @@ public:
 	
 	// --------------------------------
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int       py_setattro(PyObject *attr, PyObject *pyvalue);
+	virtual PyObject* py_repr(void) { return PyString_FromString(mMaterial->matname.ReadPtr()); }
 
 	KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader );
 	KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex );
@@ -115,6 +118,10 @@ private:
 	void ActivateTexGen( RAS_IRasterizer *ras ) const;
 
 	bool UsesLighting(RAS_IRasterizer *rasty) const;
+	void GetMaterialRGBAColor(unsigned char *rgba) const;
+	Material* GetBlenderMaterial() const;
+	Scene* GetBlenderScene() const;
+	void ReleaseMaterial();
 
 	// message centers
 	void	setTexData( bool enable,RAS_IRasterizer *ras);
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
index 062e9f7df503ac14a7e8da81dd9db1d3262f9469..300a7906e811a7134925b6412bd8289c3d03253f 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
@@ -21,9 +21,13 @@ KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInf
 : KX_IPhysicsController(dyna,compound,(PHY_IPhysicsController*)this),
 CcdPhysicsController(ci),
 m_savedCollisionFlags(0),
+m_savedCollisionFilterGroup(0),
+m_savedCollisionFilterMask(0),
+m_savedMass(0.0),
+m_savedDyna(false),
+m_suspended(false),
 m_bulletChildShape(NULL)
 {
-
 }
 	
 KX_BulletPhysicsController::~KX_BulletPhysicsController ()
@@ -59,6 +63,24 @@ void	KX_BulletPhysicsController::applyImpulse(const MT_Point3& attach, const MT_
 
 }
 
+float KX_BulletPhysicsController::GetLinVelocityMin()
+{
+	return (float)CcdPhysicsController::GetLinVelocityMin();
+}
+void  KX_BulletPhysicsController::SetLinVelocityMin(float val)
+{
+	CcdPhysicsController::SetLinVelocityMin(val);
+}
+
+float KX_BulletPhysicsController::GetLinVelocityMax()
+{
+	return (float)CcdPhysicsController::GetLinVelocityMax();
+}
+void  KX_BulletPhysicsController::SetLinVelocityMax(float val)
+{
+	CcdPhysicsController::SetLinVelocityMax(val);
+}
+
 void	KX_BulletPhysicsController::SetObject (SG_IObject* object)
 {
 	SG_Controller::SetObject(object);
@@ -73,6 +95,10 @@ void	KX_BulletPhysicsController::SetObject (SG_IObject* object)
 
 }
 
+MT_Scalar KX_BulletPhysicsController::GetRadius()
+{
+	return MT_Scalar(CcdPhysicsController::GetRadius());
+}
 
 void	KX_BulletPhysicsController::setMargin (float collisionMargin)
 {
@@ -162,9 +188,18 @@ MT_Scalar	KX_BulletPhysicsController::GetMass()
 
 }
 
-MT_Scalar KX_BulletPhysicsController::GetRadius()
+MT_Vector3 KX_BulletPhysicsController::GetLocalInertia()
 {
-	return MT_Scalar(CcdPhysicsController::GetRadius());
+    MT_Vector3 inertia(0.f, 0.f, 0.f);
+    btVector3 inv_inertia;
+    if (GetRigidBody()) {
+        inv_inertia = GetRigidBody()->getInvInertiaDiagLocal();
+		if (!btFuzzyZero(inv_inertia.getX()) && 
+			!btFuzzyZero(inv_inertia.getY()) && 
+			!btFuzzyZero(inv_inertia.getZ()))
+			inertia = MT_Vector3(1.f/inv_inertia.getX(), 1.f/inv_inertia.getY(), 1.f/inv_inertia.getZ());
+    }
+    return inertia;
 }
 
 MT_Vector3	KX_BulletPhysicsController::getReactionForce()
@@ -306,8 +341,7 @@ void    KX_BulletPhysicsController::RemoveCompoundChild(KX_IPhysicsController* c
 void KX_BulletPhysicsController::SetMass(MT_Scalar newmass)
 {
 	btRigidBody *body = GetRigidBody();
-	if (body && body->getActivationState() != DISABLE_SIMULATION && 
-		newmass>MT_EPSILON && GetMass()>MT_EPSILON)
+	if (body && !m_suspended && newmass>MT_EPSILON && GetMass()>MT_EPSILON)
 	{
 		btVector3 grav = body->getGravity();
 		btVector3 accel = grav / GetMass();
@@ -325,34 +359,37 @@ void KX_BulletPhysicsController::SetMass(MT_Scalar newmass)
 void	KX_BulletPhysicsController::SuspendDynamics(bool ghost)
 {
 	btRigidBody *body = GetRigidBody();
-	if (body && body->getActivationState() != DISABLE_SIMULATION)
+	if (body && !m_suspended)
 	{
 		btBroadphaseProxy* handle = body->getBroadphaseHandle();
 		m_savedCollisionFlags = body->getCollisionFlags();
 		m_savedMass = GetMass();
+		m_savedDyna = m_bDyna;
 		m_savedCollisionFilterGroup = handle->m_collisionFilterGroup;
 		m_savedCollisionFilterMask = handle->m_collisionFilterMask;
-		m_savedActivationState = body->getActivationState();
-		body->forceActivationState(DISABLE_SIMULATION);
+		m_suspended = true;
 		GetPhysicsEnvironment()->updateCcdPhysicsController(this, 
 			0.0,
 			btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)),
 			btBroadphaseProxy::StaticFilter, 
 			btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+		m_bDyna = false;
 	}
 }
 
 void	KX_BulletPhysicsController::RestoreDynamics()
 {
 	btRigidBody *body = GetRigidBody();
-	if (body && body->getActivationState() == DISABLE_SIMULATION)
+	if (body && m_suspended)
 	{
 		GetPhysicsEnvironment()->updateCcdPhysicsController(this, 
 			m_savedMass,
 			m_savedCollisionFlags,
 			m_savedCollisionFilterGroup,
 			m_savedCollisionFilterMask);
-		body->forceActivationState(m_savedActivationState);
+		body->activate();
+		m_bDyna = m_savedDyna;
+		m_suspended = false;
 	}
 }
 
@@ -407,23 +444,24 @@ SG_Controller*	KX_BulletPhysicsController::GetReplica(class SG_Node* destnode)
 
 void	KX_BulletPhysicsController::SetSumoTransform(bool nondynaonly)
 {
-	if (GetRigidBody())
-		GetRigidBody()->activate(true);
 
 	if (!m_bDyna)
 	{
-		GetCollisionObject()->setCollisionFlags(GetRigidBody()->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+		btCollisionObject* object = GetRigidBody();
+		object->setActivationState(ACTIVE_TAG);
+		object->setCollisionFlags(object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
 	} else
 	{
 		if (!nondynaonly)
 		{
+			/*
 			btTransform worldTrans;
 			if (GetRigidBody())
 			{
 				GetRigidBody()->getMotionState()->getWorldTransform(worldTrans);
 				GetRigidBody()->setCenterOfMassTransform(worldTrans);
 			}
-			
+			*/
 			/*
 			scaling?
 			if (m_bDyna)
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h
index 44fbde7054e7b8f8390062ce14effa6647763da2..9d2afad1a5c2aa6560617c9a07296531281836de 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h
@@ -13,6 +13,8 @@ private:
 	short int m_savedCollisionFilterGroup;
 	short int m_savedCollisionFilterMask;
 	MT_Scalar m_savedMass;
+	bool m_savedDyna;
+	bool m_suspended;
 	btCollisionShape* m_bulletChildShape;
 
 public:
@@ -42,6 +44,7 @@ public:
 	virtual	void setScaling(const MT_Vector3& scaling);
 	virtual	MT_Scalar	GetMass();
 	virtual	void	SetMass(MT_Scalar newmass);
+	virtual	MT_Vector3	GetLocalInertia();
 	virtual	MT_Vector3	getReactionForce();
 	virtual void	setRigidBody(bool rigid);
 	virtual void    AddCompoundChild(KX_IPhysicsController* child);
@@ -55,7 +58,11 @@ public:
 	virtual	SG_Controller*	GetReplica(class SG_Node* destnode);
 
 	virtual MT_Scalar GetRadius();
-
+	
+	virtual float GetLinVelocityMin();
+	virtual void  SetLinVelocityMin(float val);
+	virtual float GetLinVelocityMax();
+	virtual void  SetLinVelocityMax(float val);
 
 	virtual void	SetSumoTransform(bool nondynaonly);
 	// todo: remove next line !
diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp
index 57c9d30e92e2cb117fbf172e9c188122c53de23b..7f8505afa3d904842578348f6581315267f3ee36 100644
--- a/source/gameengine/Ketsji/KX_CDActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CDActuator.cpp
@@ -74,9 +74,6 @@ CValue* KX_CDActuator::GetReplica()
 {
 	KX_CDActuator* replica = new KX_CDActuator(*this);
 	replica->ProcessReplica();
-	
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
 	return replica;
 };
 
@@ -158,12 +155,17 @@ bool KX_CDActuator::Update()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_CDActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_SoundActuator",
-		sizeof(KX_CDActuator),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -217,18 +219,16 @@ int KX_CDActuator::pyattr_setGain(void *self, const struct KX_PYATTRIBUTE_DEF *a
 
 PyObject* KX_CDActuator::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_CDActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_CDActuator::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 
@@ -295,11 +295,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, playAll,
 }     
 
 // Deprecated ----->
-PyObject* KX_CDActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_CDActuator::PySetGain(PyObject* args)
 {
 	float gain = 1.0;
 	ShowDeprecationWarning("setGain()", "the volume property");
-	if (!PyArg_ParseTuple(args, "f", &gain))
+	if (!PyArg_ParseTuple(args, "f:setGain", &gain))
 		return NULL;
 	
 	SND_CDObject::Instance()->SetGain(gain);
@@ -309,7 +309,7 @@ PyObject* KX_CDActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwd
 
 
 
-PyObject* KX_CDActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_CDActuator::PyGetGain(PyObject* args)
 {
 	float gain = SND_CDObject::Instance()->GetGain();
 	ShowDeprecationWarning("getGain()", "the volume property");
diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h
index e7683297c7a2b6e70e2599fcb7fe391584d78a1d..2fd05ab72e5d82a7fb9df4f82989af0ee4b21fad 100644
--- a/source/gameengine/Ketsji/KX_CDActuator.h
+++ b/source/gameengine/Ketsji/KX_CDActuator.h
@@ -82,11 +82,12 @@ public:
 	/* -------------------------------------------------------------------- */
 
 	virtual PyObject*  py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	// Deprecated ----->
-	KX_PYMETHOD(KX_CDActuator,SetGain);
-	KX_PYMETHOD(KX_CDActuator,GetGain);
+	KX_PYMETHOD_VARARGS(KX_CDActuator,SetGain);
+	KX_PYMETHOD_VARARGS(KX_CDActuator,GetGain);
 	// <-----
 
 	KX_PYMETHOD_DOC_NOARGS(KX_CDActuator, startCD);
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index 19370d83322824a43d7f1fedfa97a94637254b58..3ea01cca5cad40021573421df6d00060ec65a508 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -47,7 +47,7 @@ KX_Camera::KX_Camera(void* sgReplicationInfo,
 					m_camdata(camdata),
 					m_dirty(true),
 					m_normalized(false),
-					m_frustum_culling(frustum_culling && camdata.m_perspective),
+					m_frustum_culling(frustum_culling),
 					m_set_projection_matrix(false),
 					m_set_frustum_center(false)
 {
@@ -71,16 +71,10 @@ CValue*	KX_Camera::GetReplica()
 	KX_Camera* replica = new KX_Camera(*this);
 	
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-	ProcessReplica(replica);
+	replica->ProcessReplica();
 	
 	return replica;
 }
-	
-void KX_Camera::ProcessReplica(KX_Camera* replica)
-{
-	KX_GameObject::ProcessReplica(replica);
-}
 
 MT_Transform KX_Camera::GetWorldToCamera() const
 { 
@@ -190,6 +184,11 @@ float KX_Camera::GetLens() const
 	return m_camdata.m_lens;
 }
 
+float KX_Camera::GetScale() const
+{
+	return m_camdata.m_scale;
+}
+
 
 
 float KX_Camera::GetCameraNear() const
@@ -270,80 +269,83 @@ void KX_Camera::ExtractFrustumSphere()
 	MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix;
 	clip_camcs_matrix.invert();
 
-    // detect which of the corner of the far clipping plane is the farthest to the origin
-	MT_Vector4 nfar;    // far point in device normalized coordinate
-    MT_Point3 farpoint; // most extreme far point in camera coordinate
-    MT_Point3 nearpoint;// most extreme near point in camera coordinate
-    MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate
-    MT_Scalar F=1.0, N; // square distance of far and near point to origin
-    MT_Scalar f, n;     // distance of far and near point to z axis. f is always > 0 but n can be < 0
-    MT_Scalar e, s;     // far and near clipping distance (<0)
-    MT_Scalar c;        // slope of center line = distance of far clipping center to z axis / far clipping distance
-    MT_Scalar z;        // projection of sphere center on z axis (<0)
-    // tmp value
-    MT_Vector4 npoint(1., 1., 1., 1.);
-    MT_Vector4 hpoint;
-    MT_Point3 point;
-    MT_Scalar len;
-    for (int i=0; i<4; i++)
-    {
-    	hpoint = clip_camcs_matrix*npoint;
-        point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]);
-        len = point.dot(point);
-        if (len > F)
-        {
-            nfar = npoint;
-            farpoint = point;
-            F = len;
-        }
-        // rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane
-        len = npoint[0];
-        npoint[0] = -npoint[1];
-        npoint[1] = len;
-        farcenter += point;
-    }
-    // the far center is the average of the far clipping points
-    farcenter *= 0.25;
-    // the extreme near point is the opposite point on the near clipping plane
-    nfar.setValue(-nfar[0], -nfar[1], -1., 1.);
-   	nfar = clip_camcs_matrix*nfar;
-    nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]);
-    N = nearpoint.dot(nearpoint);
-    e = farpoint[2];
-    s = nearpoint[2];
-    // projection on XY plane for distance to axis computation
-    MT_Point2 farxy(farpoint[0], farpoint[1]);
-    // f is forced positive by construction
-    f = farxy.length();
-    // get corresponding point on the near plane
-    farxy *= s/e;
-    // this formula preserve the sign of n
-    n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length();
-    c = MT_Point2(farcenter[0], farcenter[1]).length()/e;
-    // the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case
-    z = (F-N)/(2.0*(e-s+c*(f-n)));
-	m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z);
-	m_frustum_radius = m_frustum_center.distance(farpoint);
-
-#if 0
-	// The most extreme points on the near and far plane. (normalized device coords)
-	MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.);
-	
-	// Transform to hom camera local space
-	hnear = clip_camcs_matrix*hnear;
-	hfar = clip_camcs_matrix*hfar;
-	
-	// Tranform to 3d camera local space.
-	MT_Point3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]);
-	MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]);
-	
-	// Compute center
-    // don't use camera data in case the user specifies the matrix directly
-	m_frustum_center = MT_Point3(0., 0.,
-		(nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(nearpoint[2]-farpoint[2] /*m_camdata.m_clipend - m_camdata.m_clipstart*/)));
-	m_frustum_radius = m_frustum_center.distance(farpoint);
-#endif
-
+	if (m_projection_matrix[3][3] == MT_Scalar(0.0)) 
+	{
+		// frustrum projection
+		// detect which of the corner of the far clipping plane is the farthest to the origin
+		MT_Vector4 nfar;    // far point in device normalized coordinate
+		MT_Point3 farpoint; // most extreme far point in camera coordinate
+		MT_Point3 nearpoint;// most extreme near point in camera coordinate
+		MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate
+		MT_Scalar F=-1.0, N; // square distance of far and near point to origin
+		MT_Scalar f, n;     // distance of far and near point to z axis. f is always > 0 but n can be < 0
+		MT_Scalar e, s;     // far and near clipping distance (<0)
+		MT_Scalar c;        // slope of center line = distance of far clipping center to z axis / far clipping distance
+		MT_Scalar z;        // projection of sphere center on z axis (<0)
+		// tmp value
+		MT_Vector4 npoint(1., 1., 1., 1.);
+		MT_Vector4 hpoint;
+		MT_Point3 point;
+		MT_Scalar len;
+		for (int i=0; i<4; i++)
+		{
+    		hpoint = clip_camcs_matrix*npoint;
+			point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]);
+			len = point.dot(point);
+			if (len > F)
+			{
+				nfar = npoint;
+				farpoint = point;
+				F = len;
+			}
+			// rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane
+			len = npoint[0];
+			npoint[0] = -npoint[1];
+			npoint[1] = len;
+			farcenter += point;
+		}
+		// the far center is the average of the far clipping points
+		farcenter *= 0.25;
+		// the extreme near point is the opposite point on the near clipping plane
+		nfar.setValue(-nfar[0], -nfar[1], -1., 1.);
+   		nfar = clip_camcs_matrix*nfar;
+		nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]);
+		// this is a frustrum projection
+		N = nearpoint.dot(nearpoint);
+		e = farpoint[2];
+		s = nearpoint[2];
+		// projection on XY plane for distance to axis computation
+		MT_Point2 farxy(farpoint[0], farpoint[1]);
+		// f is forced positive by construction
+		f = farxy.length();
+		// get corresponding point on the near plane
+		farxy *= s/e;
+		// this formula preserve the sign of n
+		n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length();
+		c = MT_Point2(farcenter[0], farcenter[1]).length()/e;
+		// the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case
+		z = (F-N)/(2.0*(e-s+c*(f-n)));
+		m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z);
+		m_frustum_radius = m_frustum_center.distance(farpoint);
+	} 
+	else
+	{
+		// orthographic projection
+		// The most extreme points on the near and far plane. (normalized device coords)
+		MT_Vector4 hnear(1., 1., 1., 1.), hfar(-1., -1., -1., 1.);
+		
+		// Transform to hom camera local space
+		hnear = clip_camcs_matrix*hnear;
+		hfar = clip_camcs_matrix*hfar;
+		
+		// Tranform to 3d camera local space.
+		MT_Point3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]);
+		MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]);
+		
+		// just use mediant point
+		m_frustum_center = (farpoint + nearpoint)*0.5;
+		m_frustum_radius = m_frustum_center.distance(farpoint);
+	}
 	// Transform to world space.
 	m_frustum_center = GetCameraToWorld()(m_frustum_center);
 	m_frustum_radius /= fabs(NodeGetWorldScaling()[NodeGetWorldScaling().closestAxis()]);
@@ -476,36 +478,70 @@ PyMethodDef KX_Camera::Methods[] = {
 	KX_PYMETHODTABLE_NOARGS(KX_Camera, getWorldToCamera),
 	KX_PYMETHODTABLE_NOARGS(KX_Camera, getProjectionMatrix),
 	KX_PYMETHODTABLE_O(KX_Camera, setProjectionMatrix),
-	KX_PYMETHODTABLE_O(KX_Camera, enableViewport),
 	KX_PYMETHODTABLE(KX_Camera, setViewport),
 	KX_PYMETHODTABLE_NOARGS(KX_Camera, setOnTop),
 	
+	// DEPRECATED
+	KX_PYMETHODTABLE_O(KX_Camera, enableViewport),
+	
 	{NULL,NULL} //Sentinel
 };
 
 PyAttributeDef KX_Camera::Attributes[] = {
+	
+	KX_PYATTRIBUTE_BOOL_RW("frustum_culling", KX_Camera, m_frustum_culling),
+	KX_PYATTRIBUTE_RW_FUNCTION("perspective", KX_Camera, pyattr_get_perspective, pyattr_set_perspective),
+	
+	KX_PYATTRIBUTE_RW_FUNCTION("lens",	KX_Camera,	pyattr_get_lens, pyattr_set_lens),
+	KX_PYATTRIBUTE_RW_FUNCTION("near",	KX_Camera,	pyattr_get_near, pyattr_set_near),
+	KX_PYATTRIBUTE_RW_FUNCTION("far",	KX_Camera,	pyattr_get_far,  pyattr_set_far),
+	
+	KX_PYATTRIBUTE_RW_FUNCTION("isViewport",	KX_Camera,	pyattr_get_is_viewport,  pyattr_set_is_viewport),
+	
+	KX_PYATTRIBUTE_RO_FUNCTION("projection_matrix",	KX_Camera,	pyattr_get_projection_matrix),
+	KX_PYATTRIBUTE_RO_FUNCTION("modelview_matrix",	KX_Camera,	pyattr_get_modelview_matrix),
+	KX_PYATTRIBUTE_RO_FUNCTION("camera_to_world",	KX_Camera,	pyattr_get_camera_to_world),
+	KX_PYATTRIBUTE_RO_FUNCTION("world_to_camera",	KX_Camera,	pyattr_get_world_to_camera),
+	
+	/* Grrr, functions for constants? */
+	KX_PYATTRIBUTE_RO_FUNCTION("INSIDE",	KX_Camera, pyattr_get_INSIDE),
+	KX_PYATTRIBUTE_RO_FUNCTION("OUTSIDE",	KX_Camera, pyattr_get_OUTSIDE),
+	KX_PYATTRIBUTE_RO_FUNCTION("INTERSECT",	KX_Camera, pyattr_get_INTERSECT),
+	
 	{ NULL }	//Sentinel
 };
 
 PyTypeObject KX_Camera::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_Camera",
-		sizeof(KX_Camera),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
 		0,
 		py_base_repr,
-		0,0,0,0,0,0,
+		0,0,
+		&KX_GameObject::Mapping,
+		0,0,0,
 		py_base_getattro,
 		py_base_setattro,
 		0,0,0,0,0,0,0,0,0,
 		Methods
 };
 
+
+
+
+
+
 PyParentObject KX_Camera::Parents[] = {
 	&KX_Camera::Type,
 	&KX_GameObject::Type,
@@ -516,91 +552,16 @@ PyParentObject KX_Camera::Parents[] = {
 
 PyObject* KX_Camera::py_getattro(PyObject *attr)
 {
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "INSIDE"))
-		return PyInt_FromLong(INSIDE); /* new ref */
-	if (!strcmp(attr_str, "OUTSIDE"))
-		return PyInt_FromLong(OUTSIDE); /* new ref */
-	if (!strcmp(attr_str, "INTERSECT"))
-		return PyInt_FromLong(INTERSECT); /* new ref */
-	
-	if (!strcmp(attr_str, "lens"))
-		return PyFloat_FromDouble(GetLens()); /* new ref */
-	if (!strcmp(attr_str, "near"))
-		return PyFloat_FromDouble(GetCameraNear()); /* new ref */
-	if (!strcmp(attr_str, "far"))
-		return PyFloat_FromDouble(GetCameraFar()); /* new ref */
-	if (!strcmp(attr_str, "frustum_culling"))
-		return PyInt_FromLong(m_frustum_culling); /* new ref */
-	if (!strcmp(attr_str, "perspective"))
-		return PyInt_FromLong(m_camdata.m_perspective); /* new ref */
-	if (!strcmp(attr_str, "projection_matrix"))
-		return PyObjectFrom(GetProjectionMatrix()); /* new ref */
-	if (!strcmp(attr_str, "modelview_matrix"))
-		return PyObjectFrom(GetModelviewMatrix()); /* new ref */
-	if (!strcmp(attr_str, "camera_to_world"))
-		return PyObjectFrom(GetCameraToWorld()); /* new ref */
-	if (!strcmp(attr_str, "world_to_camera"))
-		return PyObjectFrom(GetWorldToCamera()); /* new ref */
-	
 	py_getattro_up(KX_GameObject);
 }
 
-int KX_Camera::py_setattro(PyObject *attr, PyObject *pyvalue)
-{
-	char *attr_str= PyString_AsString(attr);
-	
-	if (PyInt_Check(pyvalue))
-	{
-		if (!strcmp(attr_str, "frustum_culling"))
-		{
-			m_frustum_culling = PyInt_AsLong(pyvalue);
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "perspective"))
-		{
-			m_camdata.m_perspective = PyInt_AsLong(pyvalue);
-			return 0;
-		}
-	}
-	
-	if (PyFloat_Check(pyvalue))
-	{
-		if (!strcmp(attr_str, "lens"))
-		{
-			m_camdata.m_lens = PyFloat_AsDouble(pyvalue);
-			m_set_projection_matrix = false;
-			return 0;
-		}
-		if (!strcmp(attr_str, "near"))
-		{
-			m_camdata.m_clipstart = PyFloat_AsDouble(pyvalue);
-			m_set_projection_matrix = false;
-			return 0;
-		}
-		if (!strcmp(attr_str, "far"))
-		{
-			m_camdata.m_clipend = PyFloat_AsDouble(pyvalue);
-			m_set_projection_matrix = false;
-			return 0;
-		}
-	}
-	
-	if (PyObject_IsMT_Matrix(pyvalue, 4))
-	{
-		if (!strcmp(attr_str, "projection_matrix"))
-		{
-			MT_Matrix4x4 mat;
-			if (PyMatTo(pyvalue, mat))
-			{
-				SetProjectionMatrix(mat);
-				return 0;
-			}
-			return 1;
-		}
-	}
-	return KX_GameObject::py_setattro(attr, pyvalue);
+PyObject* KX_Camera::py_getattro_dict() {
+	py_getattro_dict_up(KX_GameObject);
+}
+
+int KX_Camera::py_setattro(PyObject *attr, PyObject *value)
+{	
+	py_setattro_up(KX_GameObject);
 }
 
 KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum,
@@ -623,7 +584,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum,
 {
 	PyObject *pycenter;
 	float radius;
-	if (PyArg_ParseTuple(args, "Of", &pycenter, &radius))
+	if (PyArg_ParseTuple(args, "Of:sphereInsideFrustum", &pycenter, &radius))
 	{
 		MT_Point3 center;
 		if (PyVecTo(pycenter, center))
@@ -632,7 +593,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum,
 		}
 	}
 
-	PyErr_SetString(PyExc_TypeError, "sphereInsideFrustum: Expected arguments: (center, radius)");
+	PyErr_SetString(PyExc_TypeError, "camera.sphereInsideFrustum(center, radius): KX_Camera, expected arguments: (center, radius)");
 	
 	return NULL;
 }
@@ -665,7 +626,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum,
 	unsigned int num_points = PySequence_Size(value);
 	if (num_points != 8)
 	{
-		PyErr_Format(PyExc_TypeError, "boxInsideFrustum: Expected eight (8) points, got %d", num_points);
+		PyErr_Format(PyExc_TypeError, "camera.boxInsideFrustum(box): KX_Camera, expected eight (8) points, got %d", num_points);
 		return NULL;
 	}
 	
@@ -704,7 +665,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum,
 		return PyInt_FromLong(PointInsideFrustum(point)); /* new ref */
 	}
 	
-	PyErr_SetString(PyExc_TypeError, "pointInsideFrustum: Expected point argument.");
+	PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument.");
 	return NULL;
 }
 
@@ -780,7 +741,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, setProjectionMatrix,
 	MT_Matrix4x4 mat;
 	if (!PyMatTo(value, mat))
 	{
-		PyErr_SetString(PyExc_TypeError, "setProjectionMatrix: Expected 4x4 list as matrix argument.");
+		PyErr_SetString(PyExc_TypeError, "camera.setProjectionMatrix(matrix): KX_Camera, expected 4x4 list as matrix argument.");
 		return NULL;
 	}
 	
@@ -793,10 +754,11 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, enableViewport,
 "Sets this camera's viewport status\n"
 )
 {
-	int viewport = PyObject_IsTrue(value);
+	ShowDeprecationWarning("enableViewport(bool)", "the isViewport property");
 	
+	int viewport = PyObject_IsTrue(value);
 	if (viewport == -1) {
-		PyErr_SetString(PyExc_ValueError, "expected True/False or 0/1");
+		PyErr_SetString(PyExc_ValueError, "camera.enableViewport(bool): KX_Camera, expected True/False or 0/1");
 		return NULL;
 	}
 	
@@ -824,10 +786,150 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop,
 "setOnTop()\n"
 "Sets this camera's viewport on top\n")
 {
-	class KX_Scene* scene;
-	
-	scene = KX_GetActiveScene();
-	MT_assert(scene);
+	class KX_Scene* scene = KX_GetActiveScene();
 	scene->SetCameraOnTop(this);
 	Py_RETURN_NONE;
 }
+
+PyObject* KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyBool_FromLong(self->m_camdata.m_perspective);
+}
+
+int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	int param = PyObject_IsTrue( value );
+	if (param == -1) {
+		PyErr_SetString(PyExc_AttributeError, "camera.perspective = bool: KX_Camera, expected True/False or 0/1");
+		return -1;
+	}
+	
+	self->m_camdata.m_perspective= param;
+	return 0;
+}
+
+PyObject* KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyFloat_FromDouble(self->m_camdata.m_lens);
+}
+
+int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	float param = PyFloat_AsDouble(value);
+	if (param == -1) {
+		PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero");
+		return -1;
+	}
+	
+	self->m_camdata.m_lens= param;
+	self->m_set_projection_matrix = false;
+	return 0;
+}
+
+PyObject* KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyFloat_FromDouble(self->m_camdata.m_clipstart);
+}
+
+int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	float param = PyFloat_AsDouble(value);
+	if (param == -1) {
+		PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero");
+		return -1;
+	}
+	
+	self->m_camdata.m_clipstart= param;
+	self->m_set_projection_matrix = false;
+	return 0;
+}
+
+PyObject* KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyFloat_FromDouble(self->m_camdata.m_clipend);
+}
+
+int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	float param = PyFloat_AsDouble(value);
+	if (param == -1) {
+		PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero");
+		return -1;
+	}
+	
+	self->m_camdata.m_clipend= param;
+	self->m_set_projection_matrix = false;
+	return 0;
+}
+
+
+PyObject* KX_Camera::pyattr_get_is_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyBool_FromLong(self->GetViewport());
+}
+
+int KX_Camera::pyattr_set_is_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	int param = PyObject_IsTrue( value );
+	if (param == -1) {
+		PyErr_SetString(PyExc_AttributeError, "camera.isViewport = bool: KX_Camera, expected True or False");
+		return 1;
+	}
+	self->EnableViewport((bool)param);
+	return 0;
+}
+
+
+PyObject* KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyObjectFrom(self->GetProjectionMatrix()); 
+}
+
+int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	MT_Matrix4x4 mat;
+	if (!PyMatTo(value, mat)) 
+		return -1;
+	
+	self->SetProjectionMatrix(mat);
+	return 0;
+}
+
+PyObject* KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyObjectFrom(self->GetModelviewMatrix()); 
+}
+
+PyObject* KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyObjectFrom(self->GetCameraToWorld());
+}
+
+PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Camera* self= static_cast<KX_Camera*>(self_v);
+	return PyObjectFrom(self->GetWorldToCamera()); 
+}
+
+
+PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{	return PyInt_FromLong(INSIDE); }
+PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{	return PyInt_FromLong(OUTSIDE); }
+PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{	return PyInt_FromLong(INTERSECT); }
+
diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h
index 499db66ab14683de4f1ca5f2649b8f08bc708e67..e99a0594701a734263d9916322b2b0cf045c4c36 100644
--- a/source/gameengine/Ketsji/KX_Camera.h
+++ b/source/gameengine/Ketsji/KX_Camera.h
@@ -45,6 +45,7 @@ class KX_Camera : public KX_GameObject
 {
 	Py_Header;
 protected:
+	friend class KX_Scene;
 	/** Camera parameters (clips distances, focal lenght). These
 	 * params are closely tied to Blender. In the gameengine, only the
 	 * projection and modelview matrices are relevant. There's a
@@ -67,6 +68,7 @@ protected:
 	 * Storage for the projection matrix that is passed to the
 	 * rasterizer. */
 	MT_Matrix4x4 m_projection_matrix;
+	//MT_Matrix4x4 m_projection_matrix1;
 
 	/**
 	 * Storage for the modelview matrix that is passed to the
@@ -119,6 +121,16 @@ protected:
 	 * Extracts the bound sphere of the view frustum.
 	 */
 	void ExtractFrustumSphere();
+	/**
+	 * return the clip plane
+	 */
+	MT_Vector4 *GetNormalizedClipPlanes()
+	{
+		ExtractClipPlanes();
+		NormalizeClipPlanes();
+		return m_planes;
+	}
+
 public:
 
 	enum { INSIDE, INTERSECT, OUTSIDE } ;
@@ -134,15 +146,6 @@ public:
 	virtual	CValue*				
 	GetReplica(
 	);
-	
-	/**
-	 * Inherited from CValue -- Makes sure any internal 
-	 * data owned by this class is deep copied. Called internally
-	 */
-	virtual	void				
-	ProcessReplica(
-		KX_Camera* replica
-	);
 
 	MT_Transform		GetWorldToCamera() const;
 	MT_Transform		GetCameraToWorld() const;
@@ -181,6 +184,8 @@ public:
 
 	/** Gets the aperture. */
 	float				GetLens() const;
+	/** Gets the ortho scale. */
+	float				GetScale() const;
 	/** Gets the near clip distance. */
 	float				GetCameraNear() const;
 	/** Gets the far clip distance. */
@@ -266,8 +271,32 @@ public:
 	KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop);	
 
 	virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */
+	virtual PyObject* py_getattro_dict();
 	virtual int       py_setattro(PyObject *attr, PyObject *pyvalue);
+	
+	static PyObject*	pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 
+	static PyObject*	pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	
+	static PyObject*	pyattr_get_is_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_is_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	
+	static PyObject*	pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	
+	static PyObject*	pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	
+	static PyObject*	pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 };
 
 #endif //__KX_CAMERA
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
index 354143f1e69fd63d6d09a823a77510325713c7f3..5f7197e31f17e9050fe338c1f6e00bbcaa8c592b 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -82,8 +82,6 @@ GetReplica(
 ) {
 	KX_CameraActuator* replica = new KX_CameraActuator(*this);
 	replica->ProcessReplica();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
 	return replica;
 };
 
@@ -371,12 +369,17 @@ bool KX_CameraActuator::string2axischoice(const char *axisString)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_CameraActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_CameraActuator",
-	sizeof(KX_CameraActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -408,7 +411,7 @@ PyMethodDef KX_CameraActuator::Methods[] = {
 	{"setHeight",(PyCFunction) KX_CameraActuator::sPySetHeight,	METH_VARARGS,	(PY_METHODCHAR)SetHeight_doc},
 	{"getHeight",(PyCFunction) KX_CameraActuator::sPyGetHeight,	METH_NOARGS,	(PY_METHODCHAR)GetHeight_doc},
 	{"setXY"	,(PyCFunction) KX_CameraActuator::sPySetXY,		METH_VARARGS,	(PY_METHODCHAR)SetXY_doc},
-	{"getXY"	,(PyCFunction) KX_CameraActuator::sPyGetXY,		METH_VARARGS,	(PY_METHODCHAR)GetXY_doc},
+	{"getXY"	,(PyCFunction) KX_CameraActuator::sPyGetXY,		METH_NOARGS,	(PY_METHODCHAR)GetXY_doc},
 	{NULL,NULL,NULL,NULL} //Sentinel
 };
 
@@ -417,48 +420,20 @@ PyAttributeDef KX_CameraActuator::Attributes[] = {
 	KX_PYATTRIBUTE_FLOAT_RW("max",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_maxHeight),
 	KX_PYATTRIBUTE_FLOAT_RW("height",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_height),
 	KX_PYATTRIBUTE_BOOL_RW("xy",KX_CameraActuator,m_x),
-	KX_PYATTRIBUTE_DUMMY("object"),
+	KX_PYATTRIBUTE_RW_FUNCTION("object", KX_CameraActuator, pyattr_get_object,	pyattr_set_object),
 	{NULL}
 };
 
 PyObject* KX_CameraActuator::py_getattro(PyObject *attr) {
-	PyObject* object;
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "object")) {
-		if (!m_ob)	Py_RETURN_NONE;
-		else		return m_ob->AddRef();
-	}
-	
-	object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
-int KX_CameraActuator::py_setattro(PyObject *attr, PyObject* value) {
-	int ret;
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "object")) {
-		KX_GameObject *gameobj;
-		
-		if (!ConvertPythonToGameObject(value, &gameobj, true))
-			return 1; // ConvertPythonToGameObject sets the error
-		
-		if (m_ob != NULL)
-			m_ob->UnregisterActuator(this);	
+PyObject* KX_CameraActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
 
-		m_ob = (SCA_IObject*)gameobj;
-		
-		if (m_ob)
-			m_ob->RegisterActuator(this);
-		
-		return 0;
-	}
-	
-	ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+int KX_CameraActuator::py_setattro(PyObject *attr, PyObject* value) {
+	py_setattro_up(SCA_IActuator);
 }
 
 /* get obj  ---------------------------------------------------------- */
@@ -466,35 +441,35 @@ const char KX_CameraActuator::GetObject_doc[] =
 "getObject(name_only = 1)\n"
 "name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
 "\tReturns the object this sensor reacts to.\n";
-PyObject* KX_CameraActuator::PyGetObject(PyObject* self, PyObject* args)
+PyObject* KX_CameraActuator::PyGetObject(PyObject* args)
 {
 	int ret_name_only = 1;
 	
 	ShowDeprecationWarning("getObject()", "the object property");
 	
-	if (!PyArg_ParseTuple(args, "|i", &ret_name_only))
+	if (!PyArg_ParseTuple(args, "|i:getObject", &ret_name_only))
 		return NULL;
 	
 	if (!m_ob)
 		Py_RETURN_NONE;
 	
 	if (ret_name_only)
-		return PyString_FromString(m_ob->GetName());
+		return PyString_FromString(m_ob->GetName().ReadPtr());
 	else
-		return m_ob->AddRef();
+		return m_ob->GetProxy();
 }
 /* set obj  ---------------------------------------------------------- */
 const char KX_CameraActuator::SetObject_doc[] = 
 "setObject(object)\n"
 "\t- object: KX_GameObject, string or None\n"
 "\tSets the object this sensor reacts to.\n";
-PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* value)
+PyObject* KX_CameraActuator::PySetObject(PyObject* value)
 {
 	KX_GameObject *gameobj;
 	
 	ShowDeprecationWarning("setObject()", "the object property");
 	
-	if (!ConvertPythonToGameObject(value, &gameobj, true))
+	if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_CameraActuator"))
 		return NULL; // ConvertPythonToGameObject sets the error
 	
 	if (m_ob != NULL)
@@ -511,9 +486,7 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* value)
 const char KX_CameraActuator::GetMin_doc[] = 
 "getMin\n"
 "\tReturns the minimum value set in the Min: field.\n";
-PyObject* KX_CameraActuator::PyGetMin(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PyGetMin()
 {
 	ShowDeprecationWarning("getMin()", "the min property");
 	return PyFloat_FromDouble(m_minHeight);
@@ -522,13 +495,11 @@ PyObject* KX_CameraActuator::PyGetMin(PyObject* self,
 const char KX_CameraActuator::SetMin_doc[] = 
 "setMin\n"
 "\tSets the minimum value.\n";
-PyObject* KX_CameraActuator::PySetMin(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PySetMin(PyObject* args)
 {
 	ShowDeprecationWarning("setMin()", "the min property");
 	float min;
-	if(PyArg_ParseTuple(args,"f", &min))
+	if(PyArg_ParseTuple(args,"f:setMin", &min))
 	{
 		m_minHeight = min;
 		Py_RETURN_NONE;
@@ -539,9 +510,7 @@ PyObject* KX_CameraActuator::PySetMin(PyObject* self,
 const char KX_CameraActuator::GetMax_doc[] = 
 "getMax\n"
 "\tReturns the maximum value set in the Max: field.\n";
-PyObject* KX_CameraActuator::PyGetMax(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PyGetMax()
 {
 	ShowDeprecationWarning("getMax()", "the max property");
 	return PyFloat_FromDouble(m_maxHeight);
@@ -550,13 +519,11 @@ PyObject* KX_CameraActuator::PyGetMax(PyObject* self,
 const char KX_CameraActuator::SetMax_doc[] = 
 "setMax\n"
 "\tSets the maximum value.\n";
-PyObject* KX_CameraActuator::PySetMax(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PySetMax(PyObject* args)
 {
 	ShowDeprecationWarning("getMax()", "the max property");
 	float max;
-	if(PyArg_ParseTuple(args,"f", &max))
+	if(PyArg_ParseTuple(args,"f:setMax", &max))
 	{
 		m_maxHeight = max;
 		Py_RETURN_NONE;
@@ -567,9 +534,7 @@ PyObject* KX_CameraActuator::PySetMax(PyObject* self,
 const char KX_CameraActuator::GetHeight_doc[] = 
 "getHeight\n"
 "\tReturns the height value set in the height: field.\n";
-PyObject* KX_CameraActuator::PyGetHeight(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PyGetHeight()
 {
 	ShowDeprecationWarning("getHeight()", "the height property");
 	return PyFloat_FromDouble(m_height);
@@ -578,13 +543,11 @@ PyObject* KX_CameraActuator::PyGetHeight(PyObject* self,
 const char KX_CameraActuator::SetHeight_doc[] = 
 "setHeight\n"
 "\tSets the height value.\n";
-PyObject* KX_CameraActuator::PySetHeight(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PySetHeight(PyObject* args)
 {
 	ShowDeprecationWarning("getHeight()", "the height property");
 	float height;
-	if(PyArg_ParseTuple(args,"f", &height))
+	if(PyArg_ParseTuple(args,"f:setHeight", &height))
 	{
 		m_height = height;
 		Py_RETURN_NONE;
@@ -596,13 +559,11 @@ const char KX_CameraActuator::SetXY_doc[] =
 "setXY\n"
 "\tSets axis the camera tries to get behind.\n"
 "\t1=x, 0=y\n";
-PyObject* KX_CameraActuator::PySetXY(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PySetXY(PyObject* args)
 {
 	ShowDeprecationWarning("setXY()", "the xy property");
 	int value;
-	if(PyArg_ParseTuple(args,"i", &value))
+	if(PyArg_ParseTuple(args,"i:setXY", &value))
 	{
 		m_x = value != 0;
 		Py_RETURN_NONE;
@@ -615,12 +576,36 @@ const char KX_CameraActuator::GetXY_doc[] =
 "getXY\n"
 "\tGets the axis the camera tries to get behind.\n"
 "\tTrue = X, False = Y\n";
-PyObject* KX_CameraActuator::PyGetXY(PyObject* self,
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PyGetXY()
 {
 	ShowDeprecationWarning("getXY()", "the xy property");
 	return PyInt_FromLong(m_x);
 }
 
+PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_CameraActuator* self= static_cast<KX_CameraActuator*>(self_v);
+	if (self->m_ob==NULL)
+		Py_RETURN_NONE;
+	else
+		return self->m_ob->GetProxy();
+}
+
+int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_CameraActuator* self= static_cast<KX_CameraActuator*>(self_v);
+	KX_GameObject *gameobj;
+	
+	if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_CameraActuator"))
+		return 1; // ConvertPythonToGameObject sets the error
+	
+	if (self->m_ob)
+		self->m_ob->UnregisterActuator(self);	
+
+	if ((self->m_ob = (SCA_IObject*)gameobj))
+		self->m_ob->RegisterActuator(self);
+	
+	return 0;
+}
+
 /* eof */
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h
index 5d7473a5bf08b256920cb75f8086dda44f4f153b..efa4e2f38d79d07eec2bb5712aa8b59451fa711c 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.h
+++ b/source/gameengine/Ketsji/KX_CameraActuator.h
@@ -121,20 +121,24 @@ private :
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject* value);
 
 	/* set object to look at */
 	KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject);
 	/* get current object  */
 	KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,GetObject);
-	KX_PYMETHOD_DOC(KX_CameraActuator,SetMin);
-	KX_PYMETHOD_DOC(KX_CameraActuator,GetMin);
-	KX_PYMETHOD_DOC(KX_CameraActuator,SetMax);
-	KX_PYMETHOD_DOC(KX_CameraActuator,GetMax);
-	KX_PYMETHOD_DOC(KX_CameraActuator,SetHeight);
-	KX_PYMETHOD_DOC(KX_CameraActuator,GetHeight);
-	KX_PYMETHOD_DOC(KX_CameraActuator,SetXY);
-	KX_PYMETHOD_DOC(KX_CameraActuator,GetXY);
+	KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,SetMin);
+	KX_PYMETHOD_DOC_NOARGS(KX_CameraActuator,GetMin);
+	KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,SetMax);
+	KX_PYMETHOD_DOC_NOARGS(KX_CameraActuator,GetMax);
+	KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,SetHeight);
+	KX_PYMETHOD_DOC_NOARGS(KX_CameraActuator,GetHeight);
+	KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,SetXY);
+	KX_PYMETHOD_DOC_NOARGS(KX_CameraActuator,GetXY);
+	
+	static PyObject*	pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 
 };
 
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
index feee851bb01f3a20c3ecc049652d00b9a4081628..c9cb8e1b942ac111af256be21e0c6bc091aab7fa 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -36,6 +36,7 @@
 #include "MT_Matrix3x3.h"
 #include "KX_GameObject.h"
 #include "KX_RayCast.h"
+#include "blendef.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -57,19 +58,21 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj,
 											 char *property,
 											 PyTypeObject* T) : 
 	SCA_IActuator(gameobj, T),
-	m_refDirection(refDir),
+	m_refDirVector(refDir),
 	m_currentTime(0)
 {
+	m_refDirection[0] = refDir[0];
+	m_refDirection[1] = refDir[1];
+	m_refDirection[2] = refDir[2];
 	m_posDampTime = posDampTime;
 	m_rotDampTime = rotDampTime;
 	m_locrot   = locrotxyz;
 	m_option = option;
 	m_activeTime = time;
 	if (property) {
-		strncpy(m_property, property, sizeof(m_property));
-		m_property[sizeof(m_property)-1] = 0;
+		m_property = property;
 	} else {
-		m_property[0] = 0;
+		m_property = "";
 	}
 	/* The units of bounds are determined by the type of constraint. To      */
 	/* make the constraint application easier and more transparent later on, */
@@ -80,13 +83,16 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj,
 	case KX_ACT_CONSTRAINT_ORIY:
 	case KX_ACT_CONSTRAINT_ORIZ:
 		{
-			MT_Scalar len = m_refDirection.length();
+			MT_Scalar len = m_refDirVector.length();
 			if (MT_fuzzyZero(len)) {
 				// missing a valid direction
 				std::cout << "WARNING: Constraint actuator " << GetName() << ":  There is no valid reference direction!" << std::endl;
 				m_locrot = KX_ACT_CONSTRAINT_NODEF;
 			} else {
-				m_refDirection /= len;
+				m_refDirection[0] /= len;
+				m_refDirection[1] /= len;
+				m_refDirection[2] /= len;
+				m_refDirVector /= len;
 			}
 			m_minimumBound = cos(minBound);
 			m_maximumBound = cos(maxBound);
@@ -116,7 +122,7 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* resu
 	
 	bool bFound = false;
 
-	if (m_property[0] == 0)
+	if (m_property.IsEmpty())
 	{
 		bFound = true;
 	}
@@ -126,7 +132,7 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* resu
 		{
 			if (client->m_auxilary_info)
 			{
-				bFound = !strcmp(m_property, ((char*)client->m_auxilary_info));
+				bFound = !strcmp(m_property.Ptr(), ((char*)client->m_auxilary_info));
 			}
 		}
 		else
@@ -209,7 +215,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
 			if ((m_maximumBound < (1.0f-FLT_EPSILON)) || (m_minimumBound < (1.0f-FLT_EPSILON))) {
 				// reference direction needs to be evaluated
 				// 1. get the cosine between current direction and target
-				cosangle = direction.dot(m_refDirection);
+				cosangle = direction.dot(m_refDirVector);
 				if (cosangle >= (m_maximumBound-FLT_EPSILON) && cosangle <= (m_minimumBound+FLT_EPSILON)) {
 					// no change to do
 					result = true;
@@ -218,27 +224,27 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
 				// 2. define a new reference direction
 				//    compute local axis with reference direction as X and
 				//    Y in direction X refDirection plane
-				MT_Vector3 zaxis = m_refDirection.cross(direction);
+				MT_Vector3 zaxis = m_refDirVector.cross(direction);
 				if (MT_fuzzyZero2(zaxis.length2())) {
 					// direction and refDirection are identical,
 					// choose any other direction to define plane
 					if (direction[0] < 0.9999)
-						zaxis = m_refDirection.cross(MT_Vector3(1.0,0.0,0.0));
+						zaxis = m_refDirVector.cross(MT_Vector3(1.0,0.0,0.0));
 					else
-						zaxis = m_refDirection.cross(MT_Vector3(0.0,1.0,0.0));
+						zaxis = m_refDirVector.cross(MT_Vector3(0.0,1.0,0.0));
 				}
-				MT_Vector3 yaxis = zaxis.cross(m_refDirection);
+				MT_Vector3 yaxis = zaxis.cross(m_refDirVector);
 				yaxis.normalize();
 				if (cosangle > m_minimumBound) {
 					// angle is too close to reference direction,
 					// choose a new reference that is exactly at minimum angle
-					refDirection = m_minimumBound * m_refDirection + m_minimumSine * yaxis;
+					refDirection = m_minimumBound * m_refDirVector + m_minimumSine * yaxis;
 				} else {
 					// angle is too large, choose new reference direction at maximum angle
-					refDirection = m_maximumBound * m_refDirection + m_maximumSine * yaxis;
+					refDirection = m_maximumBound * m_refDirVector + m_maximumSine * yaxis;
 				}
 			} else {
-				refDirection = m_refDirection;
+				refDirection = m_refDirVector;
 			}
 			// apply damping on the direction
 			direction = filter*direction + (1.0-filter)*refDirection;
@@ -470,7 +476,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
 					// Fh force is stored in m_maximum
 					MT_Scalar springForce = springExtent * m_maximumBound;
 					// damping is stored in m_refDirection [0] = damping, [1] = rot damping
-					MT_Scalar springDamp = relativeVelocityRay * m_refDirection[0];
+					MT_Scalar springDamp = relativeVelocityRay * m_refDirVector[0];
 					MT_Vector3 newVelocity = spc->GetLinearVelocity()-(springForce+springDamp)*direction;
 					if (m_option & KX_ACT_CONSTRAINT_NORMAL)
 					{
@@ -483,7 +489,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
 						MT_Vector3 angVelocity = spc->GetAngularVelocity();
 						// remove component that is parallel to normal
 						angVelocity -= angVelocity.dot(newnormal)*newnormal;
-						MT_Vector3 angDamp = angVelocity * ((m_refDirection[1]>MT_EPSILON)?m_refDirection[1]:m_refDirection[0]);
+						MT_Vector3 angDamp = angVelocity * ((m_refDirVector[1]>MT_EPSILON)?m_refDirVector[1]:m_refDirVector[0]);
 						spc->SetAngularVelocity(spc->GetAngularVelocity()+(angSpring-angDamp), false);
 					}
 				} else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) {
@@ -560,12 +566,17 @@ bool KX_ConstraintActuator::IsValidMode(KX_ConstraintActuator::KX_CONSTRAINTTYPE
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_ConstraintActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_ConstraintActuator",
-	sizeof(KX_ConstraintActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -587,6 +598,7 @@ PyParentObject KX_ConstraintActuator::Parents[] = {
 };
 
 PyMethodDef KX_ConstraintActuator::Methods[] = {
+	// Deprecated -->
 	{"setDamp", (PyCFunction) KX_ConstraintActuator::sPySetDamp, METH_VARARGS, (PY_METHODCHAR)SetDamp_doc},
 	{"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_NOARGS, (PY_METHODCHAR)GetDamp_doc},
 	{"setRotDamp", (PyCFunction) KX_ConstraintActuator::sPySetRotDamp, METH_VARARGS, (PY_METHODCHAR)SetRotDamp_doc},
@@ -609,28 +621,63 @@ PyMethodDef KX_ConstraintActuator::Methods[] = {
 	{"getRayLength", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, (PY_METHODCHAR)GetRayLength_doc},
 	{"setLimit", (PyCFunction) KX_ConstraintActuator::sPySetLimit, METH_VARARGS, (PY_METHODCHAR)SetLimit_doc},
 	{"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_NOARGS, (PY_METHODCHAR)GetLimit_doc},
+	// <--
 	{NULL,NULL} //Sentinel
 };
 
 PyAttributeDef KX_ConstraintActuator::Attributes[] = {
+	KX_PYATTRIBUTE_INT_RW("damp",0,100,true,KX_ConstraintActuator,m_posDampTime),
+	KX_PYATTRIBUTE_INT_RW("rotDamp",0,100,true,KX_ConstraintActuator,m_rotDampTime),
+	KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK("direction",-MAXFLOAT,MAXFLOAT,KX_ConstraintActuator,m_refDirection,3,pyattr_check_direction),
+	KX_PYATTRIBUTE_INT_RW("option",0,0xFFFF,false,KX_ConstraintActuator,m_option),
+	KX_PYATTRIBUTE_INT_RW("time",0,1000,true,KX_ConstraintActuator,m_activeTime),
+	KX_PYATTRIBUTE_STRING_RW("property",0,32,true,KX_ConstraintActuator,m_property),
+	KX_PYATTRIBUTE_FLOAT_RW("min",-MAXFLOAT,MAXFLOAT,KX_ConstraintActuator,m_minimumBound),
+	KX_PYATTRIBUTE_FLOAT_RW("distance",-MAXFLOAT,MAXFLOAT,KX_ConstraintActuator,m_minimumBound),
+	KX_PYATTRIBUTE_FLOAT_RW("max",-MAXFLOAT,MAXFLOAT,KX_ConstraintActuator,m_maximumBound),
+	KX_PYATTRIBUTE_FLOAT_RW("rayLength",0,2000.f,KX_ConstraintActuator,m_maximumBound),
+	KX_PYATTRIBUTE_INT_RW("limit",KX_ConstraintActuator::KX_ACT_CONSTRAINT_NODEF+1,KX_ConstraintActuator::KX_ACT_CONSTRAINT_MAX-1,false,KX_ConstraintActuator,m_locrot),
 	{ NULL }	//Sentinel
 };
 
-PyObject* KX_ConstraintActuator::py_getattro(PyObject *attr) {
+PyObject* KX_ConstraintActuator::py_getattro(PyObject *attr) 
+{
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_ConstraintActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_ConstraintActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+	py_setattro_up(SCA_IActuator);
+}
+
+
+int KX_ConstraintActuator::pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_ConstraintActuator* act = static_cast<KX_ConstraintActuator*>(self);
+	MT_Vector3 dir(act->m_refDirection);
+	MT_Scalar len = dir.length();
+	if (MT_fuzzyZero(len)) {
+		PyErr_SetString(PyExc_ValueError, "actuator.direction = vec: KX_ConstraintActuator, invalid direction");
+		return 1;
+	}
+	act->m_refDirVector = dir/len;
+	return 0;	
+}
+
 /* 2. setDamp                                                                */
 const char KX_ConstraintActuator::SetDamp_doc[] = 
 "setDamp(duration)\n"
 "\t- duration: integer\n"
 "\tSets the time constant of the orientation and distance constraint.\n"
 "\tIf the duration is negative, it is set to 0.\n";
-PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self, 
-										   PyObject* args, 
-										   PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PySetDamp(PyObject* args) {
+	ShowDeprecationWarning("setDamp()", "the damp property");
 	int dampArg;
-	if(!PyArg_ParseTuple(args, "i", &dampArg)) {
+	if(!PyArg_ParseTuple(args, "i:setDamp", &dampArg)) {
 		return NULL;		
 	}
 	
@@ -643,7 +690,8 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self,
 const char KX_ConstraintActuator::GetDamp_doc[] = 
 "getDamp()\n"
 "\tReturns the damping parameter.\n";
-PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self){
+PyObject* KX_ConstraintActuator::PyGetDamp(){
+	ShowDeprecationWarning("getDamp()", "the damp property");
 	return PyInt_FromLong(m_posDampTime);
 }
 
@@ -653,11 +701,10 @@ const char KX_ConstraintActuator::SetRotDamp_doc[] =
 "\t- duration: integer\n"
 "\tSets the time constant of the orientation constraint.\n"
 "\tIf the duration is negative, it is set to 0.\n";
-PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self, 
-										      PyObject* args, 
-										      PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* args) {
+	ShowDeprecationWarning("setRotDamp()", "the rotDamp property");
 	int dampArg;
-	if(!PyArg_ParseTuple(args, "i", &dampArg)) {
+	if(!PyArg_ParseTuple(args, "i:setRotDamp", &dampArg)) {
 		return NULL;		
 	}
 	
@@ -670,7 +717,8 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self,
 const char KX_ConstraintActuator::GetRotDamp_doc[] = 
 "getRotDamp()\n"
 "\tReturns the damping time for application of the constraint.\n";
-PyObject* KX_ConstraintActuator::PyGetRotDamp(PyObject* self){
+PyObject* KX_ConstraintActuator::PyGetRotDamp(){
+	ShowDeprecationWarning("getRotDamp()", "the rotDamp property");
 	return PyInt_FromLong(m_rotDampTime);
 }
 
@@ -679,14 +727,13 @@ const char KX_ConstraintActuator::SetDirection_doc[] =
 "setDirection(vector)\n"
 "\t- vector: 3-tuple\n"
 "\tSets the reference direction in world coordinate for the orientation constraint.\n";
-PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self, 
-										        PyObject* args, 
-										        PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PySetDirection(PyObject* args) {
+	ShowDeprecationWarning("setDirection()", "the direction property");
 	float x, y, z;
 	MT_Scalar len;
 	MT_Vector3 dir;
 
-	if(!PyArg_ParseTuple(args, "(fff)", &x, &y, &z)) {
+	if(!PyArg_ParseTuple(args, "(fff):setDirection", &x, &y, &z)) {
 		return NULL;		
 	}
 	dir[0] = x;
@@ -697,7 +744,10 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self,
 		std::cout << "Invalid direction" << std::endl;
 		return NULL;
 	}
-	m_refDirection = dir/len;
+	m_refDirVector = dir/len;
+	m_refDirection[0] = x/len;
+	m_refDirection[1] = y/len;
+	m_refDirection[2] = z/len;
 
 	Py_RETURN_NONE;
 }
@@ -705,12 +755,13 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self,
 const char KX_ConstraintActuator::GetDirection_doc[] = 
 "getDirection()\n"
 "\tReturns the reference direction of the orientation constraint as a 3-tuple.\n";
-PyObject* KX_ConstraintActuator::PyGetDirection(PyObject* self){
+PyObject* KX_ConstraintActuator::PyGetDirection(){
+	ShowDeprecationWarning("getDirection()", "the direction property");
 	PyObject *retVal = PyList_New(3);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_refDirection[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_refDirection[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_refDirection[2]));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_refDirection[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_refDirection[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_refDirection[2]));
 	return retVal;
 }
 
@@ -724,11 +775,10 @@ const char KX_ConstraintActuator::SetOption_doc[] =
 "\t\t128 : Detect material rather than property\n"
 "\t\t256 : No deactivation if ray does not hit target\n"
 "\t\t512 : Activate distance control\n";
-PyObject* KX_ConstraintActuator::PySetOption(PyObject* self, 
-										     PyObject* args, 
-										     PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PySetOption(PyObject* args) {
+	ShowDeprecationWarning("setOption()", "the option property");
 	int option;
-	if(!PyArg_ParseTuple(args, "i", &option)) {
+	if(!PyArg_ParseTuple(args, "i:setOption", &option)) {
 		return NULL;		
 	}
 	
@@ -740,7 +790,8 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self,
 const char KX_ConstraintActuator::GetOption_doc[] = 
 "getOption()\n"
 "\tReturns the option parameter.\n";
-PyObject* KX_ConstraintActuator::PyGetOption(PyObject* self){
+PyObject* KX_ConstraintActuator::PyGetOption(){
+	ShowDeprecationWarning("getOption()", "the option property");
 	return PyInt_FromLong(m_option);
 }
 
@@ -751,11 +802,10 @@ const char KX_ConstraintActuator::SetTime_doc[] =
 "\tSets the activation time of the actuator.\n"
 "\tThe actuator disables itself after this many frame.\n"
 "\tIf set to 0 or negative, the actuator is not limited in time.\n";
-PyObject* KX_ConstraintActuator::PySetTime(PyObject* self, 
-										   PyObject* args, 
-										   PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PySetTime(PyObject* args) {
+	ShowDeprecationWarning("setTime()", "the time property");
 	int t;
-	if(!PyArg_ParseTuple(args, "i", &t)) {
+	if(!PyArg_ParseTuple(args, "i:setTime", &t)) {
 		return NULL;		
 	}
 	
@@ -769,7 +819,8 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self,
 const char KX_ConstraintActuator::GetTime_doc[] = 
 "getTime()\n"
 "\tReturns the time parameter.\n";
-PyObject* KX_ConstraintActuator::PyGetTime(PyObject* self){
+PyObject* KX_ConstraintActuator::PyGetTime(){
+	ShowDeprecationWarning("getTime()", "the time property");
 	return PyInt_FromLong(m_activeTime);
 }
 
@@ -779,18 +830,16 @@ const char KX_ConstraintActuator::SetProperty_doc[] =
 "\t- property: string\n"
 "\tSets the name of the property or material for the ray detection of the distance constraint.\n"
 "\tIf empty, the ray will detect any collisioning object.\n";
-PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self, 
-										       PyObject* args, 
-										       PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PySetProperty(PyObject* args) {
+	ShowDeprecationWarning("setProperty()", "the 'property' property");
 	char *property;
-	if (!PyArg_ParseTuple(args, "s", &property)) {
+	if (!PyArg_ParseTuple(args, "s:setProperty", &property)) {
 		return NULL;
 	}
 	if (property == NULL) {
-		m_property[0] = 0;
+		m_property = "";
 	} else {
-		strncpy(m_property, property, sizeof(m_property));
-		m_property[sizeof(m_property)-1] = 0;
+		m_property = property;
 	}
 
 	Py_RETURN_NONE;
@@ -799,8 +848,9 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self,
 const char KX_ConstraintActuator::GetProperty_doc[] = 
 "getProperty()\n"
 "\tReturns the property parameter.\n";
-PyObject* KX_ConstraintActuator::PyGetProperty(PyObject* self){
-	return PyString_FromString(m_property);
+PyObject* KX_ConstraintActuator::PyGetProperty(){
+	ShowDeprecationWarning("getProperty()", "the 'property' property");
+	return PyString_FromString(m_property.Ptr());
 }
 
 /* 4. setDistance                                                                 */
@@ -814,11 +864,10 @@ const char KX_ConstraintActuator::SetMin_doc[] =
 "\t- lower_bound: float\n"
 "\tSets the lower value of the interval to which the value\n"
 "\tis clipped.\n";
-PyObject* KX_ConstraintActuator::PySetMin(PyObject* self, 
-										  PyObject* args, 
-										  PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PySetMin(PyObject* args) {
+	ShowDeprecationWarning("setMin() or setDistance()", "the min or distance property");
 	float minArg;
-	if(!PyArg_ParseTuple(args, "f", &minArg)) {
+	if(!PyArg_ParseTuple(args, "f:setMin", &minArg)) {
 		return NULL;		
 	}
 
@@ -844,7 +893,8 @@ const char KX_ConstraintActuator::GetMin_doc[] =
 "getMin()\n"
 "\tReturns the lower value of the interval to which the value\n"
 "\tis clipped.\n";
-PyObject* KX_ConstraintActuator::PyGetMin(PyObject* self) {
+PyObject* KX_ConstraintActuator::PyGetMin() {
+	ShowDeprecationWarning("getMin() or getDistance()", "the min or distance property");
 	return PyFloat_FromDouble(m_minimumBound);
 }
 
@@ -859,11 +909,10 @@ const char KX_ConstraintActuator::SetMax_doc[] =
 "\t- upper_bound: float\n"
 "\tSets the upper value of the interval to which the value\n"
 "\tis clipped.\n";
-PyObject* KX_ConstraintActuator::PySetMax(PyObject* self, 
-										  PyObject* args, 
-										  PyObject* kwds){
+PyObject* KX_ConstraintActuator::PySetMax(PyObject* args){
+	ShowDeprecationWarning("setMax() or setRayLength()", "the max or rayLength property");
 	float maxArg;
-	if(!PyArg_ParseTuple(args, "f", &maxArg)) {
+	if(!PyArg_ParseTuple(args, "f:setMax", &maxArg)) {
 		return NULL;		
 	}
 
@@ -889,7 +938,8 @@ const char KX_ConstraintActuator::GetMax_doc[] =
 "getMax()\n"
 "\tReturns the upper value of the interval to which the value\n"
 "\tis clipped.\n";
-PyObject* KX_ConstraintActuator::PyGetMax(PyObject* self) {
+PyObject* KX_ConstraintActuator::PyGetMax() {
+	ShowDeprecationWarning("getMax() or getRayLength()", "the max or rayLength property");
 	return PyFloat_FromDouble(m_maximumBound);
 }
 
@@ -912,11 +962,10 @@ const char KX_ConstraintActuator::SetLimit_doc[] =
 "\t  14 : Align Y axis\n"
 "\t  15 : Align Z axis\n"
 "\tSets the type of constraint.\n";
-PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PySetLimit(PyObject* args) {
+	ShowDeprecationWarning("setLimit()", "the limit property");
 	int locrotArg;
-	if(!PyArg_ParseTuple(args, "i", &locrotArg)) {
+	if(!PyArg_ParseTuple(args, "i:setLimit", &locrotArg)) {
 		return NULL;		
 	}
 	
@@ -928,7 +977,8 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self,
 const char KX_ConstraintActuator::GetLimit_doc[] = 
 "getLimit()\n"
 "\tReturns the type of constraint.\n";
-PyObject* KX_ConstraintActuator::PyGetLimit(PyObject* self) {
+PyObject* KX_ConstraintActuator::PyGetLimit() {
+	ShowDeprecationWarning("setLimit()", "the limit property");
 	return PyInt_FromLong(m_locrot);
 }
 
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h
index 193400fbf2b27b8390e466d279b6323c2ae5a803..40607b449478a54519cf0a767f9cdfb254e44e60 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.h
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h
@@ -56,7 +56,8 @@ protected:
 	// sinus of maximum angle
 	float m_maximumSine;
 	// reference direction
-	MT_Vector3 m_refDirection;
+	float m_refDirection[3];
+	MT_Vector3 m_refDirVector;	// same as m_refDirection
 	// locrotxyz choice (pick one): only one choice allowed at a time!
 	int m_locrot;
 	// active time of actuator
@@ -65,7 +66,7 @@ protected:
 	// option
 	int m_option;
 	// property to check
-	char m_property[32];
+	STR_String m_property;
 	// hit object
 	KX_GameObject* m_hitObject;
 
@@ -131,8 +132,6 @@ protected:
 	virtual CValue* GetReplica() {
 		KX_ConstraintActuator* replica = new KX_ConstraintActuator(*this);
 		replica->ProcessReplica();
-		// this will copy properties and so on...
-		CValue::AddDataToReplica(replica);
 		return replica;
 	};
 
@@ -143,28 +142,33 @@ protected:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
+	virtual int py_setattro(PyObject *attr, PyObject* value);
 
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDamp);
+	static int pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static int pyattr_check_min(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetDamp);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDamp);
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetRotDamp);
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetRotDamp);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetRotDamp);
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDirection);
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetDirection);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDirection);
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetOption);
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetOption);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetOption);
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetTime);
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetTime);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetTime);
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetProperty);
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetProperty);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetProperty);
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMin);
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetMin);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMin);
 	static const char SetDistance_doc[];
 	static const char GetDistance_doc[];
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMax);
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetMax);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMax);
 	static const char SetRayLength_doc[];
 	static const char GetRayLength_doc[];
-	KX_PYMETHOD_DOC(KX_ConstraintActuator,SetLimit);
+	KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetLimit);
 	KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetLimit);
 };
 
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
index edd6e991e9f6295d11fee839b1601fdd36e6e31f..c63f9e57ed22d86b731cbfcea86ea500636e1e58 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
@@ -48,33 +48,25 @@ KX_ConstraintWrapper::KX_ConstraintWrapper(
 KX_ConstraintWrapper::~KX_ConstraintWrapper()
 {
 }
-//python integration methods
-PyObject* KX_ConstraintWrapper::PyTestMethod(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
-{
-	
-	Py_RETURN_NONE;
-}
 
-PyObject* KX_ConstraintWrapper::PyGetConstraintId(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_ConstraintWrapper::PyGetConstraintId(PyObject* args, PyObject* kwds)
 {
 	return PyInt_FromLong(m_constraintId);
 }
 
-
-
-
 //python specific stuff
 PyTypeObject KX_ConstraintWrapper::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_ConstraintWrapper",
-		sizeof(KX_ConstraintWrapper),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -92,45 +84,28 @@ PyParentObject KX_ConstraintWrapper::Parents[] = {
 	NULL
 };
 
-PyObject*	KX_ConstraintWrapper::py_getattro(PyObject *attr)
+//here you can search for existing data members (like mass,friction etc.)
+PyObject* KX_ConstraintWrapper::py_getattro(PyObject *attr)
 {
-	//here you can search for existing data members (like mass,friction etc.)
 	py_getattro_up(PyObjectPlus);
 }
 
-int	KX_ConstraintWrapper::py_setattro(PyObject *attr,PyObject* pyobj)
-{
-	int result = 1;
-
-	if (PyList_Check(pyobj))
-	{
-		result = 0;
-	}
-	if (PyFloat_Check(pyobj))
-	{
-		result = 0;
+PyObject* KX_ConstraintWrapper::py_getattro_dict() {
+	py_getattro_dict_up(PyObjectPlus);
+}
 
-	}
-	if (PyInt_Check(pyobj))
-	{
-		result = 0;
-	}
-	if (PyString_Check(pyobj))
-	{
-		result = 0;
-	}
-	if (result)
-		result = PyObjectPlus::py_setattro(attr,pyobj);
-	return result;
+int	KX_ConstraintWrapper::py_setattro(PyObject *attr,PyObject* value)
+{
+	py_setattro_up(PyObjectPlus);	
 };
 
 
 PyMethodDef KX_ConstraintWrapper::Methods[] = {
-	{"testMethod",(PyCFunction) KX_ConstraintWrapper::sPyTestMethod, METH_VARARGS},
 	{"getConstraintId",(PyCFunction) KX_ConstraintWrapper::sPyGetConstraintId, METH_VARARGS},
 	{NULL,NULL} //Sentinel
 };
 
 PyAttributeDef KX_ConstraintWrapper::Attributes[] = {
+	//KX_PYATTRIBUTE_TODO("constraintId"),
 	{ NULL }	//Sentinel
 };
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
index 6e67d842cb6d175b194203c54e0cbfa49e6d5bf3..3270d57188d719f55be5f7d2d1ba5e74d3b177f2 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
@@ -36,6 +36,7 @@ class	KX_ConstraintWrapper : public PyObjectPlus
 {
 	Py_Header;
 	virtual PyObject*		py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int 			py_setattro(PyObject *attr, PyObject *value);
 public:
 	KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type);
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
index 3534500e61952653b442a09e7f96b462311e4778..40c715974f90fc7972dce70f631430bf2588941f 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
@@ -124,6 +124,7 @@ struct KX_ObjectProperties
 	float	m_soft_kAHR;			/* Anchors hardness [0,1] */
 	int		m_soft_collisionflags;	/* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */
 	int		m_soft_numclusteriterations;	/* number of iterations to refine collision clusters*/
+	float   m_soft_welding;			/*   threshold to remove duplicate/nearby vertices */
 
 	/////////////////////////
 	
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index 03149859f4d2d40c782b87ae7e308b0cada3be15..1943c43625877affbe87067a0cc8b2ba36c9496d 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -34,7 +34,7 @@
 
 // defines USE_ODE to choose physics engine
 #include "KX_ConvertPhysicsObject.h"
-#include "KX_GameObject.h"
+#include "BL_DeformableGameObject.h"
 #include "RAS_MeshObject.h"
 #include "KX_Scene.h"
 #include "SYS_System.h"
@@ -670,11 +670,11 @@ void	KX_ConvertODEEngineObject(KX_GameObject* gameobj,
 							
 	class KX_SoftBodyDeformer : public RAS_Deformer
 	{
-		class RAS_MeshObject*	m_pMeshObject;
-		class KX_GameObject*	m_gameobj;
+		class RAS_MeshObject*			m_pMeshObject;
+		class BL_DeformableGameObject*	m_gameobj;
 
 	public:
-		KX_SoftBodyDeformer(RAS_MeshObject*	pMeshObject,KX_GameObject*	gameobj)
+		KX_SoftBodyDeformer(RAS_MeshObject*	pMeshObject,BL_DeformableGameObject*	gameobj)
 			:m_pMeshObject(pMeshObject),
 			m_gameobj(gameobj)
 		{
@@ -687,7 +687,15 @@ void	KX_ConvertODEEngineObject(KX_GameObject* gameobj,
 		};
 		virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
 		{
-			//printf("relink\n");
+			void **h_obj = (*map)[m_gameobj];
+
+			if (h_obj) {
+				m_gameobj = (BL_DeformableGameObject*)(*h_obj);
+				m_pMeshObject = m_gameobj->GetMesh(0);
+			} else {
+				m_gameobj = NULL;
+				m_pMeshObject = NULL;
+			}
 		}
 		virtual bool Apply(class RAS_IPolyMaterial *polymat)
 		{
@@ -751,12 +759,23 @@ void	KX_ConvertODEEngineObject(KX_GameObject* gameobj,
 			//printf("update\n");
 			return true;//??
 		}
-		virtual RAS_Deformer *GetReplica(class KX_GameObject* replica)
+		virtual bool UpdateBuckets(void)
 		{
-			KX_SoftBodyDeformer* deformer = new KX_SoftBodyDeformer(replica->GetMesh(0),replica);
-			return deformer;
+			// this is to update the mesh slots outside the rasterizer, 
+			// no need to do it for this deformer, it's done in any case in Apply()
+			return false;
 		}
 
+		virtual RAS_Deformer *GetReplica()
+		{
+			KX_SoftBodyDeformer* deformer = new KX_SoftBodyDeformer(*this);
+			deformer->ProcessReplica();
+			return deformer;
+		}
+		virtual void ProcessReplica()
+		{
+			// we have two pointers to deal with but we cannot do it now, will be done in Relink
+		}
 		virtual bool SkipVertexTransform()
 		{
 			return true;
@@ -801,6 +820,8 @@ void	KX_ConvertBulletObject(	class	KX_GameObject* gameobj,
 	ci.m_gravity = btVector3(0,0,0);
 	ci.m_localInertiaTensor =btVector3(0,0,0);
 	ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f;
+	ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min;
+	ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max;
 	ci.m_margin = objprop->m_margin;
 	shapeInfo->m_radius = objprop->m_radius;
 	isbulletdyna = objprop->m_dyna;
@@ -884,7 +905,9 @@ void	KX_ConvertBulletObject(	class	KX_GameObject* gameobj,
 
 				// Soft bodies require welding. Only avoid remove doubles for non-soft bodies!
 				if (objprop->m_softbody)
-					shapeInfo->setVertexWeldingThreshold1(0.01f); //todo: expose this to the UI
+				{
+					shapeInfo->setVertexWeldingThreshold1(objprop->m_soft_welding); //todo: expose this to the UI
+				}
 
 				bm = shapeInfo->CreateBulletShape();
 				//no moving concave meshes, so don't bother calculating inertia
@@ -1185,9 +1208,8 @@ void	KX_ConvertBulletObject(	class	KX_GameObject* gameobj,
 		if (softBody && gameobj->GetMesh(0))//only the first mesh, if any
 		{
 			//should be a mesh then, so add a soft body deformer
-			KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer( gameobj->GetMesh(0),gameobj);
+			KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer( gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj);
 			gameobj->SetDeformer(softbodyDeformer);
-			
 		}
 	}
 
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index 3485d0f506fd97eece571e7ac544d073c27c411f..25efe0a59c91fdfd337fb23889eafe84b7b572cb 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -33,7 +33,6 @@ Developed as part of a Research and Development project for SAT - La Soci
 #include "BLI_arithb.h"
 
 #include "GL/glew.h"
-#include "GL/glu.h"
 
 // constructor
 KX_Dome::KX_Dome (
@@ -53,20 +52,21 @@ KX_Dome::KX_Dome (
 	struct Text* warptext
 
 ):
-	m_canvas(canvas),
-	m_rasterizer(rasterizer),
-	m_rendertools(rendertools),
-	m_engine(engine),
+	dlistSupported(false),
+	canvaswidth(-1), canvasheight(-1),
 	m_drawingmode(engine->GetDrawType()),
 	m_size(size),
 	m_resolution(res),
 	m_mode(mode),
 	m_angle(angle),
 	m_resbuffer(resbuf),
-	canvaswidth(-1), canvasheight(-1),
-	dlistSupported(false)
+	m_canvas(canvas),
+	m_rasterizer(rasterizer),
+	m_rendertools(rendertools),
+	m_engine(engine)
 {
 	warp.usemesh = false;
+	fboSupported = false;
 
 	if (mode >= DOME_NUM_MODES)
 		m_mode = DOME_FISHEYE;
@@ -108,15 +108,9 @@ KX_Dome::KX_Dome (
 				CreateMeshDome250();
 				m_numfaces = 5;
 			} break;
-		case DOME_TRUNCATED:
-			cubetop.resize(1);
-			cubebottom.resize(1);
-			cubeleft.resize(2);
-			cuberight.resize(2);
-
-			m_angle = 180;
-			CreateMeshDome180();
-			m_numfaces = 4;
+		case DOME_ENVMAP:
+			m_angle = 360;
+			m_numfaces = 6;
 			break;
 		case DOME_PANORAM_SPH:
 			cubeleft.resize(2);
@@ -130,6 +124,25 @@ KX_Dome::KX_Dome (
 			CreateMeshPanorama();
 			m_numfaces = 6;
 			break;
+		default: //DOME_TRUNCATED_DOWN and DOME_TRUNCATED_UP
+			if (m_angle <= 180){
+				cubetop.resize(1);
+				cubebottom.resize(1);
+				cubeleft.resize(2);
+				cuberight.resize(2);
+
+				CreateMeshDome180();
+				m_numfaces = 4;
+			}else if (m_angle > 180){
+				cubetop.resize(2);
+				cubebottom.resize(2);
+				cubeleft.resize(2);
+				cubefront.resize(2);
+				cuberight.resize(2);
+
+				CreateMeshDome250();
+				m_numfaces = 5;
+			} break;
 	}
 
 	m_numimages =(warp.usemesh?m_numfaces+1:m_numfaces);
@@ -138,23 +151,27 @@ KX_Dome::KX_Dome (
 
 	CreateGLImages();
 
+	if(warp.usemesh)
+		fboSupported = CreateFBO();
+
 	dlistSupported = CreateDL();
 }
 
 // destructor
 KX_Dome::~KX_Dome (void)
 {
-	GLuint m_numimages = m_numfaces;
-
 	ClearGLImages();
 
+	if(fboSupported)
+		glDeleteFramebuffersEXT(1, &warp.fboId);
+
 	if(dlistSupported)
 		glDeleteLists(dlistId, (GLsizei) m_numimages);
 }
 
 void KX_Dome::SetViewPort(GLuint viewport[4])
 {
-	if(canvaswidth != m_canvas->GetWidth() || canvasheight != m_canvas->GetHeight())
+	if(canvaswidth != m_viewport.GetWidth() || canvasheight != m_viewport.GetHeight())
 	{
 		m_viewport.SetLeft(viewport[0]); 
 		m_viewport.SetBottom(viewport[1]);
@@ -181,9 +198,9 @@ void KX_Dome::CreateGLImages(void)
 	}
 	if(warp.usemesh){
 		glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagewidth, warp.imageheight, 0, GL_RGB8,
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagesize, warp.imagesize, 0, GL_RGB8,
 				GL_UNSIGNED_BYTE, 0);
-		glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagewidth, warp.imageheight, 0);
+		glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagesize, warp.imagesize, 0);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -207,13 +224,26 @@ void KX_Dome::CalculateImageSize(void)
 - determine the minimum buffer size
 - reduce the buffer for better performace
 - create a power of 2 texture bigger than the buffer
+*/
+/*
+Blender handles Canvas size differently when in fullscreen mode.
+We are manually checking for that. Although it's a hack, it works.
+
+Bug reported here: #18655 - Inconsistency of pixels in canvas dimensions when in maximized mode (affecting BGE Dome)
+http://projects.blender.org/tracker/?func=detail&aid=18655&group_id=9&atid=125
 */
 
 	canvaswidth = m_canvas->GetWidth();
 	canvasheight = m_canvas->GetHeight();
 
+	bool fullscreen(false); //XXX HACK
+	fullscreen = (canvaswidth != m_viewport.GetWidth());
+
 	m_buffersize = (canvaswidth > canvasheight?canvasheight:canvaswidth);
-	m_buffersize *= m_resbuffer; //reduce buffer size for better performance
+	m_buffersize = (int)(m_buffersize*m_resbuffer); //reduce buffer size for better performance
+	
+	if (fullscreen) //XXX HACK
+		m_buffersize --;
 
 	int i = 0;
 	while ((1 << i) <= m_buffersize)
@@ -221,27 +251,25 @@ void KX_Dome::CalculateImageSize(void)
 	m_imagesize = (1 << i);
 
 	if (warp.usemesh){
-		warp.bufferwidth = canvaswidth;
-		warp.bufferheight = canvasheight;
-
-		i = 0;
-		while ((1 << i) <= warp.bufferwidth)
-			i++;
-		warp.imagewidth = (1 << i);
+		// warp FBO needs to be up to twice as big as m_buffersize to get more resolution
+		warp.imagesize = m_imagesize;
+		if (m_buffersize == m_imagesize)
+			warp.imagesize *= 2;
 
-		i = 0;
-		while ((1 << i) <= warp.bufferheight)
-			i++;
-		warp.imageheight = (1 << i);
+		//if FBO is not working/supported, we use the canvas dimension as buffer
+		warp.bufferwidth  = canvaswidth;
+		warp.bufferheight = canvasheight;
 	}
+
+	//XXX HACK
+	canvaswidth  = m_viewport.GetWidth();
+	canvasheight = m_viewport.GetHeight();
 }
 
 bool KX_Dome::CreateDL(){
-	int i,j;
-
 	dlistId = glGenLists((GLsizei) m_numimages);
 	if (dlistId != 0) {
-		if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED){
+		if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED_UP || m_mode == DOME_TRUNCATED_DOWN){
 			glNewList(dlistId, GL_COMPILE);
 				GLDrawTriangles(cubetop, nfacestop);
 			glEndList();
@@ -313,6 +341,46 @@ bool KX_Dome::CreateDL(){
 	return true;
 }
 
+bool KX_Dome::CreateFBO(void)
+{
+	if (!GLEW_EXT_framebuffer_object)
+	{
+		printf("Dome Error: FrameBuffer unsupported. Using low resolution warp image.");
+		return false;
+	}
+
+	glGenFramebuffersEXT(1, &warp.fboId);
+	if(warp.fboId==0)
+	{
+		printf("Dome Error: Invalid frame buffer object. Using low resolution warp image.");
+		return false;
+	}
+
+	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId);
+
+	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+		GL_TEXTURE_2D, domefacesId[m_numfaces], 0);
+
+	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+
+	if(status == GL_FRAMEBUFFER_UNSUPPORTED_EXT)
+	{
+		printf("Dome Error: FrameBuffer settings unsupported. Using low resolution warp image.");
+		return false;
+	}
+	else if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
+	{
+		glDeleteFramebuffersEXT(1, &warp.fboId);
+		return false;
+	}
+
+	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+	//nothing failed: we can use the whole FBO as buffersize
+	warp.bufferwidth = warp.bufferheight = warp.imagesize;
+	return true;
+}
+
 void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces)
 {
 	int i,j;
@@ -329,8 +397,9 @@ void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces)
 void KX_Dome::GLDrawWarpQuads(void)
 {
 	int i, j, i2;
-	float uv_width = (float)warp.bufferwidth / warp.imagewidth;
-	float uv_height = (float)warp.bufferheight / warp.imageheight;
+
+	float uv_width = (float)(warp.bufferwidth) / warp.imagesize;
+	float uv_height = (float)(warp.bufferheight) / warp.imagesize;
 
 	if(warp.mode ==2 ){
 		glBegin(GL_QUADS);
@@ -387,7 +456,7 @@ void KX_Dome::GLDrawWarpQuads(void)
 		}
 		glEnd();
 	} else{
-		printf("Error: Warp Mode unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n");
+		printf("Dome Error: Warp Mode %d unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n", warp.mode);
 	}
 }
 
@@ -416,20 +485,22 @@ y varies from -1 to 1
 u and v vary from 0 to 1
 i ranges from 0 to 1, if negative don't draw that mesh node
 */
-	int i,j,k;
+	int i;
 	int nodeX=0, nodeY=0;
 
 	vector<STR_String> columns, lines;
 
 	lines = text.Explode('\n');
 	if(lines.size() < 6){
-		printf("Error: Warp Mesh File with insufficient data!\n");
+		printf("Dome Error: Warp Mesh File with insufficient data!\n");
 		return false;
 	}
 	columns = lines[1].Explode(' ');
+	if(columns.size() == 1)
+		columns = lines[1].Explode('\t');
 
 	if(columns.size() !=2){
-		printf("Error: Warp Mesh File incorrect. The second line should contain: width height.\n");
+		printf("Dome Error: Warp Mesh File incorrect. The second line should contain: width height.\n");
 		return false;
 	}
 
@@ -438,14 +509,16 @@ i ranges from 0 to 1, if negative don't draw that mesh node
 	warp.n_width = atoi(columns[0]);
 	warp.n_height = atoi(columns[1]);
 
-	if (lines.size() < 2 + (warp.n_width * warp.n_height)){
-		printf("Error: Warp Mesh File with insufficient data!\n");
+	if ((int)lines.size() < 2 + (warp.n_width * warp.n_height)){
+		printf("Dome Error: Warp Mesh File with insufficient data!\n");
 		return false;
 	}else{
-		warp.nodes = vector<vector <WarpMeshNode>> (warp.n_height, vector<WarpMeshNode>(warp.n_width));
+		warp.nodes = vector<vector<WarpMeshNode> > (warp.n_height, vector<WarpMeshNode>(warp.n_width));
 
 		for(i=2; i-2 < (warp.n_width*warp.n_height); i++){
 			columns = lines[i].Explode(' ');
+			if(columns.size() == 1)
+				columns = lines[i].Explode('\t');
 
 			if (columns.size() == 5){
 				nodeX = (i-2)%warp.n_width;
@@ -459,7 +532,7 @@ i ranges from 0 to 1, if negative don't draw that mesh node
 			}
 			else{
 				warp.nodes.clear();
-				printf("Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n");
+				printf("Dome Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n");
 				return false;
 			}
 		}
@@ -481,7 +554,7 @@ void KX_Dome::CreateMeshDome180(void)
 */
 	int i,j;
 	float sqrt_2 = sqrt(2.0);
-	float uv_ratio = (float)m_buffersize / m_imagesize;
+	float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
 
 	m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening
 
@@ -665,7 +738,7 @@ void KX_Dome::CreateMeshDome250(void)
 	float verts_height;
 
 	float rad_ang = m_angle * MT_PI / 180.0;
-	float uv_ratio = (float)m_buffersize / m_imagesize;
+	float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
 
 	m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening
 /*
@@ -946,7 +1019,7 @@ void KX_Dome::CreateMeshPanorama(void)
 	int i,j;
 
 	float sqrt_2 = sqrt(2.0);
-	float uv_ratio = (float)m_buffersize / m_imagesize;
+	float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
 
 	/* Top face - two triangles */
 	cubetop[0].verts[0][0] = -sqrt_2;
@@ -1374,7 +1447,7 @@ void KX_Dome::CalculateFrustum(KX_Camera * cam)
 	/*
 	// manually creating a 90� Field of View Frustum 
 
-	 the original formula:
+	the original formula:
 	top = tan(fov*3.14159/360.0) * near [for fov in degrees]
 	fov*0.5 = arctan ((top-bottom)*0.5 / near) [for fov in radians]
 	bottom = -top
@@ -1416,7 +1489,9 @@ Uses 6 cameras for angles up to 360
 	MT_Scalar c = cos(deg45);
 	MT_Scalar s = sin(deg45);
 
-	if ((m_mode == DOME_FISHEYE && m_angle <= 180)|| m_mode == DOME_TRUNCATED){
+	if (m_angle <= 180 && (m_mode == DOME_FISHEYE 
+		|| m_mode == DOME_TRUNCATED_UP 
+		|| m_mode == DOME_TRUNCATED_DOWN)){
 
 		m_locRot[0] = MT_Matrix3x3( // 90� - Top
 						c, -s, 0.0,
@@ -1438,7 +1513,9 @@ Uses 6 cameras for angles up to 360
 						0.0, 1.0, 0.0,
 						s, 0.0, c);
 
-	} else if ((m_mode == DOME_FISHEYE && m_angle > 180)){
+	} else if (m_mode == DOME_ENVMAP || (m_angle > 180 && (m_mode == DOME_FISHEYE
+		|| m_mode == DOME_TRUNCATED_UP 
+		|| m_mode == DOME_TRUNCATED_DOWN))){
 
 		m_locRot[0] = MT_Matrix3x3( // 90� - Top
 						 1.0, 0.0, 0.0,
@@ -1465,7 +1542,7 @@ Uses 6 cameras for angles up to 360
 						0.0, 1.0, 0.0,
 						0.0, 0.0, 1.0);
 
-		m_locRot[5] = MT_Matrix3x3( // 180� - Back - NOT USING
+		m_locRot[5] = MT_Matrix3x3( // 180� - Back - USED for ENVMAP only
 						-1.0, 0.0, 0.0,
 						 0.0, 1.0, 0.0,
 						 0.0, 0.0,-1.0);
@@ -1512,46 +1589,64 @@ void KX_Dome::RotateCamera(KX_Camera* cam, int i)
 	MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation();
 
 	cam->NodeSetLocalOrientation(camori*m_locRot[i]);
-	cam->NodeUpdateGS(0.f,true);
+	cam->NodeUpdateGS(0.f);
 
 	MT_Transform camtrans(cam->GetWorldToCamera());
 	MT_Matrix4x4 viewmat(camtrans);
-	m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(),
-		cam->GetCameraLocation(), cam->GetCameraOrientation());
+	m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective);
 	cam->SetModelviewMatrix(viewmat);
 
 	// restore the original orientation
 	cam->NodeSetLocalOrientation(camori);
-	cam->NodeUpdateGS(0.f,true);
+	cam->NodeUpdateGS(0.f);
 }
 
 void KX_Dome::Draw(void)
 {
 
+	if (fboSupported){
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId);
+
+		glViewport(0,0,warp.imagesize, warp.imagesize);
+		glScissor(0,0,warp.imagesize, warp.imagesize);
+	}
+
 	switch(m_mode){
 		case DOME_FISHEYE:
 			DrawDomeFisheye();
 			break;
-		case DOME_TRUNCATED:
-			DrawDomeFisheye();
+		case DOME_ENVMAP:
+			DrawEnvMap();
 			break;
 		case DOME_PANORAM_SPH:
 			DrawPanorama();
 			break;
+		case DOME_TRUNCATED_UP:
+			DrawDomeFisheye();
+			break;
+		case DOME_TRUNCATED_DOWN:
+			DrawDomeFisheye();
+			break;
 	}
 
 	if(warp.usemesh)
 	{
-		glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
-		glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth+1, warp.bufferheight+1);
+		if(fboSupported)
+		{
+			m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
+			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+		}
+		else
+		{
+			glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
+			glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, warp.bufferheight);
+		}
 		DrawDomeWarped();
 	}
 }
 
-void KX_Dome::DrawDomeFisheye(void)
+void KX_Dome::DrawEnvMap(void)
 {
-	int i,j;
-
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	glMatrixMode(GL_PROJECTION);
 	glLoadIdentity();
@@ -1564,23 +1659,15 @@ void KX_Dome::DrawDomeFisheye(void)
 	float ortho_width, ortho_height;
 
 	if (warp.usemesh)
-		glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost
-
-	else if(m_mode == DOME_TRUNCATED){
-		ortho_width = 1.0;
-		ortho_height = 2 * ((float)can_height/can_width) - 1.0 ;
-		
-		ortho_width /= m_size;
-		ortho_height /= m_size;
+		glOrtho((-1.0), 1.0, (-0.66), 0.66, -20.0, 10.0); //stretch the image to reduce resolution lost
 
-		glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0);
-	} else {
-		if (can_width < can_height){
+	else {
+		if (can_width/3 <= can_height/2){
 			ortho_width = 1.0;
 			ortho_height = (float)can_height/can_width;
 		}else{
-			ortho_width = (float)can_width/can_height;
-			ortho_height = 1.0;
+			ortho_height = 2.0f / 3;
+			ortho_width = (float)can_width/can_height * ortho_height;
 		}
 		
 		ortho_width /= m_size;
@@ -1589,6 +1676,153 @@ void KX_Dome::DrawDomeFisheye(void)
 		glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
 	}
 
+	glMatrixMode(GL_TEXTURE);
+	glLoadIdentity();
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+	gluLookAt(0.0,0.0,1.0, 0.0,0.0,0.0, 0.0,1.0,0.0);
+
+	glPolygonMode(GL_FRONT, GL_FILL);
+	glShadeModel(GL_SMOOTH);
+	glDisable(GL_LIGHTING);
+	glDisable(GL_DEPTH_TEST);
+
+	glEnable(GL_TEXTURE_2D);
+	glColor3f(1.0,1.0,1.0);
+
+	float uv_ratio = (float)(m_buffersize-1) / m_imagesize;
+	double onebythree = 1.0f / 3;
+
+	// domefacesId[0] =>  (top)
+	glBindTexture(GL_TEXTURE_2D, domefacesId[0]);
+	glBegin(GL_QUADS);
+		glTexCoord2f(uv_ratio,uv_ratio);
+		glVertex3f( onebythree, 0.0f, 3.0f);
+		glTexCoord2f(0.0,uv_ratio);
+		glVertex3f(-onebythree, 0.0f, 3.0f);
+		glTexCoord2f(0.0,0.0);
+		glVertex3f(-onebythree,-2 * onebythree, 3.0f);
+		glTexCoord2f(uv_ratio,0.0);
+		glVertex3f(onebythree,-2 * onebythree, 3.0f);
+	glEnd();
+
+	// domefacesId[1] =>  (bottom)
+	glBindTexture(GL_TEXTURE_2D, domefacesId[1]);
+	glBegin(GL_QUADS);
+		glTexCoord2f(uv_ratio,uv_ratio);
+		glVertex3f(-onebythree, 0.0f, 3.0f);
+		glTexCoord2f(0.0,uv_ratio);
+		glVertex3f(-1.0f, 0.0f, 3.0f);
+		glTexCoord2f(0.0,0.0);
+		glVertex3f(-1.0f,-2 * onebythree, 3.0f);
+		glTexCoord2f(uv_ratio,0.0);
+		glVertex3f(-onebythree,-2 * onebythree, 3.0f);
+	glEnd();
+
+	// domefacesId[2] => -90� (left)
+	glBindTexture(GL_TEXTURE_2D, domefacesId[2]);
+	glBegin(GL_QUADS);
+		glTexCoord2f(uv_ratio,uv_ratio);
+		glVertex3f(-onebythree, 2 * onebythree, 3.0f);
+		glTexCoord2f(0.0,uv_ratio);
+		glVertex3f(-1.0f, 2 * onebythree, 3.0f);
+		glTexCoord2f(0.0,0.0);
+		glVertex3f(-1.0f, 0.0f, 3.0f);
+		glTexCoord2f(uv_ratio,0.0);
+		glVertex3f(-onebythree, 0.0f, 3.0f);
+	glEnd();
+
+	// domefacesId[3] => 90� (right)
+	glBindTexture(GL_TEXTURE_2D, domefacesId[3]);
+	glBegin(GL_QUADS);
+		glTexCoord2f(uv_ratio,uv_ratio);
+		glVertex3f( 1.0f, 2 * onebythree, 3.0f);
+		glTexCoord2f(0.0,uv_ratio);
+		glVertex3f( onebythree, 2 * onebythree, 3.0f);
+		glTexCoord2f(0.0,0.0);
+		glVertex3f( onebythree, 0.0f, 3.0f);
+		glTexCoord2f(uv_ratio,0.0);
+		glVertex3f(1.0f, 0.0f, 3.0f);
+	glEnd();
+
+	// domefacesId[4] => 0� (front)
+	glBindTexture(GL_TEXTURE_2D, domefacesId[4]);
+	glBegin(GL_QUADS);
+		glTexCoord2f(uv_ratio,uv_ratio);
+		glVertex3f( 1.0f, 0.0f, 3.0f);
+		glTexCoord2f(0.0,uv_ratio);
+		glVertex3f( onebythree, 0.0f, 3.0f);
+		glTexCoord2f(0.0,0.0);
+		glVertex3f( onebythree,-2 * onebythree, 3.0f);
+		glTexCoord2f(uv_ratio,0.0);
+		glVertex3f(1.0f, -2 * onebythree, 3.0f);
+	glEnd();
+
+	// domefacesId[5] => 180� (back)
+	glBindTexture(GL_TEXTURE_2D, domefacesId[5]);
+	glBegin(GL_QUADS);
+		glTexCoord2f(uv_ratio,uv_ratio);
+		glVertex3f( onebythree, 2 * onebythree, 3.0f);
+		glTexCoord2f(0.0,uv_ratio);
+		glVertex3f(-onebythree, 2 * onebythree, 3.0f);
+		glTexCoord2f(0.0,0.0);
+		glVertex3f(-onebythree, 0.0f, 3.0f);
+		glTexCoord2f(uv_ratio,0.0);
+		glVertex3f(onebythree, 0.0f, 3.0f);
+	glEnd();
+
+	glDisable(GL_TEXTURE_2D);
+	glEnable(GL_DEPTH_TEST);
+}
+
+void KX_Dome::DrawDomeFisheye(void)
+{
+	int i;
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+
+	// Making the viewport always square 
+
+	int can_width = m_viewport.GetRight();
+	int can_height = m_viewport.GetTop();
+
+	float ortho_width, ortho_height;
+
+	if(m_mode == DOME_FISHEYE) {
+		if (warp.usemesh)
+			glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost
+
+		else {
+			if (can_width < can_height){
+				ortho_width = 1.0;
+				ortho_height = (float)can_height/can_width;
+			}else{
+				ortho_width = (float)can_width/can_height;
+				ortho_height = 1.0;
+			}
+			
+			ortho_width /= m_size;
+			ortho_height /= m_size;
+			
+			glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0);
+		}
+	}
+	else if(m_mode == DOME_TRUNCATED_UP)
+	{
+		ortho_width = 1.0;
+		ortho_height = 2 * ((float)can_height/can_width) - 1.0 ;
+
+		glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0);
+	}
+	else { //m_mode == DOME_TRUNCATED_DOWN
+		ortho_width = 1.0;
+		ortho_height = 2 * ((float)can_height/can_width) - 1.0 ;
+
+		glOrtho((-ortho_width), ortho_width, (-ortho_width), ortho_height, -20.0, 10.0);
+	}
+
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
 	glMatrixMode(GL_MODELVIEW);
@@ -1642,7 +1876,7 @@ void KX_Dome::DrawDomeFisheye(void)
 
 void KX_Dome::DrawPanorama(void)
 {
-	int i,j;
+	int i;
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	glMatrixMode(GL_PROJECTION);
 	glLoadIdentity();
@@ -1729,8 +1963,6 @@ void KX_Dome::DrawPanorama(void)
 
 void KX_Dome::DrawDomeWarped(void)
 {
-	int i,j;
-
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	glMatrixMode(GL_PROJECTION);
 	glLoadIdentity();
@@ -1763,10 +1995,6 @@ void KX_Dome::DrawDomeWarped(void)
 	glEnable(GL_TEXTURE_2D);
 	glColor3f(1.0,1.0,1.0);
 
-
-	float uv_width = (float)warp.bufferwidth / warp.imagewidth;
-	float uv_height = (float)warp.bufferheight / warp.imageheight;
-
 	if (dlistSupported){
 		glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
 		glCallList(dlistId + m_numfaces);
@@ -1782,7 +2010,7 @@ void KX_Dome::DrawDomeWarped(void)
 void KX_Dome::BindImages(int i)
 {
 	glBindTexture(GL_TEXTURE_2D, domefacesId[i]);
-	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), m_buffersize+1, m_buffersize+1);
+	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), m_buffersize, m_buffersize);
 }
 
 void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
@@ -1790,7 +2018,7 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
 	if (!cam)
 		return;
 
-	m_canvas->SetViewPort(0,0,m_buffersize,m_buffersize);
+	m_canvas->SetViewPort(0,0,m_buffersize-1,m_buffersize-1);
 
 //	m_rasterizer->SetAmbient();
 	m_rasterizer->DisplayFog();
@@ -1803,12 +2031,11 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
 	MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation();
 
 	cam->NodeSetLocalOrientation(camori*m_locRot[i]);
-	cam->NodeUpdateGS(0.f,true);
+	cam->NodeUpdateGS(0.f);
 
 	MT_Transform camtrans(cam->GetWorldToCamera());
 	MT_Matrix4x4 viewmat(camtrans);
-	m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(),
-		cam->GetCameraLocation(), cam->GetCameraOrientation());
+	m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), 1.0);
 	cam->SetModelviewMatrix(viewmat);
 
 	scene->CalculateVisibleMeshes(m_rasterizer,cam);
@@ -1816,5 +2043,6 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
 	
 	// restore the original orientation
 	cam->NodeSetLocalOrientation(camori);
-	cam->NodeUpdateGS(0.f,true);
-}
\ No newline at end of file
+	cam->NodeUpdateGS(0.f);
+}
+
diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h
index de3360cd897b833939ade9bdf5a6a0c64469a129..30d02dce7a05ccd16c300a9d924e586ed8f5444f 100644
--- a/source/gameengine/Ketsji/KX_Dome.h
+++ b/source/gameengine/Ketsji/KX_Dome.h
@@ -38,13 +38,14 @@ Developed as part of a Research and Development project for SAT - La Soci
 
 #include "MEM_guardedalloc.h"
 #include "BKE_text.h"
-//#include "BLI_blenlib.h"
 
 //Dome modes: limit hardcoded in buttons_scene.c
 #define DOME_FISHEYE		1
-#define DOME_TRUNCATED		2
+#define DOME_ENVMAP			2
 #define DOME_PANORAM_SPH	3
-#define DOME_NUM_MODES		4
+#define DOME_TRUNCATED_UP	4
+#define DOME_TRUNCATED_DOWN	5
+#define DOME_NUM_MODES		6
 
 
 /// class for render 3d scene
@@ -74,6 +75,7 @@ public:
 
 	//openGL checks:
 	bool	dlistSupported;
+	bool	fboSupported;
 
 	//openGL names:
 	GLuint domefacesId[7];		// ID of the images -- room for 7 images, using only 4 for 180� x 360� dome, 6 for panoramic and +1 for warp mesh
@@ -93,8 +95,9 @@ public:
 		bool usemesh;
 		int mode;
 		int n_width, n_height; //nodes width and height
-		int imagewidth, imageheight;
+		int imagesize;
 		int bufferwidth, bufferheight;
+		GLuint fboId;
 		vector <vector <WarpMeshNode> > nodes;
 	} warp;
 
@@ -116,7 +119,7 @@ public:
 	void CalculateFrustum(KX_Camera* cam);
 	void RotateCamera(KX_Camera* cam, int i);
 
-	//Mesh  Creating Functions
+	//Mesh creation Functions
 	void CreateMeshDome180(void);
 	void CreateMeshDome250(void);
 	void CreateMeshPanorama(void);
@@ -131,6 +134,7 @@ public:
 	void GLDrawWarpQuads(void);
 	void Draw(void);
 	void DrawDomeFisheye(void);
+	void DrawEnvMap(void);
 	void DrawPanorama(void);
 	void DrawDomeWarped(void);
 
@@ -139,6 +143,8 @@ public:
 	void ClearGLImages(void);//called on resize
 	bool CreateDL(void); //create Display Lists
 	void ClearDL(void);  //remove Display Lists 
+	bool CreateFBO(void);//create FBO (for warp mesh)
+	void ClearFBO(void); //remove FBO
 
 	void CalculateCameraOrientation();
 	void CalculateImageSize(); //set m_imagesize
@@ -180,4 +186,5 @@ protected:
     KX_KetsjiEngine* m_engine;
 };
 
-#endif
\ No newline at end of file
+#endif
+
diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp
index a2a3d48642095c6b37e7fc35179311de66be3e46..9588e14d360987121e7de6a944600003acbb95f5 100644
--- a/source/gameengine/Ketsji/KX_GameActuator.cpp
+++ b/source/gameengine/Ketsji/KX_GameActuator.cpp
@@ -73,8 +73,6 @@ CValue* KX_GameActuator::GetReplica()
 {
 	KX_GameActuator* replica = new KX_GameActuator(*this);
 	replica->ProcessReplica();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
 	
 	return replica;
 }
@@ -208,12 +206,17 @@ bool KX_GameActuator::Update()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_GameActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_GameActuator",
-		sizeof(KX_GameActuator),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -250,24 +253,22 @@ PyMethodDef KX_GameActuator::Methods[] =
 
 PyAttributeDef KX_GameActuator::Attributes[] = {
 	KX_PYATTRIBUTE_STRING_RW("file",0,100,false,KX_GameActuator,m_filename),
+	KX_PYATTRIBUTE_INT_RW("mode", KX_GAME_NODEF+1, KX_GAME_MAX-1, true, KX_GameActuator, m_mode),
 	{ NULL }	//Sentinel
 };
 
-PyObject*
-KX_GameActuator::py_getattro(PyObject *attr)
+PyObject* KX_GameActuator::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_GameActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_GameActuator::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 
@@ -276,7 +277,7 @@ int KX_GameActuator::py_setattro(PyObject *attr, PyObject *value)
 const char KX_GameActuator::GetFile_doc[] = 
 "getFile()\n"
 "get the name of the file to start.\n";
-PyObject* KX_GameActuator::PyGetFile(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_GameActuator::PyGetFile(PyObject* args, PyObject* kwds)
 {	
 	ShowDeprecationWarning("getFile()", "the file property");
 	return PyString_FromString(m_filename);
@@ -286,13 +287,13 @@ PyObject* KX_GameActuator::PyGetFile(PyObject* self, PyObject* args, PyObject* k
 const char KX_GameActuator::SetFile_doc[] =
 "setFile(name)\n"
 "set the name of the file to start.\n";
-PyObject* KX_GameActuator::PySetFile(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_GameActuator::PySetFile(PyObject* args, PyObject* kwds)
 {
 	char* new_file;
 
 	ShowDeprecationWarning("setFile()", "the file property");
 	
-	if (!PyArg_ParseTuple(args, "s", &new_file))
+	if (!PyArg_ParseTuple(args, "s:setFile", &new_file))
 	{
 		return NULL;
 	}
diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h
index 570cb2e68efe0f871d10b75bf2e8630f1e9929b9..b2b1d6ec2b954c7f5a20c05187eb3ae69b8be4b1 100644
--- a/source/gameengine/Ketsji/KX_GameActuator.h
+++ b/source/gameengine/Ketsji/KX_GameActuator.h
@@ -78,6 +78,7 @@ protected:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	// Deprecated functions ----->
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index e79ef5ab72b41a5d1d94afe658d82517abd1da9e..4d01d96ced4676e2cd35c54495641c0c0f3a72f7 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -55,6 +55,7 @@ typedef unsigned long uint_ptr;
 #include <stdio.h> // printf
 #include "SG_Controller.h"
 #include "KX_IPhysicsController.h"
+#include "PHY_IGraphicController.h"
 #include "SG_Node.h"
 #include "SG_Controller.h"
 #include "KX_ClientObjectInfo.h"
@@ -62,8 +63,11 @@ typedef unsigned long uint_ptr;
 #include "KX_RayCast.h"
 #include "KX_PythonInit.h"
 #include "KX_PyMath.h"
+#include "KX_PythonSeq.h"
 #include "SCA_IActuator.h"
 #include "SCA_ISensor.h"
+#include "SCA_IController.h"
+#include "NG_NetworkScene.h" //Needed for sendMessage()
 
 #include "PyObjectPlus.h" /* python stuff */
 
@@ -72,6 +76,12 @@ typedef unsigned long uint_ptr;
 
 #include "KX_SG_NodeRelationships.h"
 
+static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
+static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
+static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(	1.0, 0.0, 0.0,
+														0.0, 1.0, 0.0,
+														0.0, 0.0, 1.0);
+
 KX_GameObject::KX_GameObject(
 	void* sgReplicationInfo,
 	SG_Callbacks callbacks,
@@ -87,11 +97,14 @@ KX_GameObject::KX_GameObject(
 	m_bIsNegativeScaling(false),
 	m_bVisible(true),
 	m_bCulled(true),
+	m_bOccluder(false),
 	m_pPhysicsController1(NULL),
+	m_pGraphicController(NULL),
 	m_pPhysicsEnvironment(NULL),
 	m_xray(false),
 	m_pHitObject(NULL),
-	m_isDeformable(false)
+	m_isDeformable(false),
+	m_attr_dict(NULL)
 {
 	m_ignore_activity_culling = false;
 	m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
@@ -129,9 +142,23 @@ KX_GameObject::~KX_GameObject()
 		}
 		m_pSGNode->SetSGClientObject(NULL);
 	}
+	if (m_pGraphicController)
+	{
+		delete m_pGraphicController;
+	}
+	
+	if (m_attr_dict) {
+		PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */
+		Py_DECREF(m_attr_dict);
+	}
 }
 
-
+KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info)
+{
+	if (!info)
+		return NULL;
+	return info->m_gameobject;
+}
 
 CValue* KX_GameObject::	Calc(VALUE_OPERATOR op, CValue *val) 
 {
@@ -154,45 +181,30 @@ const STR_String & KX_GameObject::GetText()
 
 
 
-float KX_GameObject::GetNumber()
+double KX_GameObject::GetNumber()
 {
 	return 0;
 }
 
 
 
-STR_String KX_GameObject::GetName()
+STR_String& KX_GameObject::GetName()
 {
 	return m_name;
 }
 
 
 
-void KX_GameObject::SetName(STR_String name)
+void KX_GameObject::SetName(const char *name)
 {
 	m_name = name;
 };								// Set the name of the value
 
-
-
-void KX_GameObject::ReplicaSetName(STR_String name)
-{
-}
-
-
-
-
-
-
 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
 {
 	return m_pPhysicsController1;
 }
 
-
-
-
-
 KX_GameObject* KX_GameObject::GetParent()
 {
 	KX_GameObject* result = NULL;
@@ -246,7 +258,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
 		NodeSetLocalScale(scale1);
 		NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
 		NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
-		NodeUpdateGS(0.f,true);
+		NodeUpdateGS(0.f);
 		// object will now be a child, it must be removed from the parent list
 		CListValue* rootlist = scene->GetRootParentList();
 		if (rootlist->RemoveValue(this))
@@ -266,6 +278,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
 				rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1);
 			}
 		}
+		// graphically, the object hasn't change place, no need to update m_pGraphicController
 	}
 }
 
@@ -283,7 +296,7 @@ void KX_GameObject::RemoveParent(KX_Scene *scene)
 
 		// Remove us from our parent
 		GetSGNode()->DisconnectFromParent();
-		NodeUpdateGS(0.f,true);
+		NodeUpdateGS(0.f);
 		// the object is now a root object, add it to the parentlist
 		CListValue* rootlist = scene->GetRootParentList();
 		if (!rootlist->SearchValue(this))
@@ -300,27 +313,62 @@ void KX_GameObject::RemoveParent(KX_Scene *scene)
 			}
 			m_pPhysicsController1->RestoreDynamics();
 		}
+		// graphically, the object hasn't change place, no need to update m_pGraphicController
 	}
 }
 
-void KX_GameObject::ProcessReplica(KX_GameObject* replica)
+void KX_GameObject::ProcessReplica()
+{
+	SCA_IObject::ProcessReplica();
+	
+	m_pPhysicsController1 = NULL;
+	m_pGraphicController = NULL;
+	m_pSGNode = NULL;
+	m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
+	m_pClient_info->m_gameobject = this;
+	m_state = 0;
+	if(m_attr_dict)
+		m_attr_dict= PyDict_Copy(m_attr_dict);
+		
+}
+
+static void setGraphicController_recursive(SG_Node* node, bool v)
 {
-	replica->m_pPhysicsController1 = NULL;
-	replica->m_pSGNode = NULL;
-	replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
-	replica->m_pClient_info->m_gameobject = replica;
-	replica->m_state = 0;
+	NodeList& children = node->GetSGChildren();
+
+	for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+	{
+		SG_Node* childnode = (*childit);
+		KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+		if (clientgameobj != NULL) // This is a GameObject
+			clientgameobj->ActivateGraphicController(v, false);
+		
+		// if the childobj is NULL then this may be an inverse parent link
+		// so a non recursive search should still look down this node.
+		setGraphicController_recursive(childnode, v);
+	}
 }
 
 
+void KX_GameObject::ActivateGraphicController(bool active, bool recurse)
+{
+	if (m_pGraphicController)
+	{
+		m_pGraphicController->Activate(active);
+	}
+	if (recurse)
+	{
+		setGraphicController_recursive(GetSGNode(), active);
+	}
+}
+
 
 CValue* KX_GameObject::GetReplica()
 {
 	KX_GameObject* replica = new KX_GameObject(*this);
 
 	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-	ProcessReplica(replica);
+	replica->ProcessReplica();
 
 	return replica;
 }
@@ -345,11 +393,14 @@ void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
 
 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
 {
-	if (m_pPhysicsController1) // (IsDynamic())
+	if (GetSGNode()) 
 	{
-		m_pPhysicsController1->RelativeTranslate(dloc,local);
+		if (m_pPhysicsController1) // (IsDynamic())
+		{
+			m_pPhysicsController1->RelativeTranslate(dloc,local);
+		}
+		GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
 	}
-	GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
 }
 
 
@@ -357,11 +408,13 @@ void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
 {
 	MT_Matrix3x3 rotmat(drot);
+	
+	if (GetSGNode()) {
+		GetSGNode()->RelativeRotate(rotmat,local);
 
-	GetSGNode()->RelativeRotate(rotmat,local);
-
-	if (m_pPhysicsController1) { // (IsDynamic())
-		m_pPhysicsController1->RelativeRotate(rotmat,local); 
+		if (m_pPhysicsController1) { // (IsDynamic())
+			m_pPhysicsController1->RelativeRotate(rotmat,local); 
+		}
 	}
 }
 
@@ -374,24 +427,37 @@ double*	KX_GameObject::GetOpenGLMatrix()
 {
 	// todo: optimize and only update if necessary
 	double* fl = m_OpenGL_4x4Matrix.getPointer();
-	MT_Transform trans;
+	if (GetSGNode()) {
+		MT_Transform trans;
 	
-	trans.setOrigin(GetSGNode()->GetWorldPosition());
-	trans.setBasis(GetSGNode()->GetWorldOrientation());
+		trans.setOrigin(GetSGNode()->GetWorldPosition());
+		trans.setBasis(GetSGNode()->GetWorldOrientation());
 	
-	MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
-	m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
-	trans.scale(scaling[0], scaling[1], scaling[2]);
-	trans.getValue(fl);
-
+		MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
+		m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
+		trans.scale(scaling[0], scaling[1], scaling[2]);
+		trans.getValue(fl);
+		GetSGNode()->ClearDirty();
+	}
 	return fl;
 }
 
 void KX_GameObject::AddMeshUser()
 {
 	for (size_t i=0;i<m_meshes.size();i++)
-		m_meshes[i]->AddMeshUser(this);
-	
+	{
+		m_meshes[i]->AddMeshUser(this, &m_meshSlots);
+	}
+	// set the part of the mesh slot that never change
+	double* fl = GetOpenGLMatrixPtr()->getPointer();
+	RAS_Deformer *deformer = GetDeformer();
+
+	SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
+	for(mit.begin(); !mit.end(); ++mit)
+	{
+		(*mit)->m_OpenGLMatrix = fl;
+		(*mit)->SetDeformer(deformer);
+	}
 	UpdateBuckets(false);
 }
 
@@ -414,13 +480,32 @@ static void UpdateBuckets_recursive(SG_Node* node)
 
 void KX_GameObject::UpdateBuckets( bool recursive )
 {
-	double* fl = GetOpenGLMatrix();
+	if (GetSGNode()) {
+		RAS_MeshSlot *ms;
 
-	for (size_t i=0;i<m_meshes.size();i++)
-		m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled);
+		if (GetSGNode()->IsDirty())
+			GetOpenGLMatrix();
+
+		SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
+		for(mit.begin(); !mit.end(); ++mit)
+		{
+			ms = *mit;
+			ms->m_bObjectColor = m_bUseObjectColor;
+			ms->m_RGBAcolor = m_objectColor;
+			ms->m_bVisible = m_bVisible;
+			ms->m_bCulled = m_bCulled || !m_bVisible;
+			if (!ms->m_bCulled) 
+				ms->m_bucket->ActivateMesh(ms);
+			
+			/* split if necessary */
+#ifdef USE_SPLIT
+			ms->Split();
+#endif
+		}
 	
-	if (recursive) {
-		UpdateBuckets_recursive(m_pSGNode);
+		if (recursive) {
+			UpdateBuckets_recursive(GetSGNode());
+		}
 	}
 }
 
@@ -434,22 +519,18 @@ void KX_GameObject::RemoveMeshes()
 	m_meshes.clear();
 }
 
-
-
-void KX_GameObject::UpdateNonDynas()
+void KX_GameObject::UpdateTransform()
 {
-	if (m_pPhysicsController1)
-	{
+	// HACK: saves function call for dynamic object, they are handled differently
+	if (m_pPhysicsController1 && !m_pPhysicsController1->IsDyna())
+		// Note that for Bullet, this does not even update the transform of static object
+		// but merely sets there collision flag to "kinematic" because the synchronization is 
+		// done during physics simulation
 		m_pPhysicsController1->SetSumoTransform(true);
-	}
-}
+	if (m_pGraphicController)
+		// update the culling tree
+		m_pGraphicController->SetGraphicTransform();
 
-
-
-void KX_GameObject::UpdateTransform()
-{
-	if (m_pPhysicsController1)
-		m_pPhysicsController1->SetSumoTransform(false);
 }
 
 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
@@ -575,28 +656,45 @@ KX_GameObject::SetVisible(
 	bool recursive
 	)
 {
-	m_bVisible = v;
-	if (recursive)
-		setVisible_recursive(m_pSGNode, v);
+	if (GetSGNode()) {
+		m_bVisible = v;
+		if (m_pGraphicController)
+			m_pGraphicController->Activate(m_bVisible);
+		if (recursive)
+			setVisible_recursive(GetSGNode(), v);
+	}
 }
 
-bool
-KX_GameObject::GetCulled(
-	void
-	)
+static void setOccluder_recursive(SG_Node* node, bool v)
 {
-	return m_bCulled;
+	NodeList& children = node->GetSGChildren();
+
+	for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+	{
+		SG_Node* childnode = (*childit);
+		KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+		if (clientgameobj != NULL) // This is a GameObject
+			clientgameobj->SetOccluder(v, false);
+		
+		// if the childobj is NULL then this may be an inverse parent link
+		// so a non recursive search should still look down this node.
+		setOccluder_recursive(childnode, v);
+	}
 }
 
 void
-KX_GameObject::SetCulled(
-	bool c
+KX_GameObject::SetOccluder(
+	bool v,
+	bool recursive
 	)
 {
-	m_bCulled = c;
+	if (GetSGNode()) {
+		m_bOccluder = v;
+		if (recursive)
+			setOccluder_recursive(GetSGNode(), v);
+	}
 }
 
-
 void
 KX_GameObject::SetLayer(
 	int l
@@ -764,6 +862,16 @@ MT_Scalar KX_GameObject::GetMass()
 	return 0.0;
 }
 
+MT_Vector3 KX_GameObject::GetLocalInertia()
+{
+	MT_Vector3 local_inertia(0.0,0.0,0.0);
+	if (m_pPhysicsController1)
+	{
+		local_inertia = m_pPhysicsController1->GetLocalInertia();
+	}
+	return local_inertia;
+}
+
 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
 {
 	MT_Vector3 velocity(0.0,0.0,0.0), locvel;
@@ -829,6 +937,7 @@ void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
 	}
 
 	GetSGNode()->SetLocalPosition(trans);
+
 }
 
 
@@ -883,7 +992,9 @@ void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
 
 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
 {
-	SG_Node* parent = m_pSGNode->GetSGParent();
+	if (!GetSGNode())
+		return;
+	SG_Node* parent = GetSGNode()->GetSGParent();
 	if (parent != NULL)
 	{
 		// Make sure the objects have some scale
@@ -908,7 +1019,7 @@ void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
 }
 
 
-void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
+void KX_GameObject::NodeUpdateGS(double time)
 {
 	if (GetSGNode())
 		GetSGNode()->UpdateWorldData(time);
@@ -918,13 +1029,9 @@ void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
 
 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
 {
-	static MT_Matrix3x3 defaultOrientation = MT_Matrix3x3(	1.0, 0.0, 0.0,
-															0.0, 1.0, 0.0,
-															0.0, 0.0, 1.0);
-
 	// check on valid node in case a python controller holds a reference to a deleted object
 	if (!GetSGNode())
-		return defaultOrientation;
+		return dummy_orientation;
 	return GetSGNode()->GetWorldOrientation();
 }
 
@@ -932,17 +1039,15 @@ const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
 
 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
 {
-	static MT_Vector3 defaultScaling = MT_Vector3(1.0, 1.0, 1.0);
-
 	// check on valid node in case a python controller holds a reference to a deleted object
 	if (!GetSGNode())
-		return defaultScaling;
+		return dummy_scaling;
 
 	return GetSGNode()->GetWorldScaling();
 }
 
 
-static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
+
 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
 {
 	// check on valid node in case a python controller holds a reference to a deleted object
@@ -963,7 +1068,8 @@ void KX_GameObject::Resume(void)
 {
 	if (m_suspended) {
 		SCA_IObject::Resume();
-		GetPhysicsController()->RestoreDynamics();
+		if(GetPhysicsController())
+			GetPhysicsController()->RestoreDynamics();
 
 		m_suspended = false;
 	}
@@ -974,18 +1080,54 @@ void KX_GameObject::Suspend()
 	if ((!m_ignore_activity_culling) 
 		&& (!m_suspended))  {
 		SCA_IObject::Suspend();
-		GetPhysicsController()->SuspendDynamics();
+		if(GetPhysicsController())
+			GetPhysicsController()->SuspendDynamics();
 		m_suspended = true;
 	}
 }
 
+static void walk_children(SG_Node* node, CListValue* list, bool recursive)
+{
+	if (!node)
+		return;
+	NodeList& children = node->GetSGChildren();
+
+	for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+	{
+		SG_Node* childnode = (*childit);
+		CValue* childobj = (CValue*)childnode->GetSGClientObject();
+		if (childobj != NULL) // This is a GameObject
+		{
+			// add to the list
+			list->Add(childobj->AddRef());
+		}
+		
+		// if the childobj is NULL then this may be an inverse parent link
+		// so a non recursive search should still look down this node.
+		if (recursive || childobj==NULL) {
+			walk_children(childnode, list, recursive);
+		}
+	}
+}
+
+CListValue* KX_GameObject::GetChildren()
+{
+	CListValue* list = new CListValue();
+	walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */
+	return list;
+}
 
+CListValue* KX_GameObject::GetChildrenRecursive()
+{
+	CListValue* list = new CListValue();
+	walk_children(GetSGNode(), list, 1);
+	return list;
+}
 
 
 /* ------- python stuff ---------------------------------------------------*/
 
 PyMethodDef KX_GameObject::Methods[] = {
-	{"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
 	{"applyForce", (PyCFunction)	KX_GameObject::sPyApplyForce, METH_VARARGS},
 	{"applyTorque", (PyCFunction)	KX_GameObject::sPyApplyTorque, METH_VARARGS},
 	{"applyRotation", (PyCFunction)	KX_GameObject::sPyApplyRotation, METH_VARARGS},
@@ -1006,10 +1148,10 @@ PyMethodDef KX_GameObject::Methods[] = {
 	{"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
 	{"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
 	{"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
+	{"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
 	{"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
 	{"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
 	{"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
-	{"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
 	{"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
 	{"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
 	{"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O},
@@ -1019,10 +1161,12 @@ PyMethodDef KX_GameObject::Methods[] = {
 	KX_PYMETHODTABLE(KX_GameObject, rayCast),
 	KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
 	KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
-	
+	KX_PYMETHODTABLE(KX_GameObject, sendMessage),
+
 	// deprecated
 	{"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
 	{"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
+	{"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
 	{"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
 	{"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
 	{"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
@@ -1030,6 +1174,7 @@ PyMethodDef KX_GameObject::Methods[] = {
 	{"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
 	{"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
 	{"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
+	{"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
 	{NULL,NULL} //Sentinel
 };
 
@@ -1037,13 +1182,29 @@ PyAttributeDef KX_GameObject::Attributes[] = {
 	KX_PYATTRIBUTE_RO_FUNCTION("name",		KX_GameObject, pyattr_get_name),
 	KX_PYATTRIBUTE_RO_FUNCTION("parent",	KX_GameObject, pyattr_get_parent),
 	KX_PYATTRIBUTE_RW_FUNCTION("mass",		KX_GameObject, pyattr_get_mass,		pyattr_set_mass),
+	KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin",		KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
+	KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax",		KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
 	KX_PYATTRIBUTE_RW_FUNCTION("visible",	KX_GameObject, pyattr_get_visible,	pyattr_set_visible),
-	KX_PYATTRIBUTE_RW_FUNCTION("position",	KX_GameObject, pyattr_get_position,	pyattr_set_position),
-	KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_orientation,pyattr_set_orientation),
-	KX_PYATTRIBUTE_RW_FUNCTION("scaling",	KX_GameObject, pyattr_get_scaling,	pyattr_set_scaling),
+	KX_PYATTRIBUTE_BOOL_RW    ("occlusion", KX_GameObject, m_bOccluder),
+	KX_PYATTRIBUTE_RW_FUNCTION("position",	KX_GameObject, pyattr_get_worldPosition,	pyattr_set_localPosition),
+	KX_PYATTRIBUTE_RO_FUNCTION("localInertia",	KX_GameObject, pyattr_get_localInertia),
+	KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
+	KX_PYATTRIBUTE_RW_FUNCTION("scaling",	KX_GameObject, pyattr_get_worldScaling,	pyattr_set_localScaling),
 	KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
 	KX_PYATTRIBUTE_RW_FUNCTION("state",		KX_GameObject, pyattr_get_state,	pyattr_set_state),
-	KX_PYATTRIBUTE_RO_FUNCTION("__dict__",	KX_GameObject, pyattr_get_dir_dict),
+	KX_PYATTRIBUTE_RO_FUNCTION("meshes",	KX_GameObject, pyattr_get_meshes),
+	KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
+	KX_PYATTRIBUTE_RW_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_worldOrientation),
+	KX_PYATTRIBUTE_RW_FUNCTION("localPosition",	KX_GameObject, pyattr_get_localPosition,	pyattr_set_localPosition),
+	KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",	KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
+	KX_PYATTRIBUTE_RW_FUNCTION("localScaling",	KX_GameObject, pyattr_get_localScaling,	pyattr_set_localScaling),
+	KX_PYATTRIBUTE_RO_FUNCTION("worldScaling",	KX_GameObject, pyattr_get_worldScaling),
+	KX_PYATTRIBUTE_RO_FUNCTION("attrDict",	KX_GameObject, pyattr_get_attrDict),
+	
+	/* Experemental, dont rely on these yet */
+	KX_PYATTRIBUTE_RO_FUNCTION("sensors",		KX_GameObject, pyattr_get_sensors),
+	KX_PYATTRIBUTE_RO_FUNCTION("controllers",	KX_GameObject, pyattr_get_controllers),
+	KX_PYATTRIBUTE_RO_FUNCTION("actuators",		KX_GameObject, pyattr_get_actuators),
 	{NULL} //Sentinel
 };
 
@@ -1064,32 +1225,22 @@ bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
 }
 */
 
-PyObject* KX_GameObject::PyReplaceMesh(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PyReplaceMesh(PyObject* value)
 {
 	KX_Scene *scene = KX_GetActiveScene();
-	char* meshname;
-	void* mesh_pt;
-
-	meshname = PyString_AsString(value);
-	if (meshname==NULL) {
-		PyErr_SetString(PyExc_ValueError, "Expected a mesh name");
-		return NULL;
-	}
-	mesh_pt = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname));
+	RAS_MeshObject* new_mesh;
 	
-	if (mesh_pt==NULL) {
-		PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist");
+	if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject"))
 		return NULL;
-	}
-	scene->ReplaceMesh(this, (class RAS_MeshObject*)mesh_pt);
 	
+	scene->ReplaceMesh(this, new_mesh);
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_GameObject::PyEndObject(PyObject* self)
+PyObject* KX_GameObject::PyEndObject()
 {
-
 	KX_Scene *scene = KX_GetActiveScene();
+	
 	scene->DelayedRemoveObject(this);
 	
 	Py_RETURN_NONE;
@@ -1097,101 +1248,161 @@ PyObject* KX_GameObject::PyEndObject(PyObject* self)
 }
 
 
-PyObject* KX_GameObject::PyGetPosition(PyObject* self)
+PyObject* KX_GameObject::PyGetPosition()
 {
 	ShowDeprecationWarning("getPosition()", "the position property");
 	return PyObjectFrom(NodeGetWorldPosition());
 }
 
-
-Py_ssize_t KX_GameObject::Map_Len(PyObject* self_v)
-{
-	return (static_cast<KX_GameObject*>(self_v))->GetPropertyCount();
-}
-
-
 PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item)
 {
-	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-	const char *attr= PyString_AsString(item);
+	KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+	const char *attr_str= PyString_AsString(item);
 	CValue* resultattr;
 	PyObject* pyconvert;
 	
-	
-	if(attr==NULL) {
-		PyErr_SetString(PyExc_TypeError, "KX_GameObject key but a string");
+	if (self==NULL) {
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
 		return NULL;
 	}
 	
-	resultattr = self->GetProperty(attr);
-	
-	if(resultattr==NULL) {
-		PyErr_SetString(PyExc_KeyError, "KX_GameObject key does not exist");
+	/* first see if the attributes a string and try get the cvalue attribute */
+	if(attr_str && (resultattr=self->GetProperty(attr_str))) {
+		pyconvert = resultattr->ConvertValueToPython();			
+		return pyconvert ? pyconvert:resultattr->GetProxy();
+	}
+	/* no CValue attribute, try get the python only m_attr_dict attribute */
+	else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
+		
+		if (attr_str)
+			PyErr_Clear();
+		Py_INCREF(pyconvert);
+		return pyconvert;
+	}
+	else {
+		if(attr_str)	PyErr_Format(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key \"%s\" does not exist", attr_str);
+		else			PyErr_SetString(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key does not exist");
 		return NULL;
 	}
-	
-	pyconvert = resultattr->ConvertValueToPython();
-	
-	return pyconvert ? pyconvert:resultattr;
+		
 }
 
 
 int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
 {
-	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-	const char *attr= PyString_AsString(key);
+	KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+	const char *attr_str= PyString_AsString(key);
+	if(attr_str==NULL)
+		PyErr_Clear();
 	
-	if(attr==NULL) {
-		PyErr_SetString(PyExc_TypeError, "KX_GameObject key but a string");
-		return 1;
+	if (self==NULL) {
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+		return -1;
 	}
 	
 	if (val==NULL) { /* del ob["key"] */
-		if (self->RemoveProperty(attr)==false) {
-			PyErr_Format(PyExc_KeyError, "KX_GameObject key \"%s\" not found", attr);
-			return 1;
+		int del= 0;
+		
+		/* try remove both just incase */
+		if(attr_str)
+			del |= (self->RemoveProperty(attr_str)==true) ? 1:0;
+		
+		if(self->m_attr_dict)
+			del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0;
+		
+		if (del==0) {
+			if(attr_str)	PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str);
+			else			PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key could not be set");
+			return -1;
+		}
+		else if (self->m_attr_dict) {
+			PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */
 		}
 	}
 	else { /* ob["key"] = value */
-		CValue* vallie = self->ConvertPythonToValue(val);
+		int set= 0;
 		
-		if(vallie==NULL)
-			return 1; /* ConvertPythonToValue sets the error */
+		/* as CValue */
+		if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
+		{
+			CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */
+			
+			if(vallie)
+			{
+				CValue* oldprop = self->GetProperty(attr_str);
+				
+				if (oldprop)
+					oldprop->SetValue(vallie);
+				else
+					self->SetProperty(attr_str, vallie);
+				
+				vallie->Release();
+				set= 1;
+				
+				/* try remove dict value to avoid double ups */
+				if (self->m_attr_dict){
+					if (PyDict_DelItem(self->m_attr_dict, key) != 0)
+						PyErr_Clear();
+				}
+			}
+			else {
+				PyErr_Clear();
+			}
+		}
 		
-		CValue* oldprop = self->GetProperty(attr);
+		if(set==0)
+		{
+			if (self->m_attr_dict==NULL) /* lazy init */
+				self->m_attr_dict= PyDict_New();
+			
+			
+			if(PyDict_SetItem(self->m_attr_dict, key, val)==0)
+			{
+				if(attr_str)
+					self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */
+				set= 1;
+			}
+			else {
+				if(attr_str)	PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str);
+				else			PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key not be added to internal dictionary");
+			}
+		}
 		
-		if (oldprop)
-			oldprop->SetValue(vallie);
-		else
-			self->SetProperty(attr, vallie);
+		if(set==0)
+			return -1; /* pythons error value */
 		
-		vallie->Release();
 	}
 	
-	return 0;
+	return 0; /* success */
 }
 
-
+/* Cant set the len otherwise it can evaluate as false */
 PyMappingMethods KX_GameObject::Mapping = {
-	(lenfunc)KX_GameObject::Map_Len, 			/*inquiry mp_length */
+	(lenfunc)NULL					, 			/*inquiry mp_length */
 	(binaryfunc)KX_GameObject::Map_GetItem,		/*binaryfunc mp_subscript */
 	(objobjargproc)KX_GameObject::Map_SetItem,	/*objobjargproc mp_ass_subscript */
 };
 
-
 PyTypeObject KX_GameObject::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_GameObject",
-		sizeof(KX_GameObject),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
 		0,
 		py_base_repr,
-		0,0,0,0,0,0,
+		0,0,
+		&Mapping,
+		0,0,0,
 		py_base_getattro,
 		py_base_setattro,
 		0,0,0,0,0,0,0,0,0,
@@ -1220,8 +1431,10 @@ PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 	KX_GameObject* parent = self->GetParent();
-	if (parent)
-		return parent->AddRef();
+	if (parent) {
+		parent->Release(); /* self->GetParent() AddRef's */
+		return parent->GetProxy();
+	}
 	Py_RETURN_NONE;
 }
 
@@ -1238,7 +1451,7 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd
 	KX_IPhysicsController *spc = self->GetPhysicsController();
 	MT_Scalar val = PyFloat_AsDouble(value);
 	if (val < 0.0f) { /* also accounts for non float */
-		PyErr_SetString(PyExc_AttributeError, "expected a float zero or above");
+		PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
 		return 1;
 	}
 
@@ -1248,6 +1461,53 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd
 	return 0;
 }
 
+PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	KX_IPhysicsController *spc = self->GetPhysicsController();
+	return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
+}
+
+int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	KX_IPhysicsController *spc = self->GetPhysicsController();
+	MT_Scalar val = PyFloat_AsDouble(value);
+	if (val < 0.0f) { /* also accounts for non float */
+		PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
+		return 1;
+	}
+
+	if (spc)
+		spc->SetLinVelocityMin(val);
+
+	return 0;
+}
+
+PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	KX_IPhysicsController *spc = self->GetPhysicsController();
+	return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
+}
+
+int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	KX_IPhysicsController *spc = self->GetPhysicsController();
+	MT_Scalar val = PyFloat_AsDouble(value);
+	if (val < 0.0f) { /* also accounts for non float */
+		PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
+		return 1;
+	}
+
+	if (spc)
+		spc->SetLinVelocityMax(val);
+
+	return 0;
+}
+
+
 PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
@@ -1259,7 +1519,7 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 	int param = PyObject_IsTrue( value );
 	if (param == -1) {
-		PyErr_SetString(PyExc_AttributeError, "expected True or False");
+		PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False");
 		return 1;
 	}
 
@@ -1268,88 +1528,120 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
 	return 0;
 }
 
-PyObject* KX_GameObject::pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 	return PyObjectFrom(self->NodeGetWorldPosition());
 }
 
-int KX_GameObject::pyattr_set_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 	MT_Point3 pos;
 	if (!PyVecTo(value, pos))
 		return 1;
 	
-	self->NodeSetLocalPosition(pos);
-	self->NodeUpdateGS(0.f,true);
+	self->NodeSetWorldPosition(pos);
+	self->NodeUpdateGS(0.f);
 	return 0;
 }
 
-
-PyObject* KX_GameObject::pyattr_get_orientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-	return PyObjectFrom(self->NodeGetWorldOrientation());
+	if (self->GetSGNode())
+		return PyObjectFrom(self->GetSGNode()->GetLocalPosition());
+	else
+		return PyObjectFrom(dummy_point);
 }
 
-int KX_GameObject::pyattr_set_orientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-	if (!PySequence_Check(value)) {
-		PyErr_SetString(PyExc_AttributeError, "'orientation' attribute needs to be a sequence");
+	MT_Point3 pos;
+	if (!PyVecTo(value, pos))
 		return 1;
-	}
+	
+	self->NodeSetLocalPosition(pos);
+	self->NodeUpdateGS(0.f);
+	return 0;
+}
 
-	MT_Matrix3x3 rot;
-	if (PyObject_IsMT_Matrix(value, 3))
+PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	if (self->GetPhysicsController())
 	{
-		if (PyMatTo(value, rot))
-		{
-			self->NodeSetLocalOrientation(rot);
-			self->NodeUpdateGS(0.f,true);
-			return 0;
-		}
-		return 1;
+		return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
 	}
+	return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
+}
 
-	if (PySequence_Size(value) == 4)
-	{
-		MT_Quaternion qrot;
-		if (PyVecTo(value, qrot))
-		{
-			rot.setRotation(qrot);
-			self->NodeSetLocalOrientation(rot);
-			self->NodeUpdateGS(0.f,true);
-			return 0;
-		}
-		return 1;
-	}
+PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	return PyObjectFrom(self->NodeGetWorldOrientation());
+}
 
-	if (PySequence_Size(value) == 3)
-	{
-		MT_Vector3 erot;
-		if (PyVecTo(value, erot))
-		{
-			rot.setEuler(erot);
-			self->NodeSetLocalOrientation(rot);
-			self->NodeUpdateGS(0.f,true);
-			return 0;
-		}
-		return 1;
+int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	
+	/* if value is not a sequence PyOrientationTo makes an error */
+	MT_Matrix3x3 rot;
+	if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
+		return NULL;
+
+	if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) {
+		self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
 	}
+	else {
+		self->NodeSetLocalOrientation(rot);
+	}
+	
+	self->NodeUpdateGS(0.f);
+	return 0;
+}
 
-	PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence");
-	return 1;
+PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	if (self->GetSGNode())
+		return PyObjectFrom(self->GetSGNode()->GetLocalOrientation());
+	else
+		return PyObjectFrom(dummy_orientation);
+}
+
+int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	
+	/* if value is not a sequence PyOrientationTo makes an error */
+	MT_Matrix3x3 rot;
+	if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, "))
+		return NULL;
+
+	self->NodeSetLocalOrientation(rot);
+	self->NodeUpdateGS(0.f);
+	return 0;
 }
 
-PyObject* KX_GameObject::pyattr_get_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 	return PyObjectFrom(self->NodeGetWorldScaling());
 }
 
-int KX_GameObject::pyattr_set_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	if (self->GetSGNode())
+		return PyObjectFrom(self->GetSGNode()->GetLocalScale());
+	else
+		return PyObjectFrom(dummy_scaling);
+}
+
+int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 	MT_Vector3 scale;
@@ -1357,15 +1649,15 @@ int KX_GameObject::pyattr_set_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *at
 		return 1;
 
 	self->NodeSetLocalScale(scale);
-	self->NodeUpdateGS(0.f,true);
+	self->NodeUpdateGS(0.f);
 	return 0;
 }
 
 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-	SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
-	if (sg_parent && sg_parent->IsSlowParent()) {
+	SG_Node* sg_parent;
+	if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) {
 		return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset());
 	} else {
 		return PyFloat_FromDouble(0.0);
@@ -1375,16 +1667,16 @@ PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUT
 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-	MT_Scalar val = PyFloat_AsDouble(value);
-	SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
-	if (val < 0.0f) { /* also accounts for non float */
-		PyErr_SetString(PyExc_AttributeError, "expected a float zero or above");
-		return 1;
+	if (self->GetSGNode()) {
+		MT_Scalar val = PyFloat_AsDouble(value);
+		SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
+		if (val < 0.0f) { /* also accounts for non float */
+			PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
+			return 1;
+		}
+		if (sg_parent && sg_parent->IsSlowParent())
+			static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
 	}
-
-	if (sg_parent && sg_parent->IsSlowParent())
-		static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
-
 	return 0;
 }
 
@@ -1403,32 +1695,110 @@ int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attr
 	unsigned int state = 0;
 	
 	if (state_i == -1 && PyErr_Occurred()) {
-		PyErr_SetString(PyExc_TypeError, "expected an int bit field");
+		PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field");
 		return 1;
 	}
 	
 	state |= state_i;
 	if ((state & ((1<<30)-1)) == 0) {
-		PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
+		PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
 		return 1;
 	}
 	self->SetState(state);
 	return 0;
 }
 
-/* __dict__ only for the purpose of giving useful dir() results */
-PyObject* KX_GameObject::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+	PyObject *meshes= PyList_New(self->m_meshes.size());
+	int i;
+	
+	for(i=0; i < (int)self->m_meshes.size(); i++)
+	{
+		KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
+		PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true));
+	}
+	
+	return meshes;
+}
+
+/* experemental! */
+PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
+}
+
+PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS);
+}
+
+PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
+}
+
+PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-	PyObject *dict_str = PyString_FromString("__dict__");
-	PyObject *dict= _getattr_dict(self->SCA_IObject::py_getattro(dict_str), KX_GameObject::Methods, KX_GameObject::Attributes);
-	Py_DECREF(dict_str);
 	
+	if(self->m_attr_dict==NULL)
+		self->m_attr_dict= PyDict_New();
+	
+	Py_INCREF(self->m_attr_dict);
+	return self->m_attr_dict;
+}
+
+/* We need these because the macros have a return in them */
+PyObject* KX_GameObject::py_getattro__internal(PyObject *attr)
+{
+	py_getattro_up(SCA_IObject);
+}
+
+int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value)	// py_setattro method
+{
+	py_setattro_up(SCA_IObject);
+}
+
+
+PyObject* KX_GameObject::py_getattro(PyObject *attr)
+{
+	PyObject *object= py_getattro__internal(attr);
+	
+	if (object==NULL && m_attr_dict)
+	{
+		/* backup the exception incase the attr doesnt exist in the dict either */
+		PyObject *err_type, *err_value, *err_tb;
+		PyErr_Fetch(&err_type, &err_value, &err_tb);
+		
+		object= PyDict_GetItem(m_attr_dict, attr);
+		if (object) {
+			Py_INCREF(object);
+			
+			PyErr_Clear();
+			Py_XDECREF( err_type );
+			Py_XDECREF( err_value );
+			Py_XDECREF( err_tb );
+		}
+		else {
+			PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */
+		}
+	}
+	return object;
+}
+
+PyObject* KX_GameObject::py_getattro_dict() {
+	//py_getattro_dict_up(SCA_IObject);
+	PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict);
 	if(dict==NULL)
 		return NULL;
 	
+	/* normally just return this but KX_GameObject has some more items */
+
+	
 	/* Not super fast getting as a list then making into dict keys but its only for dir() */
-	PyObject *list= self->ConvertKeysToPython();
+	PyObject *list= ConvertKeysToPython();
 	if(list)
 	{
 		int i;
@@ -1440,28 +1810,69 @@ PyObject* KX_GameObject::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_
 	
 	Py_DECREF(list);
 	
+	/* Add m_attr_dict if we have it */
+	if(m_attr_dict)
+		PyDict_Update(dict, m_attr_dict);
+	
 	return dict;
 }
 
-PyObject* KX_GameObject::py_getattro(PyObject *attr)
+int KX_GameObject::py_setattro(PyObject *attr, PyObject *value)	// py_setattro method
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
+	int ret;
 	
-	py_getattro_up(SCA_IObject);
+	ret= py_setattro__internal(attr, value);
+	
+	if (ret==PY_SET_ATTR_SUCCESS) {
+		/* remove attribute in our own dict to avoid double ups */
+		/* NOTE: Annoying that we also do this for setting builtin attributes like mass and visibility :/ */
+		if (m_attr_dict) {
+			if (PyDict_DelItem(m_attr_dict, attr) != 0)
+				PyErr_Clear();
+		}
+	}
+	
+	if (ret==PY_SET_ATTR_COERCE_FAIL) {
+		/* CValue attribute exists, remove CValue and add PyDict value */
+		RemoveProperty(PyString_AsString(attr));
+		ret= PY_SET_ATTR_MISSING;
+	}
+	
+	if (ret==PY_SET_ATTR_MISSING) {
+		/* Lazy initialization */
+		if (m_attr_dict==NULL)
+			m_attr_dict = PyDict_New();
+		
+		if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
+			PyErr_Clear();
+			ret= PY_SET_ATTR_SUCCESS;
+		}
+		else {
+			PyErr_Format(PyExc_AttributeError, "gameOb.myAttr = value: KX_GameObject, failed assigning value to internal dictionary");
+			ret= PY_SET_ATTR_FAIL;
+		}
+	}
+	
+	return ret;	
 }
 
-int KX_GameObject::py_setattro(PyObject *attr, PyObject *value)	// py_setattro method
+
+int	KX_GameObject::py_delattro(PyObject *attr)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
+	char *attr_str= PyString_AsString(attr); 
+	
+	if (RemoveProperty(attr_str)) // XXX - should call CValues instead but its only 2 lines here
+		return 0;
 	
-	return SCA_IObject::py_setattro(attr, value);
+	if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0))
+		return 0;
+	
+	PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str);
+	return 1;
 }
 
-PyObject* KX_GameObject::PyApplyForce(PyObject* self, PyObject* args)
+
+PyObject* KX_GameObject::PyApplyForce(PyObject* args)
 {
 	int local = 0;
 	PyObject* pyvect;
@@ -1476,7 +1887,7 @@ PyObject* KX_GameObject::PyApplyForce(PyObject* self, PyObject* args)
 	return NULL;
 }
 
-PyObject* KX_GameObject::PyApplyTorque(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyApplyTorque(PyObject* args)
 {
 	int local = 0;
 	PyObject* pyvect;
@@ -1491,7 +1902,7 @@ PyObject* KX_GameObject::PyApplyTorque(PyObject* self, PyObject* args)
 	return NULL;
 }
 
-PyObject* KX_GameObject::PyApplyRotation(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyApplyRotation(PyObject* args)
 {
 	int local = 0;
 	PyObject* pyvect;
@@ -1506,7 +1917,7 @@ PyObject* KX_GameObject::PyApplyRotation(PyObject* self, PyObject* args)
 	return NULL;
 }
 
-PyObject* KX_GameObject::PyApplyMovement(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyApplyMovement(PyObject* args)
 {
 	int local = 0;
 	PyObject* pyvect;
@@ -1521,7 +1932,7 @@ PyObject* KX_GameObject::PyApplyMovement(PyObject* self, PyObject* args)
 	return NULL;
 }
 
-PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args)
 {
 	// only can get the velocity if we have a physics object connected to us...
 	int local = 0;
@@ -1535,7 +1946,7 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args)
 	}
 }
 
-PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args)
 {
 	int local = 0;
 	PyObject* pyvect;
@@ -1550,7 +1961,7 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args)
 	return NULL;
 }
 
-PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args)
 {
 	// only can get the velocity if we have a physics object connected to us...
 	int local = 0;
@@ -1564,7 +1975,7 @@ PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args)
 	}
 }
 
-PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args)
 {
 	int local = 0;
 	PyObject* pyvect;
@@ -1579,7 +1990,7 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
 	return NULL;
 }
 
-PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PySetVisible(PyObject* args)
 {
 	int visible, recursive = 0;
 	if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive))
@@ -1591,13 +2002,23 @@ PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args)
 	
 }
 
-PyObject* KX_GameObject::PyGetVisible(PyObject* self)
+PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
+{
+	int occlusion, recursive = 0;
+	if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive))
+		return NULL;
+	
+	SetOccluder(occlusion ? true:false, recursive ? true:false);
+	Py_RETURN_NONE;
+}
+
+PyObject* KX_GameObject::PyGetVisible()
 {
 	ShowDeprecationWarning("getVisible()", "the visible property");
 	return PyInt_FromLong(m_bVisible);	
 }
 
-PyObject* KX_GameObject::PyGetState(PyObject* self)
+PyObject* KX_GameObject::PyGetState()
 {
 	ShowDeprecationWarning("getState()", "the state property");
 	int state = 0;
@@ -1605,7 +2026,7 @@ PyObject* KX_GameObject::PyGetState(PyObject* self)
 	return PyInt_FromLong(state);
 }
 
-PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PySetState(PyObject* value)
 {
 	ShowDeprecationWarning("setState()", "the state property");
 	int state_i = PyInt_AsLong(value);
@@ -1626,7 +2047,7 @@ PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
 {
 	// only can get the velocity if we have a physics object connected to us...
 	MT_Point3 point(0.0,0.0,0.0);
@@ -1652,112 +2073,94 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args)
 
 
 
-PyObject* KX_GameObject::PyGetMass(PyObject* self)
+PyObject* KX_GameObject::PyGetMass()
 {
 	ShowDeprecationWarning("getMass()", "the mass property");
-	return PyFloat_FromDouble(GetPhysicsController()->GetMass());
+	return PyFloat_FromDouble((GetPhysicsController() != NULL) ? GetPhysicsController()->GetMass() : 0.0f);
 }
 
-
-
-PyObject* KX_GameObject::PyGetReactionForce(PyObject* self)
+PyObject* KX_GameObject::PyGetReactionForce()
 {
 	// only can get the velocity if we have a physics object connected to us...
-	return PyObjectFrom(GetPhysicsController()->getReactionForce());
+	
+	// XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce
+	/*
+	if (GetPhysicsController())
+		return PyObjectFrom(GetPhysicsController()->getReactionForce());
+	return PyObjectFrom(dummy_point);
+	*/
+	
+	return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
+	
 }
 
 
 
-PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self)
+PyObject* KX_GameObject::PyEnableRigidBody()
 {
-	GetPhysicsController()->setRigidBody(true);
+	if(GetPhysicsController())
+		GetPhysicsController()->setRigidBody(true);
 
 	Py_RETURN_NONE;
 }
 
 
 
-PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self)
+PyObject* KX_GameObject::PyDisableRigidBody()
 {
-	GetPhysicsController()->setRigidBody(false);
+	if(GetPhysicsController())
+		GetPhysicsController()->setRigidBody(false);
 
 	Py_RETURN_NONE;
 }
 
 
 
-PyObject* KX_GameObject::PyGetParent(PyObject* self)
+PyObject* KX_GameObject::PyGetParent()
 {
 	ShowDeprecationWarning("getParent()", "the parent property");
 	KX_GameObject* parent = this->GetParent();
-	if (parent)
-		return parent->AddRef();
+	if (parent) {
+		parent->Release(); /* self->GetParent() AddRef's */
+		return parent->GetProxy();
+	}
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PySetParent(PyObject* value)
 {
-	if (!PyObject_TypeCheck(value, &KX_GameObject::Type)) {
-		PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type");
-		return NULL;
-	}
-	
-	// The object we want to set as parent
-	CValue *m_ob = (CValue*)value;
-	KX_GameObject *obj = ((KX_GameObject*)m_ob);
 	KX_Scene *scene = KX_GetActiveScene();
+	KX_GameObject *obj;
+	
+	if (!ConvertPythonToGameObject(value, &obj, false, "gameOb.setParent(value): KX_GameObject"))
+		return NULL;
 	
 	this->SetParent(scene, obj);
-		
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
+PyObject* KX_GameObject::PyRemoveParent()
 {
 	KX_Scene *scene = KX_GetActiveScene();
+	
 	this->RemoveParent(scene);
 	Py_RETURN_NONE;
 }
 
-
-static void walk_children(SG_Node* node, CListValue* list, bool recursive)
-{
-	NodeList& children = node->GetSGChildren();
-
-	for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
-	{
-		SG_Node* childnode = (*childit);
-		CValue* childobj = (CValue*)childnode->GetSGClientObject();
-		if (childobj != NULL) // This is a GameObject
-		{
-			// add to the list
-			list->Add(childobj->AddRef());
-		}
-		
-		// if the childobj is NULL then this may be an inverse parent link
-		// so a non recursive search should still look down this node.
-		if (recursive || childobj==NULL) {
-			walk_children(childnode, list, recursive);
-		}
-	}
-}
-
-PyObject* KX_GameObject::PyGetChildren(PyObject* self)
+PyObject* KX_GameObject::PyGetChildren()
 {
-	CListValue* list = new CListValue();
-	walk_children(m_pSGNode, list, 0);
-	return list;
+	return GetChildren()->NewProxy(true);
 }
 
-PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
+PyObject* KX_GameObject::PyGetChildrenRecursive()
 {
-	CListValue* list = new CListValue();
-	walk_children(m_pSGNode, list, 1);
-	return list;
+	return GetChildrenRecursive()->NewProxy(true);
 }
 
-PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyGetMesh(PyObject* args)
 {
+	ShowDeprecationWarning("getMesh()", "the meshes property");
+	
 	int mesh = 0;
 
 	if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh))
@@ -1766,7 +2169,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args)
 	if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
 	{
 		KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
-		return meshproxy;
+		return meshproxy->NewProxy(true); // XXX Todo Python own.
 	}
 	
 	Py_RETURN_NONE;
@@ -1776,7 +2179,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args)
 
 
 
-PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value)
 {
 	float collisionMargin = PyFloat_AsDouble(value);
 	
@@ -1796,7 +2199,7 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
 
 
 
-PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyApplyImpulse(PyObject* args)
 {
 	PyObject* pyattach;
 	PyObject* pyimpulse;
@@ -1823,7 +2226,7 @@ PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args)
 
 
 
-PyObject* KX_GameObject::PySuspendDynamics(PyObject* self)
+PyObject* KX_GameObject::PySuspendDynamics()
 {
 	SuspendDynamics();
 	Py_RETURN_NONE;
@@ -1831,7 +2234,7 @@ PyObject* KX_GameObject::PySuspendDynamics(PyObject* self)
 
 
 
-PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self)
+PyObject* KX_GameObject::PyRestoreDynamics()
 {
 	RestoreDynamics();
 	Py_RETURN_NONE;
@@ -1839,7 +2242,7 @@ PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self)
 
 
 
-PyObject* KX_GameObject::PyGetOrientation(PyObject* self) //keywords
+PyObject* KX_GameObject::PyGetOrientation() //keywords
 {
 	ShowDeprecationWarning("getOrientation()", "the orientation property");
 	return PyObjectFrom(NodeGetWorldOrientation());
@@ -1847,29 +2250,21 @@ PyObject* KX_GameObject::PyGetOrientation(PyObject* self) //keywords
 
 
 
-PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PySetOrientation(PyObject* value)
 {
 	ShowDeprecationWarning("setOrientation()", "the orientation property");
-	MT_Matrix3x3 matrix;
-	if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix))
-	{
-		NodeSetLocalOrientation(matrix);
-		NodeUpdateGS(0.f,true);
-		Py_RETURN_NONE;
-	}
+	MT_Matrix3x3 rot;
+	
+	/* if value is not a sequence PyOrientationTo makes an error */
+	if (!PyOrientationTo(value, rot, "gameOb.setOrientation(sequence): KX_GameObject, "))
+		return NULL;
 
-	MT_Quaternion quat;
-	if (PyVecTo(value, quat))
-	{
-		matrix.setRotation(quat);
-		NodeSetLocalOrientation(matrix);
-		NodeUpdateGS(0.f,true);
-		Py_RETURN_NONE;
-	}
-	return NULL;
+	NodeSetLocalOrientation(rot);
+	NodeUpdateGS(0.f);
+	Py_RETURN_NONE;
 }
 
-PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args)
+PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
 {
 	PyObject* pyvect;
 	int axis = 2; //z axis is the default
@@ -1884,14 +2279,14 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args)
 			if (fac> 1.0) fac= 1.0;
 			
 			AlignAxisToVect(vect,axis,fac);
-			NodeUpdateGS(0.f,true);
+			NodeUpdateGS(0.f);
 			Py_RETURN_NONE;
 		}
 	}
 	return NULL;
 }
 
-PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
 {
 	MT_Vector3 vect;
 	if (PyVecTo(value, vect))
@@ -1901,34 +2296,35 @@ PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value)
 	return NULL;
 }
 
-PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PySetPosition(PyObject* value)
 {
 	ShowDeprecationWarning("setPosition()", "the position property");
 	MT_Point3 pos;
 	if (PyVecTo(value, pos))
 	{
 		NodeSetLocalPosition(pos);
-		NodeUpdateGS(0.f,true);
+		NodeUpdateGS(0.f);
 		Py_RETURN_NONE;
 	}
 
 	return NULL;
 }
 
-PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PySetWorldPosition(PyObject* value)
 {
+	ShowDeprecationWarning("setWorldPosition()", "the worldPosition property");
 	MT_Point3 pos;
 	if (PyVecTo(value, pos))
 	{
 		NodeSetWorldPosition(pos);
-		NodeUpdateGS(0.f,true);
+		NodeUpdateGS(0.f);
 		Py_RETURN_NONE;
 	}
 
 	return NULL;
 }
 
-PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self)
+PyObject* KX_GameObject::PyGetPhysicsId()
 {
 	KX_IPhysicsController* ctrl = GetPhysicsController();
 	uint_ptr physid=0;
@@ -1939,9 +2335,19 @@ PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self)
 	return PyInt_FromLong((long)physid);
 }
 
-PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self)
+PyObject* KX_GameObject::PyGetPropertyNames()
 {
-	return ConvertKeysToPython();
+	PyObject *list=  ConvertKeysToPython();
+	
+	if(m_attr_dict) {
+		PyObject *key, *value;
+		Py_ssize_t pos = 0;
+
+		while (PyDict_Next(m_attr_dict, &pos, &key, &value)) {
+			PyList_Append(list, key);
+		}
+	}
+	return list;
 }
 
 KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo,
@@ -1955,7 +2361,7 @@ KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo,
 	PyErr_Clear();
 	
 	KX_GameObject *other;
-	if (ConvertPythonToGameObject(value, &other, false))
+	if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject"))
 	{
 		return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
 	}
@@ -1978,12 +2384,12 @@ KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo,
 		PyErr_Clear();
 		
 		KX_GameObject *other;
-		if (ConvertPythonToGameObject(value, &other, false))
+		if (ConvertPythonToGameObject(value, &other, false, "")) /* error will be overwritten */
 		{
 			toPoint = other->NodeGetWorldPosition();
 		} else
 		{
-			PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type");
+			PyErr_SetString(PyExc_TypeError, "gameOb.getVectTo(other): KX_GameObject, expected a 3D Vector or KX_GameObject type");
 			return NULL;
 		}
 	}
@@ -2072,12 +2478,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
 		KX_GameObject *other;
 		PyErr_Clear();
 		
-		if (ConvertPythonToGameObject(pyarg, &other, false))
+		if (ConvertPythonToGameObject(pyarg, &other, false, "")) /* error will be overwritten */
 		{
 			toPoint = other->NodeGetWorldPosition();
 		} else
 		{
-			PyErr_SetString(PyExc_TypeError, "the first argument to rayCastTo must be a vector or a KX_GameObject");
+			PyErr_SetString(PyExc_TypeError, "gameOb.rayCastTo(other,dist,prop): KX_GameObject, the first argument to rayCastTo must be a vector or a KX_GameObject");
 			return NULL;
 		}
 	}
@@ -2106,7 +2512,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
 	KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
 
     if (m_pHitObject)
-		return m_pHitObject->AddRef();
+		return m_pHitObject->GetProxy();
 	
 	Py_RETURN_NONE;
 }
@@ -2148,7 +2554,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
 	{
 		PyErr_Clear();
 		
-		if (ConvertPythonToGameObject(pyto, &other, false))
+		if (ConvertPythonToGameObject(pyto, &other, false, ""))  /* error will be overwritten */
 		{
 			toPoint = other->NodeGetWorldPosition();
 		} else
@@ -2165,12 +2571,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
 	{
 		PyErr_Clear();
 		
-		if (ConvertPythonToGameObject(pyfrom, &other, false))
+		if (ConvertPythonToGameObject(pyfrom, &other, false, "")) /* error will be overwritten */
 		{
 			fromPoint = other->NodeGetWorldPosition();
 		} else
 		{
-			PyErr_SetString(PyExc_TypeError, "the second optional argument to rayCast must be a vector or a KX_GameObject");
+			PyErr_SetString(PyExc_TypeError, "gameOb.rayCast(to,from,dist,prop,face,xray,poly): KX_GameObject, the second optional argument to rayCast must be a vector or a KX_GameObject");
 			return NULL;
 		}
 	}
@@ -2208,7 +2614,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
 	{
 		PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
 		if (returnValue) { // unlikely this would ever fail, if it does python sets an error
-			PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
+			PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy());
 			PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
 			PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
 			if (poly)
@@ -2218,7 +2624,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
 					// if this field is set, then we can trust that m_hitPolygon is a valid polygon
 					RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
 					KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon);
-					PyTuple_SET_ITEM(returnValue, 3, polyproxy);
+					PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true));
 				}
 				else
 				{
@@ -2236,6 +2642,26 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
 		return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
 }
 
+KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, 
+						   "sendMessage(subject, [body, to])\n"
+"sends a message in same manner as a message actuator"
+"subject = Subject of the message (string)"
+"body = Message body (string)"
+"to = Name of object to send the message to")
+{
+	KX_Scene *scene = KX_GetActiveScene();
+	char* subject;
+	char* body = (char *)"";
+	char* to = (char *)"";
+	const STR_String& from = GetName();
+
+	if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to))
+		return NULL;
+	
+	scene->GetNetworkScene()->SendMessage(to, from, subject, body);
+	Py_RETURN_NONE;
+}
+
 /* --------------------------------------------------------------------- 
  * Some stuff taken from the header
  * --------------------------------------------------------------------- */
@@ -2258,10 +2684,10 @@ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
 	}
 }
 
-bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok)
+bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
 {
 	if (value==NULL) {
-		PyErr_SetString(PyExc_TypeError, "Error in ConvertPythonToGameObject, python pointer NULL, should never happen");
+		PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
 		*object = NULL;
 		return false;
 	}
@@ -2272,33 +2698,40 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py
 		if (py_none_ok) {
 			return true;
 		} else {
-			PyErr_SetString(PyExc_TypeError, "Expected KX_GameObject or a string for a name of a KX_GameObject, None is invalid");
+			PyErr_Format(PyExc_TypeError, "%s, expected KX_GameObject or a KX_GameObject name, None is invalid", error_prefix);
 			return false;
 		}
 	}
 	
 	if (PyString_Check(value)) {
-		*object = (KX_GameObject *)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
+		*object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
 		
 		if (*object) {
 			return true;
 		} else {
-			PyErr_SetString(PyExc_ValueError, "Requested name did not match any KX_GameObject");
+			PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value));
 			return false;
 		}
 	}
 	
 	if (PyObject_TypeCheck(value, &KX_GameObject::Type)) {
-		*object = static_cast<KX_GameObject*>(value);
+		*object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
+		
+		/* sets the error */
+		if (*object==NULL) {
+			PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
+			return false;
+		}
+		
 		return true;
 	}
 	
 	*object = NULL;
 	
 	if (py_none_ok) {
-		PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject, a string or None");
+		PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject, a string or None", error_prefix);
 	} else {
-		PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject or a string");
+		PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject or a string", error_prefix);
 	}
 	
 	return false;
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 9ed35b6d26bc50063184b7330edaf0f18cec3cfa..e5b26539d4d6b0232ebcc0ef2a2ae93dd0d9d6e7 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -51,15 +51,18 @@
 #include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */
 #define KX_OB_DYNAMIC 1
 
-
 //Forward declarations.
 struct KX_ClientObjectInfo;
 class KX_RayCast;
 class RAS_MeshObject;
 class KX_IPhysicsController;
+class PHY_IGraphicController;
 class PHY_IPhysicsEnvironment;
 struct Object;
 
+/* utility conversion function */
+bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix);
+
 /**
  * KX_GameObject is the main class for dynamic objects.
  */
@@ -74,6 +77,7 @@ protected:
 	STR_String							m_text;
 	int									m_layer;
 	std::vector<RAS_MeshObject*>		m_meshes;
+	SG_QList							m_meshSlots;	// head of mesh slots of this 
 	struct Object*						m_pBlenderObject;
 	struct Object*						m_pBlenderGroupObject;
 	
@@ -86,8 +90,10 @@ protected:
 	// culled = while rendering, depending on camera
 	bool       							m_bVisible; 
 	bool       							m_bCulled; 
+	bool								m_bOccluder;
 
 	KX_IPhysicsController*				m_pPhysicsController1;
+	PHY_IGraphicController*				m_pGraphicController;
 	// used for ray casting
 	PHY_IPhysicsEnvironment*			m_pPhysicsEnvironment;
 	STR_String							m_testPropName;
@@ -101,6 +107,28 @@ protected:
 public:
 	bool								m_isDeformable;
 
+	/**
+	 * Helper function for modules that can't include KX_ClientObjectInfo.h
+	 */
+	static KX_GameObject* GetClientObject(KX_ClientObjectInfo* info);
+
+	// Python attributes that wont convert into CValue
+	// 
+	// there are 2 places attributes can be stored, in the CValue,
+	// where attributes are converted into BGE's CValue types
+	// these can be used with property actuators
+	//
+	// For the python API, For types that cannot be converted into CValues (lists, dicts, GameObjects)
+	// these will be put into "m_attr_dict", logic bricks cannot access them.
+	// 
+	// rules for setting attributes.
+	// 
+	// * there should NEVER be a CValue and a m_attr_dict attribute with matching names. get/sets make sure of this.
+	// * if CValue conversion fails, use a PyObject in "m_attr_dict"
+	// * when assigning a value, first see if it can be a CValue, if it can remove the "m_attr_dict" and set the CValue
+	// 
+	PyObject*							m_attr_dict; 
+
 	virtual void	/* This function should be virtual - derived classed override it */
 	Relink(
 		GEN_Map<GEN_HashedPtr, void*> *map
@@ -165,11 +193,6 @@ public:
 	~KX_GameObject(
 	);
 
-		CValue*				
-	AddRef() { 
-		/* temporarily to find memleaks */ return CValue::AddRef(); 
-	}
-
 	/** 
 	 * @section Stuff which is here due to poor design.
 	 * Inherited from CValue and needs an implementation. 
@@ -206,7 +229,7 @@ public:
 	/**
 	 * Inherited from CValue -- does nothing!
 	 */
-		float				
+		double
 	GetNumber(
 	);
 
@@ -218,7 +241,7 @@ public:
 	/**
 	 * Inherited from CValue -- returns the name of this object.
 	 */
-		STR_String			
+		STR_String&			
 	GetName(
 	);
 
@@ -227,15 +250,7 @@ public:
 	 */
 		void				
 	SetName(
-		STR_String name
-	);
-
-	/**
-	 * Inherited from CValue -- does nothing.
-	 */
-		void				
-	ReplicaSetName(
-		STR_String name
+		const char *name
 	);
 
 	/** 
@@ -252,9 +267,7 @@ public:
 	 * data owned by this class is deep copied. Called internally
 	 */
 	virtual	void				
-	ProcessReplica(
-		KX_GameObject* replica
-	);
+	ProcessReplica();
 
 	/** 
 	 * Return the linear velocity of the game object.
@@ -279,6 +292,12 @@ public:
 		MT_Scalar	
 	GetMass();
 
+	/**
+	 * Return the local inertia vector of the object
+	 */
+		MT_Vector3
+	GetLocalInertia();
+
 	/** 
 	 * Return the angular velocity of the game object.
 	 */
@@ -350,6 +369,23 @@ public:
 
 	}
 
+	/**
+	 * @return a pointer to the graphic controller owner by this class 
+	 */
+	PHY_IGraphicController* GetGraphicController()
+	{
+		return m_pGraphicController;
+	}
+
+	void SetGraphicController(PHY_IGraphicController* graphiccontroller) 
+	{ 
+		m_pGraphicController = graphiccontroller;
+	}
+	/*
+	 * @add/remove the graphic controller to the physic system
+	 */
+	void ActivateGraphicController(bool active, bool recurse);
+
 	/**
 	 * @section Coordinate system manipulation functions
 	 */
@@ -367,8 +403,7 @@ public:
 
 		void						
 	NodeUpdateGS(
-		double time,
-		bool bInitiator
+		double time
 	);
 
 	const 
@@ -524,13 +559,6 @@ public:
 
 	static void UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene);
 
-	/**
-	 * Only update the transform if it's a non-dynamic object
-	 */
-		void 
-	UpdateNonDynas(
-	);
-
 	/**
 	 * Function to set IPO option at start of IPO
 	 */ 
@@ -665,19 +693,36 @@ public:
 	/**
 	 * Was this object culled?
 	 */
-		bool
+	inline bool
 	GetCulled(
 		void
-	);
+	) { return m_bCulled; }
 
 	/**
 	 * Set culled flag of this object
 	 */
-		void
+	inline void
 	SetCulled(
 		bool c
-	);
+	) { m_bCulled = c; }
+	
+	/**
+	 * Is this object an occluder?
+	 */
+	inline bool
+	GetOccluder(
+		void
+	) { return m_bOccluder; }
 
+	/**
+	 * Set occluder flag of this object
+	 */
+	void
+	SetOccluder(
+		bool v,
+		bool recursive
+	);
+	
 	/**
 	 * Change the layer of the object (when it is added in another layer
 	 * than the original layer)
@@ -752,14 +797,30 @@ public:
 	}
 	
 	KX_ClientObjectInfo* getClientInfo() { return m_pClient_info; }
+	
+	CListValue* GetChildren();
+	CListValue* GetChildrenRecursive();
+	
 	/**
 	 * @section Python interface functions.
 	 */
-
+	
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);		// py_setattro method
-	virtual PyObject* py_repr(void) { return PyString_FromString(GetName().ReadPtr()); }
+	virtual int				py_delattro(PyObject *attr);
+	virtual PyObject* py_repr(void)
+	{
+		return PyString_FromString(GetName().ReadPtr());
+	}
 	
+	
+	/* quite annoying that we need these but the bloody 
+	 * py_getattro_up and py_setattro_up macro's have a returns in them! */
+	PyObject* py_getattro__internal(PyObject *attr);
+	int py_setattro__internal(PyObject *attr, PyObject *value);		// py_setattro method
+	
+		
 	KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition);
 	KX_PYMETHOD_O(KX_GameObject,SetPosition);
 	KX_PYMETHOD_O(KX_GameObject,SetWorldPosition);
@@ -778,6 +839,7 @@ public:
 	KX_PYMETHOD_O(KX_GameObject,SetOrientation);
 	KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible);
 	KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible);
+	KX_PYMETHOD_VARARGS(KX_GameObject,SetOcclusion);
 	KX_PYMETHOD_NOARGS(KX_GameObject,GetState);
 	KX_PYMETHOD_O(KX_GameObject,SetState);
 	KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect);
@@ -802,28 +864,43 @@ public:
 	KX_PYMETHOD_DOC(KX_GameObject,rayCast);
 	KX_PYMETHOD_DOC_O(KX_GameObject,getDistanceTo);
 	KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo);
-
+	KX_PYMETHOD_DOC_VARARGS(KX_GameObject, sendMessage);
 	/* attributes */
 	static PyObject*	pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static PyObject*	pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 
 	static PyObject*	pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static int			pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 	static PyObject*	pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static int			pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-	static PyObject*	pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
-	static int			pyattr_set_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-	static PyObject*	pyattr_get_orientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
-	static int			pyattr_set_orientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-	static PyObject*	pyattr_get_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
-	static int			pyattr_set_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 	static PyObject*	pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static int			pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 	static PyObject*	pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static int			pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_meshes(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	
-	/* for dir(), python3 uses __dir__() */
-	static PyObject*	pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	/* Experemental! */
+	static PyObject*	pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	
 	/* getitem/setitem */
 	static Py_ssize_t			Map_Len(PyObject* self);
@@ -831,7 +908,6 @@ public:
 	static PyObject*			Map_GetItem(PyObject *self_v, PyObject *item);
 	static int					Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val);
 	
-	
 private :
 
 	/**	
@@ -849,8 +925,7 @@ private :
 
 };
 
-/* utility conversion function */
-bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok);
+
 
 #endif //__KX_GAMEOBJECT
 
diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h
index 13501f1fbbdf972924641721e926ba7bf20162e4..10b66da7b7666c9bbe1401b17896d5a2a065aa61 100644
--- a/source/gameengine/Ketsji/KX_IPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_IPhysicsController.h
@@ -79,6 +79,13 @@ public:
 	virtual	void setScaling(const MT_Vector3& scaling)=0;
 	virtual	MT_Scalar	GetMass()=0;
 	virtual void	SetMass(MT_Scalar newmass)=0;
+	
+	virtual	float GetLinVelocityMin()=0;
+	virtual void	SetLinVelocityMin(float newmass)=0;
+	virtual	float GetLinVelocityMax()=0;
+	virtual void	SetLinVelocityMax(float newmass)=0;
+	
+	virtual	MT_Vector3	GetLocalInertia()=0;
 	virtual	MT_Vector3	getReactionForce()=0;
 	virtual void	setRigidBody(bool rigid)=0;
 	virtual void    AddCompoundChild(KX_IPhysicsController* child) = 0;
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
index adb9c284828d2546621d538961136fbe85888f20..5e1785e9c216a9b064178caf155221b767d9bd64 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.cpp
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -164,14 +164,14 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
 	// result = true if animation has to be continued, false if animation stops
 	// maybe there are events for us in the queue !
 	bool bNegativeEvent = false;
-	int numevents = 0;
+	bool numevents = false;
 	bool bIpoStart = false;
 
 	curtime -= KX_KetsjiEngine::GetSuspendedDelta();
 
 	if (frame)
 	{
-		numevents = m_events.size();
+		numevents = m_posevent || m_negevent;
 		bNegativeEvent = IsNegativeEvent();
 		RemoveAllEvents();
 	}
@@ -273,7 +273,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
 			{
 				result = false;
 				m_bNegativeEvent = false;
-				numevents = 0;
+				numevents = false;
 			}
 			if (!m_bIpoPlaying)
 			{
@@ -413,12 +413,17 @@ int KX_IpoActuator::string2mode(char* modename) {
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_IpoActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_IpoActuator",
-	sizeof(KX_IpoActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -474,20 +479,16 @@ PyAttributeDef KX_IpoActuator::Attributes[] = {
 };
 
 PyObject* KX_IpoActuator::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
-	
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_IpoActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_IpoActuator::py_setattro(PyObject *attr, PyObject *value)	// py_setattro method
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 /* set --------------------------------------------------------------------- */
@@ -498,9 +499,7 @@ const char KX_IpoActuator::Set_doc[] =
 "\t - endframe  : last frame to use (int)\n"
 "\t - mode?     : special mode (0=normal, 1=interpret location as force, 2=additive)"
 "\tSet the properties of the actuator.\n";
-PyObject* KX_IpoActuator::PySet(PyObject* self, 
-								PyObject* args, 
-								PyObject* kwds) {
+PyObject* KX_IpoActuator::PySet(PyObject* args) {
 	
 	ShowDeprecationWarning("set()", "a number properties");
 									
@@ -511,7 +510,7 @@ PyObject* KX_IpoActuator::PySet(PyObject* self,
 	int forceToggle;
 	int modenum;
 	int startFrame, stopFrame;
-	if(!PyArg_ParseTuple(args, "siii", &mode, &startFrame, 
+	if(!PyArg_ParseTuple(args, "siii:set", &mode, &startFrame, 
 						 &stopFrame, &forceToggle)) {
 		return NULL;
 	}
@@ -541,16 +540,14 @@ const char KX_IpoActuator::SetProperty_doc[] =
 "setProperty(propname)\n"
 "\t - propname: name of the property (string)\n"
 "\tSet the property to be used in FromProp mode.\n";
-PyObject* KX_IpoActuator::PySetProperty(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds) {
+PyObject* KX_IpoActuator::PySetProperty(PyObject* args) {
 
 	ShowDeprecationWarning("setProperty()", "the propName property");
 
 	/* mode is implicit here, but not supported yet... */
 	/* args: property */
 	char *propertyName;
-	if(!PyArg_ParseTuple(args, "s", &propertyName)) {
+	if(!PyArg_ParseTuple(args, "s:setProperty", &propertyName)) {
 		return NULL;
 	}
 
@@ -564,14 +561,12 @@ const char KX_IpoActuator::SetStart_doc[] =
 "setStart(frame)\n"
 "\t - frame: first frame to use (int)\n"
 "\tSet the frame from which the ipo starts playing.\n";
-PyObject* KX_IpoActuator::PySetStart(PyObject* self, 
-									 PyObject* args, 
-									 PyObject* kwds) {
+PyObject* KX_IpoActuator::PySetStart(PyObject* args) {
 
 	ShowDeprecationWarning("setStart()", "the startFrame property");
 
 	float startArg;
-	if(!PyArg_ParseTuple(args, "f", &startArg)) {
+	if(!PyArg_ParseTuple(args, "f:setStart", &startArg)) {
 		return NULL;		
 	}
 	
@@ -583,7 +578,7 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self,
 const char KX_IpoActuator::GetStart_doc[] = 
 "getStart()\n"
 "\tReturns the frame from which the ipo starts playing.\n";
-PyObject* KX_IpoActuator::PyGetStart(PyObject* self) {
+PyObject* KX_IpoActuator::PyGetStart() {
 	ShowDeprecationWarning("getStart()", "the startFrame property");
 	return PyFloat_FromDouble(m_startframe);
 }
@@ -593,12 +588,10 @@ const char KX_IpoActuator::SetEnd_doc[] =
 "setEnd(frame)\n"
 "\t - frame: last frame to use (int)\n"
 "\tSet the frame at which the ipo stops playing.\n";
-PyObject* KX_IpoActuator::PySetEnd(PyObject* self, 
-								   PyObject* args, 
-								   PyObject* kwds) {
+PyObject* KX_IpoActuator::PySetEnd(PyObject* args) {
 	ShowDeprecationWarning("setEnd()", "the endFrame property");
 	float endArg;
-	if(!PyArg_ParseTuple(args, "f", &endArg)) {
+	if(!PyArg_ParseTuple(args, "f:setEnd", &endArg)) {
 		return NULL;		
 	}
 	
@@ -610,7 +603,7 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self,
 const char KX_IpoActuator::GetEnd_doc[] = 
 "getEnd()\n"
 "\tReturns the frame at which the ipo stops playing.\n";
-PyObject* KX_IpoActuator::PyGetEnd(PyObject* self) {
+PyObject* KX_IpoActuator::PyGetEnd() {
 	ShowDeprecationWarning("getEnd()", "the endFrame property");
 	return PyFloat_FromDouble(m_endframe);
 }
@@ -620,13 +613,11 @@ const char KX_IpoActuator::SetIpoAsForce_doc[] =
 "setIpoAsForce(force?)\n"
 "\t - force?    : interpret this ipo as a force? (KX_TRUE, KX_FALSE)\n"
 "\tSet whether to interpret the ipo as a force rather than a displacement.\n";
-PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, 
-										  PyObject* args, 
-										  PyObject* kwds) { 
+PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* args) { 
 	ShowDeprecationWarning("setIpoAsForce()", "the useIpoAsForce property");
 	int boolArg;
 	
-	if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+	if (!PyArg_ParseTuple(args, "i:setIpoAsForce", &boolArg)) {
 		return NULL;
 	}
 
@@ -640,7 +631,7 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self,
 const char KX_IpoActuator::GetIpoAsForce_doc[] = 
 "getIpoAsForce()\n"
 "\tReturns whether to interpret the ipo as a force rather than a displacement.\n";
-PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self) {
+PyObject* KX_IpoActuator::PyGetIpoAsForce() {
 	ShowDeprecationWarning("getIpoAsForce()", "the useIpoAsForce property");
 	return BoolToPyArg(m_ipo_as_force);
 }
@@ -650,13 +641,11 @@ const char KX_IpoActuator::SetIpoAdd_doc[] =
 "setIpoAdd(add?)\n"
 "\t - add?    : add flag (KX_TRUE, KX_FALSE)\n"
 "\tSet whether to interpret the ipo as additive rather than absolute.\n";
-PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self, 
-									  PyObject* args, 
-									  PyObject* kwds) { 
+PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* args) { 
 	ShowDeprecationWarning("setIpoAdd()", "the useIpoAdd property");
 	int boolArg;
 	
-	if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+	if (!PyArg_ParseTuple(args, "i:setIpoAdd", &boolArg)) {
 		return NULL;
 	}
 
@@ -670,7 +659,7 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self,
 const char KX_IpoActuator::GetIpoAdd_doc[] = 
 "getIpoAsAdd()\n"
 "\tReturns whether to interpret the ipo as additive rather than absolute.\n";
-PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self) {
+PyObject* KX_IpoActuator::PyGetIpoAdd() {
 	ShowDeprecationWarning("getIpoAdd()", "the useIpoAdd property");
 	return BoolToPyArg(m_ipo_add);
 }
@@ -680,13 +669,11 @@ const char KX_IpoActuator::SetType_doc[] =
 "setType(mode)\n"
 "\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
 "\tSet the operation mode of the actuator.\n";
-PyObject* KX_IpoActuator::PySetType(PyObject* self, 
-									PyObject* args, 
-									PyObject* kwds) {
+PyObject* KX_IpoActuator::PySetType(PyObject* args) {
 	ShowDeprecationWarning("setType()", "the type property");
 	int typeArg;
 	
-	if (!PyArg_ParseTuple(args, "i", &typeArg)) {
+	if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) {
 		return NULL;
 	}
 	
@@ -701,7 +688,7 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self,
 const char KX_IpoActuator::GetType_doc[] = 
 "getType()\n"
 "\tReturns the operation mode of the actuator.\n";
-PyObject* KX_IpoActuator::PyGetType(PyObject* self) {
+PyObject* KX_IpoActuator::PyGetType() {
 	ShowDeprecationWarning("getType()", "the type property");
 	return PyInt_FromLong(m_type);
 }
@@ -713,13 +700,11 @@ const char KX_IpoActuator::SetForceIpoActsLocal_doc[] =
 "\t               coordinates? (KX_TRUE, KX_FALSE)\n"
 "\tSet whether to apply the force in the object's local\n"
 "\tcoordinates rather than the world global coordinates.\n";
-PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self, 
-										         PyObject* args, 
-						       				     PyObject* kwds) { 
+PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* args) { 
 	ShowDeprecationWarning("setForceIpoActsLocal()", "the useIpoLocal property");
 	int boolArg;
 	
-	if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+	if (!PyArg_ParseTuple(args, "i:setForceIpoActsLocal", &boolArg)) {
 		return NULL;
 	}
 
@@ -732,7 +717,7 @@ const char KX_IpoActuator::GetForceIpoActsLocal_doc[] =
 "getForceIpoActsLocal()\n"
 "\tReturn whether to apply the force in the object's local\n"
 "\tcoordinates rather than the world global coordinates.\n";
-PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self) {
+PyObject* KX_IpoActuator::PyGetForceIpoActsLocal() {
 	ShowDeprecationWarning("getForceIpoActsLocal()", "the useIpoLocal property");
 	return BoolToPyArg(m_ipo_local);
 }
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h
index 7e85a28eb96144ce9e4b3c1cf8b4e5d2ff88a09d..9ea597def1eb1772abb9c6ff77db00a88887b39c 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.h
+++ b/source/gameengine/Ketsji/KX_IpoActuator.h
@@ -128,8 +128,6 @@ public:
 	virtual CValue* GetReplica() {
 		KX_IpoActuator* replica = new KX_IpoActuator(*this);//m_float,GetName());
 		replica->ProcessReplica();
-		// this will copy properties and so on...
-		CValue::AddDataToReplica(replica);
 		return replica;
 	};
 
@@ -142,23 +140,24 @@ public:
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 	
 	//KX_PYMETHOD_DOC
-	KX_PYMETHOD_DOC(KX_IpoActuator,Set);
-	KX_PYMETHOD_DOC(KX_IpoActuator,SetProperty);
+	KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,Set);
+	KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetProperty);
 /*  	KX_PYMETHOD_DOC(KX_IpoActuator,SetKey2Key); */
-	KX_PYMETHOD_DOC(KX_IpoActuator,SetStart);
+	KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetStart);
 	KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetStart);
-	KX_PYMETHOD_DOC(KX_IpoActuator,SetEnd);
+	KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetEnd);
 	KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetEnd);
-	KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAsForce);
+	KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetIpoAsForce);
 	KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetIpoAsForce);
-	KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAdd);
+	KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetIpoAdd);
 	KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetIpoAdd);
-	KX_PYMETHOD_DOC(KX_IpoActuator,SetType);
+	KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetType);
 	KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetType);
-	KX_PYMETHOD_DOC(KX_IpoActuator,SetForceIpoActsLocal);
+	KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetForceIpoActsLocal);
 	KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetForceIpoActsLocal);
 	
 };
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 68eb9f5537826dc353b3c99d712de198ef52d0b3..e773a9571f111f313fe794bcad622fb20656d927 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -97,6 +97,7 @@ const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
 };
 
 double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE;
+int	   KX_KetsjiEngine::m_maxLogicFrame = 5;
 double KX_KetsjiEngine::m_anim_framerate = 25.0;
 double KX_KetsjiEngine::m_suspendedtime = 0.0;
 double KX_KetsjiEngine::m_suspendeddelta = 0.0;
@@ -145,8 +146,6 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
 	m_stereo(false),
 	m_curreye(0),
 
-	m_usedome(false),
-
 	m_logger(NULL),
 	
 	// Set up timing info display variables
@@ -164,7 +163,9 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
 	m_overrideFrameColor(false),
 	m_overrideFrameColorR(0.0),
 	m_overrideFrameColorG(0.0),
-	m_overrideFrameColorB(0.0)
+	m_overrideFrameColorB(0.0),
+
+	m_usedome(false)
 {
 	// Initialize the time logger
 	m_logger = new KX_TimeCategoryLogger (25);
@@ -294,8 +295,16 @@ void KX_KetsjiEngine::RenderDome()
 	if (!BeginFrame())
 		return;
 
-	int n_renders=m_dome->GetNumberRenders();// usually 4 or 6
 	KX_SceneList::iterator sceneit;
+
+	// This is now done incrementally in KX_Scene::CalculateVisibleMeshes()
+	//for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
+	//{
+	//	// do this only once per scene
+	//	(*sceneit)->UpdateMeshTransformations();
+	//}
+
+	int n_renders=m_dome->GetNumberRenders();// usually 4 or 6
 	for (int i=0;i<n_renders;i++){
 		m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
 		for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
@@ -311,7 +320,6 @@ void KX_KetsjiEngine::RenderDome()
 			// shadow buffers
 			if (i == 0){
 				RenderShadowBuffers(scene);
-				scene->UpdateMeshTransformations();//I need to run it somewherelse, otherwise Im overrunning it
 			}
 			// Avoid drawing the scene with the active camera twice when it's viewport is enabled
 			if(cam && !cam->GetViewport())
@@ -348,7 +356,6 @@ void KX_KetsjiEngine::RenderDome()
 		m_dome->BindImages(i);
 	}	
 
-//	m_dome->Dome_PostRender(scene, cam, stereomode);
 	m_canvas->EndFrame();//XXX do we really need that?
 
 	m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
@@ -376,7 +383,8 @@ void KX_KetsjiEngine::RenderDome()
 
 	m_dome->Draw();
 
-	//run 2dfilters
+	// run the 2dfilters and motion blur once for all the scenes
+	PostRenderFrame();
 	EndFrame();
 }
 
@@ -394,6 +402,7 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo)
 	m_firstframe = true;
 	m_bInitialized = true;
 	m_ticrate = DEFAULT_LOGIC_TIC_RATE;
+	m_maxLogicFrame = 5;
 	
 	if (m_game2ipo)
 	{
@@ -506,7 +515,8 @@ void KX_KetsjiEngine::EndFrame()
 
 bool KX_KetsjiEngine::NextFrame()
 {
-
+	double timestep = 1.0/m_ticrate;
+	double framestep = timestep;
 //	static hidden::Clock sClock;
 
 m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true);
@@ -515,7 +525,7 @@ m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true);
 //sClock.reset();
 
 if (m_bFixedTime)
-	m_clockTime += 1./m_ticrate;
+	m_clockTime += timestep;
 else
 {
 
@@ -534,7 +544,7 @@ else
 
 
 	// Compute the number of logic frames to do each update (fixed tic bricks)
-	int frames =int(deltatime*m_ticrate);
+	int frames =int(deltatime*m_ticrate+1e-6);
 //	if (frames>1)
 //		printf("****************************************");
 //	printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames);
@@ -549,18 +559,24 @@ else
 	{
 	
 	//	printf("framedOut: %d\n",frames);
-		m_frameTime+=(frames-frameOut)*(1.0/m_ticrate);
+		m_frameTime+=(frames-frameOut)*timestep;
 		frames = frameOut;
 	}
 	
 
 	bool doRender = frames>0;
 
+	if (frames > m_maxLogicFrame)
+	{
+		framestep = (frames*timestep)/m_maxLogicFrame;
+		frames = m_maxLogicFrame;
+	}
+		
 	while (frames)
 	{
 	
 
-		m_frameTime += 1.0/m_ticrate;
+		m_frameTime += framestep;
 		
 		for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
 		// for each scene, call the proceed functions
@@ -587,12 +603,15 @@ else
 
 				
 				m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_NETWORK);
 				scene->GetNetworkScene()->proceed(m_frameTime);
 	
-				m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
-				scene->UpdateParents(m_frameTime);
+				//m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+				//SG_SetActiveStage(SG_STAGE_NETWORK_UPDATE);
+				//scene->UpdateParents(m_frameTime);
 				
 				m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_PHYSICS1);
 				// set Python hooks for each scene
 				PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
 				KX_SetActiveScene(scene);
@@ -601,38 +620,45 @@ else
 				
 				// Update scenegraph after physics step. This maps physics calculations
 				// into node positions.		
-				m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
-				scene->UpdateParents(m_frameTime);
+				//m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+				//SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE);
+				//scene->UpdateParents(m_frameTime);
 				
 				// Process sensors, and controllers
 				m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_CONTROLLER);
 				scene->LogicBeginFrame(m_frameTime);
 	
 				// Scenegraph needs to be updated again, because Logic Controllers 
 				// can affect the local matrices.
 				m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_CONTROLLER_UPDATE);
 				scene->UpdateParents(m_frameTime);
 	
 				// Process actuators
 	
 				// Do some cleanup work for this logic frame
 				m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_ACTUATOR);
 				scene->LogicUpdateFrame(m_frameTime, true);
 				
 				scene->LogicEndFrame();
 	
 				// Actuators can affect the scenegraph
 				m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE);
 				scene->UpdateParents(m_frameTime);
 				
 				m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_PHYSICS2);
 				scene->GetPhysicsEnvironment()->beginFrame();
 		
 				// Perform physics calculations on the scene. This can involve 
 				// many iterations of the physics solver.
-				scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,1.0/m_ticrate);//m_deltatimerealDeltaTime);
+				scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,timestep,framestep);//m_deltatimerealDeltaTime);
 
 				m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE);
 				scene->UpdateParents(m_frameTime);
 			
 			
@@ -696,15 +722,17 @@ else
 				KX_SetActiveScene(scene);
 				
 				m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_PHYSICS1);
 				scene->UpdateParents(m_clockTime);
 
 				// Perform physics calculations on the scene. This can involve 
 				// many iterations of the physics solver.
 				m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
-				scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,0.f);
+				scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep);
 				// Update scenegraph after physics step. This maps physics calculations
 				// into node positions.		
 				m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_PHYSICS2);
 				scene->UpdateParents(m_clockTime);
 				
 				// Do some cleanup work for this logic frame
@@ -713,6 +741,7 @@ else
 
 				// Actuators can affect the scenegraph
 				m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+				SG_SetActiveStage(SG_STAGE_ACTUATOR);
 				scene->UpdateParents(m_clockTime);
 				 
  				scene->setSuspendedTime(0.0);
@@ -748,6 +777,7 @@ void KX_KetsjiEngine::Render()
 	const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
 
 	m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+	SG_SetActiveStage(SG_STAGE_RENDER);
 
 	// hiding mouse cursor each frame
 	// (came back when going out of focus and then back in again)
@@ -798,6 +828,9 @@ void KX_KetsjiEngine::Render()
 		// pass the scene's worldsettings to the rasterizer
 		SetWorldSettings(scene->GetWorldInfo());
 
+		// this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes
+		//scene->UpdateMeshTransformations();
+
 		// shadow buffers
 		RenderShadowBuffers(scene);
 
@@ -975,7 +1008,7 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
 			wi->getAmbientColorBlue()
 		);
 
-		if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
+		if (m_drawingmode >= RAS_IRasterizer::KX_SOLID)
 		{	
 			if (wi->hasMist())
 			{
@@ -987,10 +1020,6 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
 					wi->getMistColorBlue()
 				);
 			}
-			else
-			{
-				m_rasterizer->DisableFog();
-			}
 		}
 	}
 }
@@ -1072,7 +1101,7 @@ void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect
 
 		area = userviewport;
 	}
-	else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) ||  m_overrideCamUseOrtho ) {
+	else if ( !m_overrideCam || (scene->GetName() != m_overrideSceneName) ||  m_overrideCamUseOrtho ) {
 		RAS_FramingManager::ComputeViewport(
 			scene->GetFramingType(),
 			m_canvas->GetDisplayArea(),
@@ -1092,16 +1121,13 @@ void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect
 
 void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
 {
-	CListValue *objectlist = scene->GetObjectList();
+	CListValue *lightlist = scene->GetLightList();
 	int i, drawmode;
 
 	m_rendertools->SetAuxilaryClientInfo(scene);
 
-	for(i=0; i<objectlist->GetCount(); i++) {
-		KX_GameObject *gameobj = (KX_GameObject*)objectlist->GetValue(i);
-
-		if(!gameobj->IsLight())
-			continue;
+	for(i=0; i<lightlist->GetCount(); i++) {
+		KX_GameObject *gameobj = (KX_GameObject*)lightlist->GetValue(i);
 
 		KX_LightObject *light = (KX_LightObject*)gameobj;
 
@@ -1123,7 +1149,6 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
 			light->BindShadowBuffer(m_rasterizer, cam, camtrans);
 
 			/* update scene */
-			scene->UpdateMeshTransformations();
 			scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer());
 
 			/* render */
@@ -1143,13 +1168,11 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
 {
 	bool override_camera;
 	RAS_Rect viewport, area;
-	float left, right, bottom, top, nearfrust, farfrust, focallength;
-	const float ortho = 100.0;
+	float nearfrust, farfrust, focallength;
 //	KX_Camera* cam = scene->GetActiveCamera();
 	
 	if (!cam)
 		return;
-
 	GetSceneViewport(scene, cam, area, viewport);
 
 	// store the computed viewport in the scene
@@ -1167,19 +1190,24 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
 	override_camera = override_camera && (cam->GetName() == "__default__cam__");
 
 	if (override_camera && m_overrideCamUseOrtho) {
-		MT_CmMatrix4x4 projmat = m_overrideCamProjMat;
-		m_rasterizer->SetProjectionMatrix(projmat);
+		m_rasterizer->SetProjectionMatrix(m_overrideCamProjMat);
+		if (!cam->hasValidProjectionMatrix()) {
+			// needed to get frustrum planes for culling
+			MT_Matrix4x4 projmat;
+			projmat.setValue(m_overrideCamProjMat.getPointer());
+			cam->SetProjectionMatrix(projmat);
+		}
 	} else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() )
 	{
 		m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix());
 	} else
 	{
 		RAS_FrameFrustum frustum;
-		float lens = cam->GetLens();
 		bool orthographic = !cam->GetCameraData()->m_perspective;
 		nearfrust = cam->GetCameraNear();
 		farfrust = cam->GetCameraFar();
 		focallength = cam->GetFocalLength();
+		MT_Matrix4x4 projmat;
 
 		if(override_camera) {
 			nearfrust = m_overrideCamNear;
@@ -1187,55 +1215,71 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
 		}
 
 		if (orthographic) {
-			lens *= ortho;
-			nearfrust = (nearfrust + 1.0)*ortho;
-			farfrust *= ortho;
-		}
-		
-		RAS_FramingManager::ComputeFrustum(
-			scene->GetFramingType(),
-			area,
-			viewport,
-			lens,
-			nearfrust,
-			farfrust,
-			frustum
-		);
 
-		left = frustum.x1 * m_cameraZoom;
-		right = frustum.x2 * m_cameraZoom;
-		bottom = frustum.y1 * m_cameraZoom;
-		top = frustum.y2 * m_cameraZoom;
-		nearfrust = frustum.camnear;
-		farfrust = frustum.camfar;
+			RAS_FramingManager::ComputeOrtho(
+				scene->GetFramingType(),
+				area,
+				viewport,
+				cam->GetScale(),
+				nearfrust,
+				farfrust,
+				frustum
+			);
+			if (!cam->GetViewport()) {
+				frustum.x1 *= m_cameraZoom;
+				frustum.x2 *= m_cameraZoom;
+				frustum.y1 *= m_cameraZoom;
+				frustum.y2 *= m_cameraZoom;
+			}
+			projmat = m_rasterizer->GetOrthoMatrix(
+				frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar);
 
-		MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(
-			left, right, bottom, top, nearfrust, farfrust, focallength);
+		} else {
+			RAS_FramingManager::ComputeFrustum(
+				scene->GetFramingType(),
+				area,
+				viewport,
+				cam->GetLens(),
+				nearfrust,
+				farfrust,
+				frustum
+			);
 
+			if (!cam->GetViewport()) {
+				frustum.x1 *= m_cameraZoom;
+				frustum.x2 *= m_cameraZoom;
+				frustum.y1 *= m_cameraZoom;
+				frustum.y2 *= m_cameraZoom;
+			}
+			projmat = m_rasterizer->GetFrustumMatrix(
+				frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar, focallength);
+		}
 		cam->SetProjectionMatrix(projmat);
 		
 		// Otherwise the projection matrix for each eye will be the same...
-		if (m_rasterizer->Stereo())
+		if (!orthographic && m_rasterizer->Stereo())
 			cam->InvalidateProjectionMatrix();
 	}
 
 	MT_Transform camtrans(cam->GetWorldToCamera());
-	if (!cam->GetCameraData()->m_perspective)
-		camtrans.getOrigin()[2] *= ortho;
 	MT_Matrix4x4 viewmat(camtrans);
 	
-	m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(),
-		cam->GetCameraLocation(), cam->GetCameraOrientation());
+	m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective);
 	cam->SetModelviewMatrix(viewmat);
 
-	scene->UpdateMeshTransformations();
-
 	// The following actually reschedules all vertices to be
 	// redrawn. There is a cache between the actual rescheduling
 	// and this call though. Visibility is imparted when this call
 	// runs through the individual objects.
+
+	m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
+	SG_SetActiveStage(SG_STAGE_CULLING);
+
 	scene->CalculateVisibleMeshes(m_rasterizer,cam);
 
+	m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+	SG_SetActiveStage(SG_STAGE_RENDER);
+
 	scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
 	
 	if (scene->GetPhysicsEnvironment())
@@ -1243,15 +1287,14 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
 	
 	m_rasterizer->FlushDebugLines();
 
+	//it's running once for every scene (i.e. overlay scenes have  it running twice). That's not the ideal.
 	PostRenderFrame();
 }
 
 void KX_KetsjiEngine::PostRenderFrame()
 {
-	m_rendertools->PushMatrix();
 	m_rendertools->Render2DFilters(m_canvas);
 	m_rendertools->MotionBlur(m_rasterizer);
-	m_rendertools->PopMatrix();
 }
 
 void KX_KetsjiEngine::StopEngine()
@@ -1292,15 +1335,17 @@ void KX_KetsjiEngine::AddScene(KX_Scene* scene)
 void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
 {
 	bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName));
-	
-		// if there is no activecamera, or the camera is being
-		// overridden we need to construct a temporarily camera
+
+	SG_SetActiveStage(SG_STAGE_SCENE);
+
+	// if there is no activecamera, or the camera is being
+	// overridden we need to construct a temporarily camera
 	if (!scene->GetActiveCamera() || override_camera)
 	{
 		KX_Camera* activecam = NULL;
 
 		RAS_CameraData camdata = RAS_CameraData();
-		activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata, false);
+		activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata);
 		activecam->SetName("__default__cam__");
 	
 			// set transformation
@@ -1312,11 +1357,11 @@ void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
 			
 			activecam->NodeSetLocalPosition(camtrans.getOrigin());
 			activecam->NodeSetLocalOrientation(camtrans.getBasis());
-			activecam->NodeUpdateGS(0,true);
+			activecam->NodeUpdateGS(0);
 		} else {
 			activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0));
 			activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0));
-			activecam->NodeUpdateGS(0,true);
+			activecam->NodeUpdateGS(0);
 		}
 
 		scene->AddCamera(activecam);
@@ -1371,7 +1416,7 @@ void KX_KetsjiEngine::RenderDebugProperties()
 										m_canvas->GetWidth(), 
 										m_canvas->GetHeight());
 			double time = m_logger->GetAverage((KX_TimeCategory)j);
-			debugtxt.Format("%2.2f %%", time/tottime * 100.f);
+			debugtxt.Format("%.3fms (%2.2f %%)", time*1000.f, time/tottime * 100.f);
 			m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
 										debugtxt.Ptr(),
 										xcoord + 60 ,ycoord,
@@ -1689,6 +1734,16 @@ void KX_KetsjiEngine::SetTicRate(double ticrate)
 	m_ticrate = ticrate;
 }
 
+int KX_KetsjiEngine::GetMaxLogicFrame()
+{
+	return m_maxLogicFrame;
+}
+
+void KX_KetsjiEngine::SetMaxLogicFrame(int frame)
+{
+	m_maxLogicFrame = frame;
+}
+
 double KX_KetsjiEngine::GetAnimFrameRate()
 {
 	return m_anim_framerate;
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index a8ccd6100d7c560b69494728ccb36879f41fd970..528465b6c2ccac43e5f73d63237f542592d4fda4 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -103,6 +103,7 @@ private:
 	double				m_previousClockTime;//previous clock time
 	double				m_remainingTime;
 
+	static int				m_maxLogicFrame;	/* maximum number of consecutive logic frame */
 	static double			m_ticrate;
 	static double			m_anim_framerate; /* for animation playback only - ipo and action */
 
@@ -283,6 +284,14 @@ public:
 	 * Sets the number of logic updates per second.
 	 */
 	static void SetTicRate(double ticrate);
+	/**
+	 * Gets the maximum number of logic frame before render frame
+	 */
+	static int GetMaxLogicFrame();
+	/**
+	 * Sets the maximum number of logic frame before render frame
+	 */
+	static void SetMaxLogicFrame(int frame);
 
 	/**
 	 * Gets the framerate for playing animations. (actions and ipos)
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 6f9d8b0211b4afa143a14e019070913bca6679b8..777a7f326298e8a375aa38fa5d845bc65fcc8475 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -82,10 +82,7 @@ CValue*		KX_LightObject::GetReplica()
 
 	KX_LightObject* replica = new KX_LightObject(*this);
 
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-
-	ProcessReplica(replica);
+	replica->ProcessReplica();
 	
 	replica->m_lightobj.m_worldmatrix = replica->GetOpenGLMatrixPtr();
 	m_rendertools->AddLight(&replica->m_lightobj);
@@ -105,8 +102,11 @@ void KX_LightObject::Update()
 {
 	GPULamp *lamp;
 
-	if((lamp = GetGPULamp())) {
+	if((lamp = GetGPULamp()) != NULL && GetSGNode()) {
 		float obmat[4][4];
+		// lights don't get their openGL matrix updated, do it now
+		if (GetSGNode()->IsDirty())
+			GetOpenGLMatrix();
 		double *dobmat = GetOpenGLMatrixPtr()->getPointer();
 
 		for(int i=0; i<4; i++)
@@ -159,12 +159,11 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T
 	
 	cam->NodeSetLocalPosition(camtrans.getOrigin());
 	cam->NodeSetLocalOrientation(camtrans.getBasis());
-	cam->NodeUpdateGS(0,true);
+	cam->NodeUpdateGS(0);
 
 	/* setup rasterizer transformations */
 	ras->SetProjectionMatrix(projectionmat);
-	ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(),
-		cam->GetCameraLocation(), cam->GetCameraOrientation());
+	ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective);
 }
 
 void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras)
@@ -173,156 +172,35 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras)
 	GPU_lamp_shadow_buffer_unbind(lamp);
 }
 
-PyObject* KX_LightObject::py_getattro(PyObject *attr)
-{
-	char *attr_str= PyString_AsString(attr);
-	
-	if (!strcmp(attr_str, "layer"))
-		return PyInt_FromLong(m_lightobj.m_layer);
-	
-	if (!strcmp(attr_str, "energy"))
-		return PyFloat_FromDouble(m_lightobj.m_energy);
-	
-	if (!strcmp(attr_str, "distance"))
-		return PyFloat_FromDouble(m_lightobj.m_distance);
-	
-	if (!strcmp(attr_str, "colour") || !strcmp(attr_str, "color"))
-		return Py_BuildValue("[fff]", m_lightobj.m_red, m_lightobj.m_green, m_lightobj.m_blue);
-		
-	if (!strcmp(attr_str, "lin_attenuation"))
-		return PyFloat_FromDouble(m_lightobj.m_att1);
-	
-	if (!strcmp(attr_str, "quad_attenuation"))
-		return PyFloat_FromDouble(m_lightobj.m_att2);
-	
-	if (!strcmp(attr_str, "spotsize"))
-		return PyFloat_FromDouble(m_lightobj.m_spotsize);
-	
-	if (!strcmp(attr_str, "spotblend"))
-		return PyFloat_FromDouble(m_lightobj.m_spotblend);
-		
-	if (!strcmp(attr_str, "SPOT"))
-		return PyInt_FromLong(RAS_LightObject::LIGHT_SPOT);
-		
-	if (!strcmp(attr_str, "SUN"))
-		return PyInt_FromLong(RAS_LightObject::LIGHT_SUN);
-	
-	if (!strcmp(attr_str, "NORMAL"))
-		return PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL);
-	
-	if (!strcmp(attr_str, "type"))
-		return PyInt_FromLong(m_lightobj.m_type);
-		
-	py_getattro_up(KX_GameObject);
-}
+/* ------------------------------------------------------------------------- */
+/* Python Integration Hooks					                                 */
+/* ------------------------------------------------------------------------- */
 
-int       KX_LightObject::py_setattro(PyObject *attr, PyObject *pyvalue)
-{
-	char *attr_str= PyString_AsString(attr);
-	if (PyInt_Check(pyvalue))
-	{
-		int value = PyInt_AsLong(pyvalue);
-		if (!strcmp(attr_str, "layer"))
-		{
-			m_lightobj.m_layer = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "type"))
-		{
-			if (value >= RAS_LightObject::LIGHT_SPOT && value <= RAS_LightObject::LIGHT_NORMAL)
-				m_lightobj.m_type = (RAS_LightObject::LightType) value;
-			return 0;
-		}
-	}
-	
-	if (PyFloat_Check(pyvalue))
-	{
-		float value = PyFloat_AsDouble(pyvalue);
-		if (!strcmp(attr_str, "energy"))
-		{
-			m_lightobj.m_energy = value;
-			return 0;
-		}
-	
-		if (!strcmp(attr_str, "distance"))
-		{
-			m_lightobj.m_distance = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "lin_attenuation"))
-		{
-			m_lightobj.m_att1 = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "quad_attenuation"))
-		{
-			m_lightobj.m_att2 = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "spotsize"))
-		{
-			m_lightobj.m_spotsize = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "spotblend"))
-		{
-			m_lightobj.m_spotblend = value;
-			return 0;
-		}
-	}
-
-	if (PySequence_Check(pyvalue))
-	{
-		if (!strcmp(attr_str, "colour") || !strcmp(attr_str, "color"))
-		{
-			MT_Vector3 color;
-			if (PyVecTo(pyvalue, color))
-			{
-				m_lightobj.m_red = color[0];
-				m_lightobj.m_green = color[1];
-				m_lightobj.m_blue = color[2];
-				return 0;
-			}
-			return 1;
-		}
-	}
-	
-	if (!strcmp(attr_str, "SPOT") || !strcmp(attr_str, "SUN") || !strcmp(attr_str, "NORMAL"))
-	{
-		PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr_str);
-		return 1;
-	}
-	
-	return KX_GameObject::py_setattro(attr, pyvalue);
+PyObject* KX_LightObject::py_getattro_dict() {
+	py_getattro_dict_up(KX_GameObject);
 }
 
-PyMethodDef KX_LightObject::Methods[] = {
-	{NULL,NULL} //Sentinel
-};
-
-PyAttributeDef KX_LightObject::Attributes[] = {
-	{ NULL }	//Sentinel
-};
-
 
 PyTypeObject KX_LightObject::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_LightObject",
-		sizeof(KX_LightObject),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
 		0,
 		py_base_repr,
-		0,0,0,0,0,0,
+		0,0,
+		&KX_GameObject::Mapping,
+		0,0,0,
 		py_base_getattro,
 		py_base_setattro,
 		0,0,0,0,0,0,0,0,0,
@@ -336,3 +214,98 @@ PyParentObject KX_LightObject::Parents[] = {
 		&CValue::Type,
 		NULL
 };
+
+PyMethodDef KX_LightObject::Methods[] = {
+	{NULL,NULL} //Sentinel
+};
+
+PyAttributeDef KX_LightObject::Attributes[] = {
+	KX_PYATTRIBUTE_INT_RW("layer", 1, 20, true, KX_LightObject, m_lightobj.m_layer),
+	KX_PYATTRIBUTE_FLOAT_RW("energy", 0, 10, KX_LightObject, m_lightobj.m_energy),
+	KX_PYATTRIBUTE_FLOAT_RW("distance", 0.01, 5000, KX_LightObject, m_lightobj.m_distance),
+	KX_PYATTRIBUTE_RW_FUNCTION("color", KX_LightObject, pyattr_get_color, pyattr_set_color),
+	KX_PYATTRIBUTE_RW_FUNCTION("colour", KX_LightObject, pyattr_get_color, pyattr_set_color),
+	KX_PYATTRIBUTE_FLOAT_RW("lin_attenuation", 0, 1, KX_LightObject, m_lightobj.m_att1),
+	KX_PYATTRIBUTE_FLOAT_RW("quat_attenuation", 0, 1, KX_LightObject, m_lightobj.m_att2),
+	KX_PYATTRIBUTE_FLOAT_RW("spotsize", 1, 180, KX_LightObject, m_lightobj.m_spotsize),
+	KX_PYATTRIBUTE_FLOAT_RW("spotblend", 0, 1, KX_LightObject, m_lightobj.m_spotblend),
+	KX_PYATTRIBUTE_RO_FUNCTION("SPOT", KX_LightObject, pyattr_get_typeconst),
+	KX_PYATTRIBUTE_RO_FUNCTION("SUN", KX_LightObject, pyattr_get_typeconst),
+	KX_PYATTRIBUTE_RO_FUNCTION("NORMAL", KX_LightObject, pyattr_get_typeconst),
+	KX_PYATTRIBUTE_RW_FUNCTION("type", KX_LightObject, pyattr_get_type, pyattr_set_type),
+	{ NULL }	//Sentinel
+};
+
+PyObject* KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
+	return Py_BuildValue("[fff]", self->m_lightobj.m_red, self->m_lightobj.m_green, self->m_lightobj.m_blue);
+}
+
+int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
+
+	MT_Vector3 color;
+	if (PyVecTo(value, color))
+	{
+		self->m_lightobj.m_red = color[0];
+		self->m_lightobj.m_green = color[1];
+		self->m_lightobj.m_blue = color[2];
+		return 0;
+	}
+	return 1;
+}
+
+PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	PyObject* retvalue;
+
+	const char* type = attrdef->m_name;
+
+	if(strcmp(type, "SPOT")) {
+		retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SPOT);
+	} else if (strcmp(type, "SUN")) {
+		retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SUN);
+	} else if (strcmp(type, "NORMAL")) {
+		retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL);
+	}
+
+	return retvalue;
+}
+
+PyObject* KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
+	return PyInt_FromLong(self->m_lightobj.m_type);
+}
+
+int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value)
+{
+	KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
+	int val = PyInt_AsLong(value);
+	switch(val) {
+		case 0:
+			self->m_lightobj.m_type = self->m_lightobj.LIGHT_SPOT;
+			break;
+		case 1:
+			self->m_lightobj.m_type = self->m_lightobj.LIGHT_SUN;
+			break;
+		default:
+			self->m_lightobj.m_type = self->m_lightobj.LIGHT_NORMAL;
+			break;
+	}
+
+	return PY_SET_ATTR_SUCCESS;
+}
+
+
+PyObject* KX_LightObject::py_getattro(PyObject *attr)
+{
+	py_getattro_up(KX_GameObject);
+}
+
+int KX_LightObject::py_setattro(PyObject *attr, PyObject *value)
+{
+	py_setattro_up(KX_GameObject);
+}
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 4559954c8d7152caaba7dbfceff7e070fbf6ac6b..35f25515e3b228c81bd2fc378a2a41b974e99bb7 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -63,8 +63,16 @@ public:
 	void Update();
 	
 	virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */
+	virtual PyObject* py_getattro_dict();
 	virtual int       py_setattro(PyObject *attr, PyObject *pyvalue);
 
+	/* attributes */
+	static PyObject*	pyattr_get_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value);
+	static PyObject*	pyattr_get_typeconst(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value);
+
 	virtual bool IsLight(void) { return true; }
 };
 
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
index f464cb798e81220aa807ea8721e98b6fdd5b5140..0d1bc289a5c254e0fc794eadb3a5176282593fd6 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.cpp
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -46,12 +46,17 @@
 #include "PyObjectPlus.h" 
 
 PyTypeObject KX_MeshProxy::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_MeshProxy",
-	sizeof(KX_MeshProxy),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -66,15 +71,17 @@ PyTypeObject KX_MeshProxy::Type = {
 
 PyParentObject KX_MeshProxy::Parents[] = {
 	&KX_MeshProxy::Type,
-	&SCA_IObject::Type,
 	&CValue::Type,
 	&PyObjectPlus::Type,
 	NULL
 };
 
 PyMethodDef KX_MeshProxy::Methods[] = {
+// Deprecated ----->
 {"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS},
 {"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS},
+// <-----
+
 {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS},
 {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS},
 {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
@@ -87,6 +94,10 @@ KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh),
 };
 
 PyAttributeDef KX_MeshProxy::Attributes[] = {
+	KX_PYATTRIBUTE_RO_FUNCTION("materials",		KX_MeshProxy, pyattr_get_materials),
+	KX_PYATTRIBUTE_RO_FUNCTION("numPolygons",	KX_MeshProxy, pyattr_get_numPolygons),
+	KX_PYATTRIBUTE_RO_FUNCTION("numMaterials",	KX_MeshProxy, pyattr_get_numMaterials),
+
 	{ NULL }	//Sentinel
 };
 
@@ -96,37 +107,23 @@ void KX_MeshProxy::SetMeshModified(bool v)
 }
 
 
-PyObject*
-KX_MeshProxy::py_getattro(PyObject *attr)
+PyObject* KX_MeshProxy::py_getattro(PyObject *attr)
 {
-	char *attr_str= PyString_AsString(attr);
-	
-	if (!strcmp(attr_str, "materials"))
-	{
-		PyObject *materials = PyList_New(0);
-		list<RAS_MeshMaterial>::iterator mit = m_meshobj->GetFirstMaterial();
-		for(; mit != m_meshobj->GetLastMaterial(); ++mit)
-		{
-			RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial();
-
-			if(polymat->GetFlag() & RAS_BLENDERMAT)
-			{
-				KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat);
-				PyList_Append(materials, mat);
-			}else
-			{
-				PyList_Append(materials, static_cast<KX_PolygonMaterial*>(polymat));
-			}
-		}
-		return materials;
-	}
- 	py_getattro_up(SCA_IObject);
+ 	py_getattro_up(CValue);
 }
 
+PyObject* KX_MeshProxy::py_getattro_dict() {
+	py_getattro_dict_up(CValue);
+}
+
+int KX_MeshProxy::py_setattro(PyObject *attr, PyObject* value)
+{
+	py_setattro_up(CValue);
+}
 
 
 KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh)
-	: SCA_IObject(&Type), m_meshobj(mesh)
+	: CValue(&Type), m_meshobj(mesh)
 {
 }
 
@@ -141,37 +138,34 @@ CValue*		KX_MeshProxy::Calc(VALUE_OPERATOR op, CValue *val) { return NULL;}
 CValue*		KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;}	
 
 const STR_String &	KX_MeshProxy::GetText() {return m_meshobj->GetName();};
-float		KX_MeshProxy::GetNumber() { return -1;}
-STR_String	KX_MeshProxy::GetName() { return m_meshobj->GetName();}
-void		KX_MeshProxy::SetName(STR_String name) { };
+double		KX_MeshProxy::GetNumber() { return -1;}
+STR_String&	KX_MeshProxy::GetName() { return m_meshobj->GetName();}
+void		KX_MeshProxy::SetName(const char *name) { };
 CValue*		KX_MeshProxy::GetReplica() { return NULL;}
-void		KX_MeshProxy::ReplicaSetName(STR_String name) {};
 
 
 // stuff for python integration
 	
-PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* self, 
-			       PyObject* args, 
-			       PyObject* kwds)
+PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* args, PyObject* kwds)
 {
 	int num = m_meshobj->NumMaterials();
+	ShowDeprecationWarning("getNumMaterials()", "the numMaterials property");
 	return PyInt_FromLong(num);
 }
 
-PyObject* KX_MeshProxy::PyGetNumPolygons(PyObject* self)
+PyObject* KX_MeshProxy::PyGetNumPolygons()
 {
 	int num = m_meshobj->NumPolygons();
+	ShowDeprecationWarning("getNumPolygons()", "the numPolygons property");
 	return PyInt_FromLong(num);
 }
 
-PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self, 
-			       PyObject* args, 
-			       PyObject* kwds)
+PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds)
 {
     int matid= 1;
 	STR_String matname;
 
-	if (PyArg_ParseTuple(args,"i",&matid))
+	if (PyArg_ParseTuple(args,"i:getMaterialName",&matid))
 	{
 		matname = m_meshobj->GetMaterialName(matid);
 	}
@@ -184,14 +178,12 @@ PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self,
 }
 	
 
-PyObject* KX_MeshProxy::PyGetTextureName(PyObject* self, 
-			       PyObject* args, 
-			       PyObject* kwds)
+PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds)
 {
     int matid= 1;
 	STR_String matname;
 
-	if (PyArg_ParseTuple(args,"i",&matid))
+	if (PyArg_ParseTuple(args,"i:getTextureName",&matid))
 	{
 		matname = m_meshobj->GetTextureName(matid);
 	}
@@ -203,73 +195,70 @@ PyObject* KX_MeshProxy::PyGetTextureName(PyObject* self,
 		
 }
 
-PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* self, 
-			       PyObject* args, 
-			       PyObject* kwds)
+PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds)
 {
-    int matid= -1;
-	int length = -1;
+    int matid= 0;
+	int length = 0;
 
 	
-	if (PyArg_ParseTuple(args,"i",&matid))
+	if (!PyArg_ParseTuple(args,"i:getVertexArrayLength",&matid))
+		return NULL;
+	
+
+	RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); /* can be NULL*/
+	
+	if (mmat)
 	{
-		RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid);
 		RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial();
-
 		if (mat)
 			length = m_meshobj->NumVertices(mat);
 	}
-	else {
-		return NULL;
-	}
-
+	
 	return PyInt_FromLong(length);
-		
 }
 
 
-PyObject* KX_MeshProxy::PyGetVertex(PyObject* self, 
-			       PyObject* args, 
-			       PyObject* kwds)
+PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds)
 {
-    int vertexindex= 1;
-	int matindex= 1;
+    int vertexindex;
+	int matindex;
 	PyObject* vertexob = NULL;
 
-	if (PyArg_ParseTuple(args,"ii",&matindex,&vertexindex))
-	{
-		RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex);
-		if (vertex)
-		{
-			vertexob = new KX_VertexProxy(this, vertex);
-		}
-	}
-	else {
+	if (!PyArg_ParseTuple(args,"ii:getVertex",&matindex,&vertexindex))
+		return NULL;
+	
+	RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex);
+	
+	if(vertex==NULL) {
+		PyErr_SetString(PyExc_ValueError, "mesh.getVertex(mat_idx, vert_idx): KX_MeshProxy, could not get a vertex at the given indicies");
 		return NULL;
 	}
-
-	return vertexob;
-		
+	
+	return (new KX_VertexProxy(this, vertex))->NewProxy(true);
 }
 
-PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self,
-			       PyObject* args, 
-			       PyObject* kwds)
+PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds)
 {
     int polyindex= 1;
 	PyObject* polyob = NULL;
 
-	if (!PyArg_ParseTuple(args,"i",&polyindex))
+	if (!PyArg_ParseTuple(args,"i:getPolygon",&polyindex))
 		return NULL;
+	
+	if (polyindex<0 || polyindex >= m_meshobj->NumPolygons())
+	{
+		PyErr_SetString(PyExc_AttributeError, "mesh.getPolygon(int): KX_MeshProxy, invalid polygon index");
+		return NULL;
+	}
+		
 
 	RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex);
 	if (polygon)
 	{
-		polyob = new KX_PolyProxy(m_meshobj, polygon);
+		polyob = (new KX_PolyProxy(m_meshobj, polygon))->NewProxy(true);
 	}
-	else
-	{
-		PyErr_SetString(PyExc_AttributeError, "Invalid polygon index");
+	else {
+		PyErr_SetString(PyExc_AttributeError, "mesh.getPolygon(int): KX_MeshProxy, polygon is NULL, unknown reason");
 	}
 	return polyob;
 }
@@ -277,6 +266,104 @@ PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self,
 KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh,
 "Reinstance the physics mesh.")
 {
+#if 0
 	//this needs to be reviewed, it is dependend on Sumo/Solid. Who is using this ?
-	Py_RETURN_NONE;//(KX_ReInstanceShapeFromMesh(m_meshobj)) ? Py_RETURN_TRUE : Py_RETURN_FALSE;
+	if(KX_ReInstanceShapeFromMesh(m_meshobj))
+		Py_RETURN_TRUE;
+#endif
+	Py_RETURN_FALSE;
+}
+
+PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_MeshProxy* self= static_cast<KX_MeshProxy*>(self_v);
+	
+	int tot= self->m_meshobj->NumMaterials();
+	int i;
+	
+	PyObject *materials = PyList_New( tot );
+	
+	list<RAS_MeshMaterial>::iterator mit= self->m_meshobj->GetFirstMaterial();
+	
+	
+	for(i=0; i<tot; mit++, i++) {
+		RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial(); 	 
+		
+		/* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
+		if(polymat->GetFlag() & RAS_BLENDERMAT) 	 
+		{ 	 
+			KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat); 	 
+			PyList_SET_ITEM(materials, i, mat->GetProxy());
+		}
+		else { 	
+			KX_PolygonMaterial *mat = static_cast<KX_PolygonMaterial*>(polymat);
+			PyList_SET_ITEM(materials, i, mat->GetProxy());
+		}
+	}	
+	return materials;
+}
+
+PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) {
+	KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv);
+	return PyInt_FromLong(self->m_meshobj->NumMaterials());
+}
+
+PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) {
+	KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv);
+	return PyInt_FromLong(self->m_meshobj->NumPolygons());
+}
+
+/* a close copy of ConvertPythonToGameObject but for meshes */
+bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix)
+{
+	if (value==NULL) {
+		PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
+		*object = NULL;
+		return false;
+	}
+		
+	if (value==Py_None) {
+		*object = NULL;
+		
+		if (py_none_ok) {
+			return true;
+		} else {
+			PyErr_Format(PyExc_TypeError, "%s, expected KX_MeshProxy or a KX_MeshProxy name, None is invalid", error_prefix);
+			return false;
+		}
+	}
+	
+	if (PyString_Check(value)) {
+		*object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( PyString_AsString(value) ));
+		
+		if (*object) {
+			return true;
+		} else {
+			PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyString_AsString(value));
+			return false;
+		}
+	}
+	
+	if (PyObject_TypeCheck(value, &KX_MeshProxy::Type)) {
+		KX_MeshProxy *kx_mesh = static_cast<KX_MeshProxy*>BGE_PROXY_REF(value);
+		
+		/* sets the error */
+		if (*object==NULL) {
+			PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
+			return false;
+		}		
+		
+		*object = kx_mesh->GetMesh();
+		return true;
+	}
+	
+	*object = NULL;
+	
+	if (py_none_ok) {
+		PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy, a string or None", error_prefix);
+	} else {
+		PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy or a string", error_prefix);
+	}
+	
+	return false;
 }
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h
index 0b9738153ff2d8b46efcef7a996a28885a88624f..bfdd4be41187899f6ceb234a1aca89714e6ed445 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.h
+++ b/source/gameengine/Ketsji/KX_MeshProxy.h
@@ -31,7 +31,10 @@
 
 #include "SCA_IObject.h"
 
-class KX_MeshProxy	: public SCA_IObject
+/* utility conversion function */
+bool ConvertPythonToMesh(PyObject * value, class RAS_MeshObject **object, bool py_none_ok, const char *error_prefix);
+
+class KX_MeshProxy	: public CValue
 {
 	Py_Header;
 
@@ -46,25 +49,31 @@ public:
 	virtual CValue*		Calc(VALUE_OPERATOR op, CValue *val) ;
 	virtual CValue*		CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
 	virtual const STR_String &	GetText();
-	virtual float		GetNumber();
+	virtual double		GetNumber();
 	virtual RAS_MeshObject* GetMesh() { return m_meshobj; }
-	virtual STR_String	GetName();
-	virtual void		SetName(STR_String name);								// Set the name of the value
-	virtual void		ReplicaSetName(STR_String name);
+	virtual STR_String&	GetName();
+	virtual void		SetName(const char *name);								// Set the name of the value
 	virtual CValue*		GetReplica();
 
 // stuff for python integration
 	virtual PyObject*  py_getattro(PyObject *attr);
-	KX_PYMETHOD(KX_MeshProxy,GetNumMaterials);
+	virtual PyObject* py_getattro_dict();
+	virtual int py_setattro(PyObject *attr, PyObject* value);
+
+	KX_PYMETHOD(KX_MeshProxy,GetNumMaterials);	// Deprecated
 	KX_PYMETHOD(KX_MeshProxy,GetMaterialName);
 	KX_PYMETHOD(KX_MeshProxy,GetTextureName);
-	KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons);
+	KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons); // Deprecated
 	
 	// both take materialid (int)
 	KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength);
 	KX_PYMETHOD(KX_MeshProxy,GetVertex);
 	KX_PYMETHOD(KX_MeshProxy,GetPolygon);
 	KX_PYMETHOD_DOC(KX_MeshProxy, reinstancePhysicsMesh);
+	
+	static PyObject*	pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject * pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
+	static PyObject * pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
 };
 
 #endif //__KX_MESHPROXY
diff --git a/source/gameengine/Ketsji/KX_MotionState.cpp b/source/gameengine/Ketsji/KX_MotionState.cpp
index 15f100af915745f2122a3c3650daed5fa6314746..b4d58dccfdf1418a950b9a734be9057642883921 100644
--- a/source/gameengine/Ketsji/KX_MotionState.cpp
+++ b/source/gameengine/Ketsji/KX_MotionState.cpp
@@ -44,7 +44,7 @@ KX_MotionState::~KX_MotionState()
 
 void	KX_MotionState::getWorldPosition(float& posX,float& posY,float& posZ)
 {
-	MT_Point3 pos = m_node->GetWorldPosition();
+	const MT_Point3& pos = m_node->GetWorldPosition();
 	posX = pos[0];
 	posY = pos[1];
 	posZ = pos[2];
@@ -52,7 +52,7 @@ void	KX_MotionState::getWorldPosition(float& posX,float& posY,float& posZ)
 
 void	KX_MotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)
 {
-	MT_Vector3 scale = m_node->GetWorldScaling();
+	const MT_Vector3& scale = m_node->GetWorldScaling();
 	scaleX = scale[0];
 	scaleY = scale[1];
 	scaleZ = scale[2];
@@ -67,10 +67,16 @@ void	KX_MotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float&
 	quatReal = orn[3];
 }
 	
+void	KX_MotionState::getWorldOrientation(float* ori)
+{
+	const MT_Matrix3x3& mat = m_node->GetWorldOrientation();
+	mat.getValue(ori);
+}
+	
 void	KX_MotionState::setWorldPosition(float posX,float posY,float posZ)
 {
 	m_node->SetLocalPosition(MT_Point3(posX,posY,posZ));
-	m_node->SetWorldPosition(MT_Point3(posX,posY,posZ));
+	//m_node->SetWorldPosition(MT_Point3(posX,posY,posZ));
 }
 
 void	KX_MotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)
@@ -82,13 +88,15 @@ void	KX_MotionState::setWorldOrientation(float quatIma0,float quatIma1,float qua
 	orn[3] = quatReal;
 
 	m_node->SetLocalOrientation(orn);
-	m_node->SetWorldOrientation(orn);
+	//m_node->SetWorldOrientation(orn);
 
 }
 
 void	KX_MotionState::calculateWorldTransformations()
 {
-	m_node->ComputeWorldTransforms(NULL);
+	//Not needed, will be done in KX_Scene::UpdateParents() after the physics simulation
+	//bool parentUpdated = false;
+	//m_node->ComputeWorldTransforms(NULL, parentUpdated);
 }
 
  
diff --git a/source/gameengine/Ketsji/KX_MotionState.h b/source/gameengine/Ketsji/KX_MotionState.h
index c83af66481738b421f7103b71308432bc0c1c046..7ba3ca2f85c222c85a09c0ff880975cc57abc7a7 100644
--- a/source/gameengine/Ketsji/KX_MotionState.h
+++ b/source/gameengine/Ketsji/KX_MotionState.h
@@ -44,6 +44,7 @@ public:
 	virtual void	getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal);
 	virtual void	setWorldPosition(float posX,float posY,float posZ);
 	virtual	void	setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal);
+	virtual void	getWorldOrientation(float* ori);
 
 	virtual	void	calculateWorldTransformations();
 };
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index 72a0381e8dca052972328c379b451a35e8e80ab6..74b5c923db80c6813347b3a641c1a8b26bbc3108 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -61,14 +61,12 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
 										 int starty,
 										 short int mousemode,
 										 int focusmode,
-										 RAS_ICanvas* canvas,
 										 KX_Scene* kxscene,
 										 KX_KetsjiEngine *kxengine,
 										 SCA_IObject* gameobj, 
 										 PyTypeObject* T)
     : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T),
 	  m_focusmode(focusmode),
-	  m_gp_canvas(canvas),
 	  m_kxscene(kxscene),
 	  m_kxengine(kxengine)
 {
@@ -81,9 +79,14 @@ void KX_MouseFocusSensor::Init()
 	m_positive_event = false;
 	m_hitObject = 0;
 	m_reset = true;
+	
+	m_hitPosition.setValue(0,0,0);
+	m_prevTargetPoint.setValue(0,0,0);
+	m_prevSourcePoint.setValue(0,0,0);
+	m_hitNormal.setValue(0,0,1);
 }
 
-bool KX_MouseFocusSensor::Evaluate(CValue* event)
+bool KX_MouseFocusSensor::Evaluate()
 {
 	bool result = false;
 	bool obHasFocus = false;
@@ -116,7 +119,7 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event)
          * mode is never used, because the converter never makes this
          * sensor for a mouse-key event. It is here for
          * completeness. */
-		result = SCA_MouseSensor::Evaluate(event);
+		result = SCA_MouseSensor::Evaluate();
 		m_positive_event = (m_val!=0);
 	}
 
@@ -150,12 +153,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* r
 
 
 
-bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
+bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
 {
-	m_hitObject = 0;
-	m_hitPosition = MT_Vector3(0,0,0);
-	m_hitNormal =	MT_Vector3(1,0,0);
-
 	/* All screen handling in the gameengine is done by GL,
 	 * specifically the model/view and projection parts. The viewport
 	 * part is in the creator. 
@@ -187,6 +186,7 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
 	 *    = 1.0 - 2(y_blender - y_lb)/height
 	 *
 	 * */
+	 
 	
 	/* Because we don't want to worry about resize events, camera
 	 * changes and all that crap, we just determine this over and
@@ -195,15 +195,18 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
 	 * canvas, the test is irrelevant. The 1.0 makes sure the
 	 * calculations don't bomb. Maybe we should explicitly guard for
 	 * division by 0.0...*/
-
-	KX_Camera* cam = m_kxscene->GetActiveCamera();
-
-	/* get the scenes current viewport. we recompute it because there
-	 * may be multiple cameras and m_kxscene->GetSceneViewport() only
-	 * has the one that was last drawn */
-
+	
 	RAS_Rect area, viewport;
 	m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport);
+	
+	/* Check if the mouse is in the viewport */
+	if ((	m_x < viewport.m_x2 &&	// less then right
+			m_x > viewport.m_x1 &&	// more then then left
+			m_y < viewport.m_y2 &&	// below top
+			m_y > viewport.m_y1) == 0)	// above bottom
+	{
+		return false;
+	}
 
 	float height = float(viewport.m_y2 - viewport.m_y1 + 1);
 	float width  = float(viewport.m_x2 - viewport.m_x1 + 1);
@@ -211,14 +214,13 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
 	float x_lb = float(viewport.m_x1);
 	float y_lb = float(viewport.m_y1);
 
+	MT_Vector4 frompoint;
+	MT_Vector4 topoint;
+	
 	/* There's some strangeness I don't fully get here... These values
-	 * _should_ be wrong! */
+	 * _should_ be wrong! - see from point Z values */
+	
 	
-
-	/* old: */
-	float nearclip = 0.0;
-	float farclip = 1.0;
-
 	/*	build the from and to point in normalized device coordinates 
 	 *	Looks like normailized device coordinates are [-1,1] in x [-1,1] in y
 	 *	[0,-1] in z 
@@ -226,23 +228,19 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
 	 *	The actual z coordinates used don't have to be exact just infront and 
 	 *	behind of the near and far clip planes.
 	 */ 
-	MT_Vector4 frompoint = MT_Vector4( 
-		(2 * (m_x-x_lb) / width) - 1.0,
-		1.0 - (2 * (m_y - y_lb) / height),
-		nearclip,
-		1.0
-	);
-	MT_Vector4 topoint = MT_Vector4( 
-		(2 * (m_x-x_lb) / width) - 1.0,
-		1.0 - (2 * (m_y-y_lb) / height),
-		farclip,
-		1.0
-	);
+	frompoint.setValue(	(2 * (m_x-x_lb) / width) - 1.0,
+						1.0 - (2 * (m_y - y_lb) / height),
+						/*cam->GetCameraData()->m_perspective ? 0.0:cdata->m_clipstart,*/ /* real clipstart is scaled in ortho for some reason, zero is ok */
+						0.0, /* nearclip, see above comments */
+						1.0 );
+	
+	topoint.setValue(	(2 * (m_x-x_lb) / width) - 1.0,
+						1.0 - (2 * (m_y-y_lb) / height),
+						cam->GetCameraData()->m_perspective ? 1.0:cam->GetCameraData()->m_clipend, /* farclip, see above comments */
+						1.0 );
 
 	/* camera to world  */
 	MT_Transform wcs_camcs_tranform = cam->GetWorldToCamera();
-	if (!cam->GetCameraData()->m_perspective)
-		wcs_camcs_tranform.getOrigin()[2] *= 100.0;
 	MT_Transform cams_wcs_transform;
 	cams_wcs_transform.invert(wcs_camcs_tranform);
 	
@@ -260,31 +258,74 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
 	topoint   = camcs_wcs_matrix * topoint;
 	
 	/* from hom wcs to 3d wcs: */
-	MT_Point3 frompoint3 = MT_Point3(frompoint[0]/frompoint[3], 
-									 frompoint[1]/frompoint[3], 
-									 frompoint[2]/frompoint[3]); 
-	MT_Point3 topoint3 = MT_Point3(topoint[0]/topoint[3], 
-								   topoint[1]/topoint[3], 
-								   topoint[2]/topoint[3]); 
-	m_prevTargetPoint = topoint3;
-	m_prevSourcePoint = frompoint3;
+	m_prevSourcePoint.setValue(	frompoint[0]/frompoint[3],
+								frompoint[1]/frompoint[3],
+								frompoint[2]/frompoint[3]); 
+	
+	m_prevTargetPoint.setValue(	topoint[0]/topoint[3],
+								topoint[1]/topoint[3],
+								topoint[2]/topoint[3]); 
 	
 	/* 2. Get the object from PhysicsEnvironment */
 	/* Shoot! Beware that the first argument here is an
 	 * ignore-object. We don't ignore anything... */
-	
 	KX_IPhysicsController* physics_controller = cam->GetPhysicsController();
 	PHY_IPhysicsEnvironment* physics_environment = m_kxscene->GetPhysicsEnvironment();
 
-	bool result = false;
-
 	KX_RayCast::Callback<KX_MouseFocusSensor> callback(this,physics_controller);
-	KX_RayCast::RayTest(physics_environment, frompoint3, topoint3, callback);
+	 
+	KX_RayCast::RayTest(physics_environment, m_prevSourcePoint, m_prevTargetPoint, callback);
+	
+	if (m_hitObject)
+		return true;
 	
-	result = (m_hitObject!=0);
+	return false;
+}
 
-	return result;
+bool KX_MouseFocusSensor::ParentObjectHasFocus()
+{
+	m_hitObject = 0;
+	m_hitPosition.setValue(0,0,0);
+	m_hitNormal.setValue(1,0,0);
+	
+	KX_Camera *cam= m_kxscene->GetActiveCamera();
+	
+	if(ParentObjectHasFocusCamera(cam))
+		return true;
+
+	list<class KX_Camera*>* cameras = m_kxscene->GetCameras();
+	list<KX_Camera*>::iterator it = cameras->begin();
+	
+	while(it != cameras->end())
+	{
+		if(((*it) != cam) && (*it)->GetViewport())
+			if (ParentObjectHasFocusCamera(*it))
+				return true;
+		
+		it++;
+	}
+	
+	return false;
+}
+
+const MT_Point3& KX_MouseFocusSensor::RaySource() const
+{
+	return m_prevSourcePoint;
+}
+
+const MT_Point3& KX_MouseFocusSensor::RayTarget() const
+{
+	return m_prevTargetPoint;
+}
 
+const MT_Point3& KX_MouseFocusSensor::HitPosition() const
+{
+	return m_hitPosition;
+}
+
+const MT_Vector3& KX_MouseFocusSensor::HitNormal() const
+{
+	return m_hitNormal;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -293,12 +334,17 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_MouseFocusSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_MouseFocusSensor",
-	sizeof(KX_MouseFocusSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -328,11 +374,16 @@ PyMethodDef KX_MouseFocusSensor::Methods[] = {
 	{"getHitNormal",(PyCFunction) KX_MouseFocusSensor::sPyGetHitNormal,METH_NOARGS, (PY_METHODCHAR)GetHitNormal_doc},
 	{"getRayDirection",(PyCFunction) KX_MouseFocusSensor::sPyGetRayDirection,METH_NOARGS, (PY_METHODCHAR)GetRayDirection_doc},
 
-
 	{NULL,NULL} //Sentinel
 };
 
 PyAttributeDef KX_MouseFocusSensor::Attributes[] = {
+	KX_PYATTRIBUTE_RO_FUNCTION("raySource",		KX_MouseFocusSensor, pyattr_get_ray_source),
+	KX_PYATTRIBUTE_RO_FUNCTION("rayTarget",		KX_MouseFocusSensor, pyattr_get_ray_target),
+	KX_PYATTRIBUTE_RO_FUNCTION("rayDirection",	KX_MouseFocusSensor, pyattr_get_ray_direction),
+	KX_PYATTRIBUTE_RO_FUNCTION("hitObject",		KX_MouseFocusSensor, pyattr_get_hit_object),
+	KX_PYATTRIBUTE_RO_FUNCTION("hitPosition",	KX_MouseFocusSensor, pyattr_get_hit_position),
+	KX_PYATTRIBUTE_RO_FUNCTION("hitNormal",		KX_MouseFocusSensor, pyattr_get_hit_normal),
 	{ NULL }	//Sentinel
 };
 
@@ -340,14 +391,20 @@ PyObject* KX_MouseFocusSensor::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_MouseSensor);
 }
 
+PyObject* KX_MouseFocusSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_MouseSensor);
+}
+
 
 const char KX_MouseFocusSensor::GetHitObject_doc[] = 
 "getHitObject()\n"
-"\tReturns the name of the object that was hit by this ray.\n";
-PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self)
+"\tReturns the object that was hit by this ray.\n";
+PyObject* KX_MouseFocusSensor::PyGetHitObject()
 {
+	ShowDeprecationWarning("GetHitObject()", "the hitObject property");
+	
 	if (m_hitObject)
-		return m_hitObject->AddRef();
+		return m_hitObject->GetProxy();
 	
 	Py_RETURN_NONE;
 }
@@ -356,27 +413,33 @@ PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self)
 const char KX_MouseFocusSensor::GetHitPosition_doc[] = 
 "getHitPosition()\n"
 "\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n";
-PyObject* KX_MouseFocusSensor::PyGetHitPosition(PyObject* self)
+PyObject* KX_MouseFocusSensor::PyGetHitPosition()
 {
+	ShowDeprecationWarning("getHitPosition()", "the hitPosition property");
+	
 	return PyObjectFrom(m_hitPosition);
 }
 
 const char KX_MouseFocusSensor::GetRayDirection_doc[] = 
 "getRayDirection()\n"
 "\tReturns the direction from the ray (in worldcoordinates) .\n";
-PyObject* KX_MouseFocusSensor::PyGetRayDirection(PyObject* self)
+PyObject* KX_MouseFocusSensor::PyGetRayDirection()
 {
-
+	ShowDeprecationWarning("getRayDirection()", "the rayDirection property");
+	
 	MT_Vector3 dir = m_prevTargetPoint - m_prevSourcePoint;
-	dir.normalize();
+	if(MT_fuzzyZero(dir))	dir.setValue(0,0,0);
+	else					dir.normalize();
 	return PyObjectFrom(dir);
 }
 
 const char KX_MouseFocusSensor::GetHitNormal_doc[] = 
 "getHitNormal()\n"
-"\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n";
-PyObject* KX_MouseFocusSensor::PyGetHitNormal(PyObject* self)
+"\tReturns the normal (in worldcoordinates) at the point of collision where the object was hit by this ray.\n";
+PyObject* KX_MouseFocusSensor::PyGetHitNormal()
 {
+	ShowDeprecationWarning("getHitNormal()", "the hitNormal property");
+	
 	return PyObjectFrom(m_hitNormal);
 }
 
@@ -386,7 +449,10 @@ const char KX_MouseFocusSensor::GetRayTarget_doc[] =
 "getRayTarget()\n"
 "\tReturns the target of the ray that seeks the focus object,\n"
 "\tin worldcoordinates.";
-PyObject* KX_MouseFocusSensor::PyGetRayTarget(PyObject* self) {
+PyObject* KX_MouseFocusSensor::PyGetRayTarget()
+{
+	ShowDeprecationWarning("getRayTarget()", "the rayTarget property");
+	
 	return PyObjectFrom(m_prevTargetPoint);
 }
 
@@ -395,9 +461,58 @@ const char KX_MouseFocusSensor::GetRaySource_doc[] =
 "getRaySource()\n"
 "\tReturns the source of the ray that seeks the focus object,\n"
 "\tin worldcoordinates.";
-PyObject* KX_MouseFocusSensor::PyGetRaySource(PyObject* self) {
+PyObject* KX_MouseFocusSensor::PyGetRaySource()
+{
+	ShowDeprecationWarning("getRaySource()", "the raySource property");
+	
 	return PyObjectFrom(m_prevSourcePoint);
 }
 
+/* Attributes */
+PyObject* KX_MouseFocusSensor::pyattr_get_ray_source(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
+	return PyObjectFrom(self->RaySource());
+}
+
+PyObject* KX_MouseFocusSensor::pyattr_get_ray_target(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
+	return PyObjectFrom(self->RayTarget());
+}
+
+PyObject* KX_MouseFocusSensor::pyattr_get_ray_direction(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
+	MT_Vector3 dir = self->RayTarget() - self->RaySource();
+	if(MT_fuzzyZero(dir))	dir.setValue(0,0,0);
+	else					dir.normalize();
+	return PyObjectFrom(dir);
+}
+
+PyObject* KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
+	
+	if(self->m_hitObject)
+		return self->m_hitObject->GetProxy();
+	
+	Py_RETURN_NONE;
+}
+
+PyObject* KX_MouseFocusSensor::pyattr_get_hit_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
+	return PyObjectFrom(self->HitPosition());
+}
+
+PyObject* KX_MouseFocusSensor::pyattr_get_hit_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v);
+	return PyObjectFrom(self->HitNormal());
+}
+
+
+
 /* eof */
 
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
index 804f34e6076a1c3b70dd655eac60d9c2c601e0a2..29d674eb30527875f5186d9fc516390c6335f1af 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
@@ -54,7 +54,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
 						int starty,
 						short int mousemode,
 						int focusmode,
-						RAS_ICanvas* canvas,
 						KX_Scene* kxscene,
 						KX_KetsjiEngine* kxengine,
 						SCA_IObject* gameobj,
@@ -64,13 +63,13 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
 	virtual CValue* GetReplica() {
 		CValue* replica = new KX_MouseFocusSensor(*this);
 		// this will copy properties and so on...
-		CValue::AddDataToReplica(replica);
+		replica->ProcessReplica();
 		return replica;
 	};
 	/**
 	 * @attention Overrides default evaluate. 
 	 */
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual void Init();
 
 	virtual bool IsPositiveTrigger() {
@@ -82,12 +81,16 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
 	bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
 	bool NeedRayCast(KX_ClientObjectInfo* client) { return true; }
 	
-
+	const MT_Point3& RaySource() const;
+	const MT_Point3& RayTarget() const;
+	const MT_Point3& HitPosition() const;
+	const MT_Vector3& HitNormal() const;
 	
 	/* --------------------------------------------------------------------- */
 	/* Python interface ---------------------------------------------------- */
 	/* --------------------------------------------------------------------- */
-	virtual PyObject*  py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 
 	KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayTarget);
 	KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRaySource);
@@ -97,6 +100,14 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
 	KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetHitNormal);
 	KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayDirection);
 
+	/* attributes */
+	static PyObject*	pyattr_get_ray_source(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_ray_target(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_ray_direction(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_hit_object(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_hit_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_hit_normal(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+		
 	/* --------------------------------------------------------------------- */
 	SCA_IObject*	m_hitObject;
 
@@ -116,9 +127,13 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
 	 */
 	bool m_positive_event;
 
+ 	/**
+	 * Tests whether the object is in mouse focus for this camera
+	 */
+	bool ParentObjectHasFocusCamera(KX_Camera *cam);
 	
 	/**
-	 * Tests whether the object is in mouse focus in this frame.
+	 * Tests whether the object is in mouse focus in this scene.
 	 */
 	bool ParentObjectHasFocus(void);
 
@@ -142,12 +157,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
 	 * the object was hit.  */
 	MT_Vector3		 m_hitNormal;
 
-
-	/**
-	 * The active canvas. The size of this canvas determines a part of
-	 * the start position of the picking ray.  */
-	RAS_ICanvas* m_gp_canvas;
-
 	/**
 	 * The KX scene that holds the camera. The camera position
 	 * determines a part of the start location of the picking ray.  */
diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp
index 2debfd793c16efccae24b6710728deaa1f771a81..a3c4e95ae245f237b22626d1a971f75c54bb4bfe 100644
--- a/source/gameengine/Ketsji/KX_NearSensor.cpp
+++ b/source/gameengine/Ketsji/KX_NearSensor.cpp
@@ -109,52 +109,34 @@ void KX_NearSensor::UnregisterSumo(KX_TouchEventManager* touchman)
 CValue* KX_NearSensor::GetReplica()
 {
 	KX_NearSensor* replica = new KX_NearSensor(*this);
-	replica->m_colliders = new CListValue();
-	replica->Init();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
+	return replica;
+}
+
+void KX_NearSensor::ProcessReplica()
+{
+	KX_TouchSensor::ProcessReplica();
 	
-	replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::NEAR);
+	m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::NEAR);
 	
-	if (replica->m_physCtrl)
+	if (m_physCtrl)
 	{
-		replica->m_physCtrl = replica->m_physCtrl->GetReplica();
-		if (replica->m_physCtrl)
+		m_physCtrl = m_physCtrl->GetReplica();
+		if (m_physCtrl)
 		{
 			//static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->addSensor(replica->m_physCtrl);
-			replica->m_physCtrl->SetMargin(m_Margin);
-			replica->m_physCtrl->setNewClientInfo(replica->m_client_info);
+			m_physCtrl->SetMargin(m_Margin);
+			m_physCtrl->setNewClientInfo(m_client_info);
 		}
 		
 	}
-	//static_cast<KX_TouchEventManager*>(m_eventmgr)->RegisterSensor(this);
-	//todo: make sure replication works fine
-	//>m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
-	//replica->m_sumoObj->setMargin(m_Margin);
-	//replica->m_sumoObj->setClientObject(replica->m_client_info);
-	
-	((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL);
-	replica->SynchronizeTransform();
-	
-	return replica;
 }
 
-
-
 void KX_NearSensor::ReParent(SCA_IObject* parent)
 {
 	m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); 
 	m_client_info->m_sensors.push_back(this);
-	
-
-/*	KX_ClientObjectInfo *client_info = gameobj->getClientInfo();
-	client_info->m_gameobject = gameobj;
-	client_info->m_auxilary_info = NULL;
-	
-	client_info->m_sensors.push_back(this);
-	SCA_ISensor::ReParent(parent);
-*/
-	((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL);
+	//Synchronize here with the actual parent.
 	SynchronizeTransform();
 	SCA_ISensor::ReParent(parent);
 }
@@ -178,7 +160,7 @@ KX_NearSensor::~KX_NearSensor()
 }
 
 
-bool KX_NearSensor::Evaluate(CValue* event)
+bool KX_NearSensor::Evaluate()
 {
 	bool result = false;
 //	KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
@@ -287,12 +269,17 @@ bool	KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData
 /* ------------------------------------------------------------------------- */
 
 PyTypeObject KX_NearSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_NearSensor",
-	sizeof(KX_NearSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -332,18 +319,14 @@ PyAttributeDef KX_NearSensor::Attributes[] = {
 
 PyObject* KX_NearSensor::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
-
 	py_getattro_up(KX_TouchSensor);
 }
 
+PyObject* KX_NearSensor::py_getattro_dict() {
+	py_getattro_dict_up(KX_TouchSensor);
+}
+
 int KX_NearSensor::py_setattro(PyObject*attr, PyObject* value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-
-	return KX_TouchSensor::py_setattro(attr, value);
+	py_setattro_up(KX_TouchSensor);
 }
diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h
index 26c5feb4e67afe7db052eb98ce4680e777f4eb5b..35136b79d138d0a96c3b2f80a2cd23268f949c9c 100644
--- a/source/gameengine/Ketsji/KX_NearSensor.h
+++ b/source/gameengine/Ketsji/KX_NearSensor.h
@@ -70,7 +70,8 @@ public:
 	virtual ~KX_NearSensor(); 
 	virtual void SynchronizeTransform();
 	virtual CValue* GetReplica();
-	virtual bool Evaluate(CValue* event);
+	virtual void ProcessReplica();
+	virtual bool Evaluate();
 
 	virtual void ReParent(SCA_IObject* parent);
 	virtual bool	NewHandleCollision(void* obj1,void* obj2,
@@ -83,6 +84,7 @@ public:
 	/* Python interface ---------------------------------------------------- */
 	/* --------------------------------------------------------------------- */
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject* value);
 
 	//No methods
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
index a343eeb71ccd065f9a6ac73395e3183d3e37daa9..e3d7a0f4b7127c9f93f630d563bb05016853812a 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -253,9 +253,6 @@ CValue* KX_ObjectActuator::GetReplica()
 	KX_ObjectActuator* replica = new KX_ObjectActuator(*this);//m_float,GetName());
 	replica->ProcessReplica();
 
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-
 	return replica;
 }
 
@@ -277,12 +274,17 @@ bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_ObjectActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_ObjectActuator",
-	sizeof(KX_ObjectActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -333,6 +335,17 @@ PyMethodDef KX_ObjectActuator::Methods[] = {
 };
 
 PyAttributeDef KX_ObjectActuator::Attributes[] = {
+	//KX_PYATTRIBUTE_TODO("force"),
+	//KX_PYATTRIBUTE_TODO("torque"),
+	//KX_PYATTRIBUTE_TODO("dLoc"),
+	//KX_PYATTRIBUTE_TODO("dRot"),
+	//KX_PYATTRIBUTE_TODO("linV"),
+	//KX_PYATTRIBUTE_TODO("angV"),
+	//KX_PYATTRIBUTE_TODO("damping"),
+	//KX_PYATTRIBUTE_TODO("forceLimitX"),
+	//KX_PYATTRIBUTE_TODO("forceLimitY"),
+	//KX_PYATTRIBUTE_TODO("forceLimitZ"),
+	//KX_PYATTRIBUTE_TODO("pid"),
 	{ NULL }	//Sentinel
 };
 
@@ -340,29 +353,31 @@ PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) {
 	py_getattro_up(SCA_IActuator);
 };
 
+PyObject* KX_ObjectActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 /* 1. set ------------------------------------------------------------------ */
 /* Removed! */
 
 /* 2. getForce                                                               */
-PyObject* KX_ObjectActuator::PyGetForce(PyObject* self)
+PyObject* KX_ObjectActuator::PyGetForce()
 {
 	PyObject *retVal = PyList_New(4);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_force[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_force[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_force[2]));
-	PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_force[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_force[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_force[2]));
+	PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
 	
 	return retVal;
 }
 /* 3. setForce                                                               */
-PyObject* KX_ObjectActuator::PySetForce(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_ObjectActuator::PySetForce(PyObject* args)
 {
 	float vecArg[3];
 	int bToggle = 0;
-	if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
+	if (!PyArg_ParseTuple(args, "fffi:setForce", &vecArg[0], &vecArg[1], 
 						  &vecArg[2], &bToggle)) {
 		return NULL;
 	}
@@ -373,25 +388,23 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self,
 }
 
 /* 4. getTorque                                                              */
-PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self)
+PyObject* KX_ObjectActuator::PyGetTorque()
 {
 	PyObject *retVal = PyList_New(4);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2]));
-	PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
+	PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
 	
 	return retVal;
 }
 /* 5. setTorque                                                              */
-PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, 
-										 PyObject* args, 
-										 PyObject* kwds)
+PyObject* KX_ObjectActuator::PySetTorque(PyObject* args)
 {
 	float vecArg[3];
 	int bToggle = 0;
-	if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
+	if (!PyArg_ParseTuple(args, "fffi:setTorque", &vecArg[0], &vecArg[1], 
 						  &vecArg[2], &bToggle)) {
 		return NULL;
 	}
@@ -402,25 +415,23 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self,
 }
 
 /* 6. getDLoc                                                                */
-PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self)
+PyObject* KX_ObjectActuator::PyGetDLoc()
 {
 	PyObject *retVal = PyList_New(4);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
-	PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
+	PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
 	
 	return retVal;
 }
 /* 7. setDLoc                                                                */
-PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, 
-									   PyObject* args, 
-									   PyObject* kwds)
+PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args)
 {
 	float vecArg[3];
 	int bToggle = 0;
-	if(!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
+	if(!PyArg_ParseTuple(args, "fffi:setDLoc", &vecArg[0], &vecArg[1], 
 						 &vecArg[2], &bToggle)) {
 		return NULL;
 	}
@@ -431,25 +442,23 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self,
 }
 
 /* 8. getDRot                                                                */
-PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self)
+PyObject* KX_ObjectActuator::PyGetDRot()
 {
 	PyObject *retVal = PyList_New(4);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_drot[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_drot[2]));
-	PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_drot[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_drot[2]));
+	PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
 	
 	return retVal;
 }
 /* 9. setDRot                                                                */
-PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, 
-									   PyObject* args, 
-									   PyObject* kwds)
+PyObject* KX_ObjectActuator::PySetDRot(PyObject* args)
 {
 	float vecArg[3];
 	int bToggle = 0;
-	if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
+	if (!PyArg_ParseTuple(args, "fffi:setDRot", &vecArg[0], &vecArg[1], 
 						  &vecArg[2], &bToggle)) {
 		return NULL;
 	}
@@ -460,24 +469,22 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self,
 }
 
 /* 10. getLinearVelocity                                                 */
-PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self) {
+PyObject* KX_ObjectActuator::PyGetLinearVelocity() {
 	PyObject *retVal = PyList_New(4);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
-	PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
+	PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
 	
 	return retVal;
 }
 
 /* 11. setLinearVelocity                                                 */
-PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, 
-												 PyObject* args, 
-												 PyObject* kwds) {
+PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) {
 	float vecArg[3];
 	int bToggle = 0;
-	if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
+	if (!PyArg_ParseTuple(args, "fffi:setLinearVelocity", &vecArg[0], &vecArg[1], 
 						  &vecArg[2], &bToggle)) {
 		return NULL;
 	}
@@ -489,23 +496,21 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self,
 
 
 /* 12. getAngularVelocity                                                */
-PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self) {
+PyObject* KX_ObjectActuator::PyGetAngularVelocity() {
 	PyObject *retVal = PyList_New(4);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
-	PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
+	PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
 	
 	return retVal;
 }
 /* 13. setAngularVelocity                                                */
-PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, 
-												  PyObject* args, 
-												  PyObject* kwds) {
+PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) {
 	float vecArg[3];
 	int bToggle = 0;
-	if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
+	if (!PyArg_ParseTuple(args, "fffi:setAngularVelocity", &vecArg[0], &vecArg[1], 
 						  &vecArg[2], &bToggle)) {
 		return NULL;
 	}
@@ -516,11 +521,9 @@ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self,
 }
 
 /* 13. setDamping                                                */
-PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, 
-										  PyObject* args, 
-										  PyObject* kwds) {
+PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) {
 	int damping = 0;
-	if (!PyArg_ParseTuple(args, "i", &damping) || damping < 0 || damping > 1000) {
+	if (!PyArg_ParseTuple(args, "i:setDamping", &damping) || damping < 0 || damping > 1000) {
 		return NULL;
 	}
 	m_damping = damping;
@@ -528,28 +531,26 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* self,
 }
 
 /* 13. getVelocityDamping                                                */
-PyObject* KX_ObjectActuator::PyGetDamping(PyObject* self) {
+PyObject* KX_ObjectActuator::PyGetDamping() {
 	return Py_BuildValue("i",m_damping);
 }
 /* 6. getForceLimitX                                                                */
-PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self)
+PyObject* KX_ObjectActuator::PyGetForceLimitX()
 {
 	PyObject *retVal = PyList_New(3);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
-	PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
+	PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
 	
 	return retVal;
 }
 /* 7. setForceLimitX                                                         */
-PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, 
-											  PyObject* args, 
-											  PyObject* kwds)
+PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args)
 {
 	float vecArg[2];
 	int bToggle = 0;
-	if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
+	if(!PyArg_ParseTuple(args, "ffi:setForceLimitX", &vecArg[0], &vecArg[1], &bToggle)) {
 		return NULL;
 	}
 	m_drot[0] = vecArg[0];
@@ -559,24 +560,22 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self,
 }
 
 /* 6. getForceLimitY                                                                */
-PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self)
+PyObject* KX_ObjectActuator::PyGetForceLimitY()
 {
 	PyObject *retVal = PyList_New(3);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[1]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
-	PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[1]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
+	PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
 	
 	return retVal;
 }
 /* 7. setForceLimitY                                                                */
-PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, 
-											  PyObject* args, 
-											  PyObject* kwds)
+PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args)
 {
 	float vecArg[2];
 	int bToggle = 0;
-	if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
+	if(!PyArg_ParseTuple(args, "ffi:setForceLimitY", &vecArg[0], &vecArg[1], &bToggle)) {
 		return NULL;
 	}
 	m_drot[1] = vecArg[0];
@@ -586,24 +585,22 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self,
 }
 
 /* 6. getForceLimitZ                                                                */
-PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self)
+PyObject* KX_ObjectActuator::PyGetForceLimitZ()
 {
 	PyObject *retVal = PyList_New(3);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[2]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
-	PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[2]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
+	PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
 	
 	return retVal;
 }
 /* 7. setForceLimitZ                                                                */
-PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, 
-											  PyObject* args, 
-											  PyObject* kwds)
+PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args)
 {
 	float vecArg[2];
 	int bToggle = 0;
-	if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
+	if(!PyArg_ParseTuple(args, "ffi:setForceLimitZ", &vecArg[0], &vecArg[1], &bToggle)) {
 		return NULL;
 	}
 	m_drot[2] = vecArg[0];
@@ -613,23 +610,21 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self,
 }
 
 /* 4. getPID                                                              */
-PyObject* KX_ObjectActuator::PyGetPID(PyObject* self)
+PyObject* KX_ObjectActuator::PyGetPID()
 {
 	PyObject *retVal = PyList_New(3);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2]));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
 	
 	return retVal;
 }
 /* 5. setPID                                                              */
-PyObject* KX_ObjectActuator::PySetPID(PyObject* self, 
-									  PyObject* args, 
-									  PyObject* kwds)
+PyObject* KX_ObjectActuator::PySetPID(PyObject* args)
 {
 	float vecArg[3];
-	if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) {
+	if (!PyArg_ParseTuple(args, "fff:setPID", &vecArg[0], &vecArg[1], &vecArg[2])) {
 		return NULL;
 	}
 	m_torque.setValue(vecArg);
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h
index 00c8fb700ae3f505e6e1993cc394080c7a32b30c..ab5fbe44409268ec58036393263f7af39a340b39 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.h
@@ -154,29 +154,30 @@ public:
 	/* --------------------------------------------------------------------- */
 	
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce);
-	KX_PYMETHOD(KX_ObjectActuator,SetForce);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForce);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetTorque);
-	KX_PYMETHOD(KX_ObjectActuator,SetTorque);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetTorque);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDLoc);
-	KX_PYMETHOD(KX_ObjectActuator,SetDLoc);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetDLoc);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDRot);
-	KX_PYMETHOD(KX_ObjectActuator,SetDRot);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetDRot);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetLinearVelocity);
-	KX_PYMETHOD(KX_ObjectActuator,SetLinearVelocity);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetLinearVelocity);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetAngularVelocity);
-	KX_PYMETHOD(KX_ObjectActuator,SetAngularVelocity);
-	KX_PYMETHOD(KX_ObjectActuator,SetDamping);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetAngularVelocity);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetDamping);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDamping);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitX);
-	KX_PYMETHOD(KX_ObjectActuator,SetForceLimitX);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForceLimitX);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitY);
-	KX_PYMETHOD(KX_ObjectActuator,SetForceLimitY);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForceLimitY);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitZ);
-	KX_PYMETHOD(KX_ObjectActuator,SetForceLimitZ);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForceLimitZ);
 	KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetPID);
-	KX_PYMETHOD(KX_ObjectActuator,SetPID);
+	KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetPID);
 };
 
 #endif //__KX_OBJECTACTUATOR
diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h
index e3b5336c0b55ba2f1e0e9e9cf3054bb9e26b8c33..21b7e632d83e89320e07353d2ae2e5042524a95f 100644
--- a/source/gameengine/Ketsji/KX_OdePhysicsController.h
+++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h
@@ -82,6 +82,10 @@ public:
 
 	virtual	SG_Controller*	GetReplica(class SG_Node* destnode);
 
+	virtual	float GetLinVelocityMin() { return ODEPhysicsController::GetLinVelocityMin(); }
+	virtual void	SetLinVelocityMin(float val) { ODEPhysicsController::SetLinVelocityMin(val); }
+	virtual	float GetLinVelocityMax() { return ODEPhysicsController::GetLinVelocityMax(); }
+	virtual void	SetLinVelocityMax(float val) { ODEPhysicsController::SetLinVelocityMax(val); }
 	
 	virtual void	SetSumoTransform(bool nondynaonly);
 	// todo: remove next line !
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp
index 1baf581f8a00700dfefd4468610d69a04d986e5a..c5248785b12d73e28374f94950c3c5e030eda520 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp
@@ -73,8 +73,6 @@ CValue* KX_ParentActuator::GetReplica()
 	KX_ParentActuator* replica = new KX_ParentActuator(*this);
 	// replication just copy the m_base pointer => common random generator
 	replica->ProcessReplica();
-	CValue::AddDataToReplica(replica);
-
 	return replica;
 }
 
@@ -139,12 +137,17 @@ bool KX_ParentActuator::Update()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_ParentActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_ParentActuator",
-	sizeof(KX_ParentActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -175,6 +178,7 @@ PyMethodDef KX_ParentActuator::Methods[] = {
 
 PyAttributeDef KX_ParentActuator::Attributes[] = {
 	KX_PYATTRIBUTE_RW_FUNCTION("object", KX_ParentActuator, pyattr_get_object, pyattr_set_object),
+	KX_PYATTRIBUTE_INT_RW("mode", KX_PARENT_NODEF+1, KX_PARENT_MAX-1, true, KX_ParentActuator, m_mode),
 	{ NULL }	//Sentinel
 };
 
@@ -184,7 +188,7 @@ PyObject* KX_ParentActuator::pyattr_get_object(void *self, const struct KX_PYATT
 	if (!actuator->m_ob)	
 		Py_RETURN_NONE;
 	else
-		return actuator->m_ob->AddRef();
+		return actuator->m_ob->GetProxy();
 }
 
 int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -192,7 +196,7 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE
 	KX_ParentActuator* actuator = static_cast<KX_ParentActuator*>(self);
 	KX_GameObject *gameobj;
 		
-	if (!ConvertPythonToGameObject(value, &gameobj, true))
+	if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_ParentActuator"))
 		return 1; // ConvertPythonToGameObject sets the error
 		
 	if (actuator->m_ob != NULL)
@@ -208,19 +212,15 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE
 
 
 PyObject* KX_ParentActuator::py_getattro(PyObject *attr) {	
-	
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_ParentActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_ParentActuator::py_setattro(PyObject *attr, PyObject* value) {
-	
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 /* Deprecated -----> */
@@ -229,12 +229,12 @@ const char KX_ParentActuator::SetObject_doc[] =
 "setObject(object)\n"
 "\t- object: KX_GameObject, string or None\n"
 "\tSet the object to set as parent.\n";
-PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* value) {
+PyObject* KX_ParentActuator::PySetObject(PyObject* value) {
 	KX_GameObject *gameobj;
 	
 	ShowDeprecationWarning("setObject()", "the object property");
 	
-	if (!ConvertPythonToGameObject(value, &gameobj, true))
+	if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_ParentActuator"))
 		return NULL; // ConvertPythonToGameObject sets the error
 	
 	if (m_ob != NULL)
@@ -254,22 +254,22 @@ const char KX_ParentActuator::GetObject_doc[] =
 "getObject(name_only = 1)\n"
 "name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
 "\tReturns the object that is set to.\n";
-PyObject* KX_ParentActuator::PyGetObject(PyObject* self, PyObject* args)
+PyObject* KX_ParentActuator::PyGetObject(PyObject* args)
 {
 	int ret_name_only = 1;
 	
 	ShowDeprecationWarning("getObject()", "the object property");
 	
-	if (!PyArg_ParseTuple(args, "|i", &ret_name_only))
+	if (!PyArg_ParseTuple(args, "|i:getObject", &ret_name_only))
 		return NULL;
 	
 	if (!m_ob)
 		Py_RETURN_NONE;
 	
 	if (ret_name_only)
-		return PyString_FromString(m_ob->GetName());
+		return PyString_FromString(m_ob->GetName().ReadPtr());
 	else
-		return m_ob->AddRef();
+		return m_ob->GetProxy();
 }
 /* <----- */
 
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h
index f9f0b73b876d76ddab744bfd41dc68932138b339..6af0888e2bae99f7cf8ad5075b3cc5efd6a37349 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.h
+++ b/source/gameengine/Ketsji/KX_ParentActuator.h
@@ -57,6 +57,7 @@ class KX_ParentActuator : public SCA_IActuator
 		KX_PARENT_NODEF = 0,
 		KX_PARENT_SET,
 		KX_PARENT_REMOVE,
+		KX_PARENT_MAX
 
 	};
  
@@ -77,6 +78,7 @@ class KX_ParentActuator : public SCA_IActuator
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject* value);
 
 	/* These are used to get and set m_ob */
diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
index 3bef85e7f93fbe3a3aff6ddfae577938aa50d48d..c968e50957e7c4602f108432598e87dde115653a 100644
--- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
@@ -51,12 +51,10 @@ KX_PhysicsObjectWrapper::~KX_PhysicsObjectWrapper()
 }
 
 
-PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* args)
 {
 	float x,y,z;
-	if (PyArg_ParseTuple(args,"fff",&x,&y,&z))
+	if (PyArg_ParseTuple(args,"fff:setPosition",&x,&y,&z))
 	{
 		m_ctrl->setPosition(x,y,z);
 	}
@@ -67,13 +65,11 @@ PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* self,
 }
 
 
-PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* args)
 {
 	float x,y,z;
 	int local;
-	if (PyArg_ParseTuple(args,"fffi",&x,&y,&z,&local))
+	if (PyArg_ParseTuple(args,"fffi:setLinearVelocity",&x,&y,&z,&local))
 	{
 		m_ctrl->SetLinearVelocity(x,y,z,local != 0);
 	}
@@ -83,13 +79,11 @@ PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* self,
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* args)
 {
 	float x,y,z;
 	int local;
-	if (PyArg_ParseTuple(args,"fffi",&x,&y,&z,&local))
+	if (PyArg_ParseTuple(args,"fffi:setAngularVelocity",&x,&y,&z,&local))
 	{
 		m_ctrl->SetAngularVelocity(x,y,z,local != 0);
 	}
@@ -99,12 +93,10 @@ PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* self,
 	Py_RETURN_NONE;
 }
 
-PyObject*	KX_PhysicsObjectWrapper::PySetActive(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject*	KX_PhysicsObjectWrapper::PySetActive(PyObject* args)
 {
 	int active;
-	if (PyArg_ParseTuple(args,"i",&active))
+	if (PyArg_ParseTuple(args,"i:setActive",&active))
 	{
 		m_ctrl->SetActive(active!=0);
 	}
@@ -121,12 +113,17 @@ PyAttributeDef KX_PhysicsObjectWrapper::Attributes[] = {
 
 //python specific stuff
 PyTypeObject KX_PhysicsObjectWrapper::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_PhysicsObjectWrapper",
-		sizeof(KX_PhysicsObjectWrapper),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -144,11 +141,14 @@ PyParentObject KX_PhysicsObjectWrapper::Parents[] = {
 	NULL
 };
 
-PyObject*	KX_PhysicsObjectWrapper::py_getattro(PyObject *attr)
+PyObject* KX_PhysicsObjectWrapper::py_getattro(PyObject *attr)
 {
 	py_getattro_up(PyObjectPlus);
 }
 
+PyObject* KX_PhysicsObjectWrapper::py_getattro_dict() {
+	py_getattro_dict_up(PyObjectPlus);
+}
 
 int	KX_PhysicsObjectWrapper::py_setattro(PyObject *attr,PyObject *pyobj)
 {
diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h
index 6dc10f030f09bdb4913dceb08bcc7beffa03715c..1b59686babc0a8e55a881d1a4153be242d7f8c41 100644
--- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h
+++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h
@@ -37,15 +37,16 @@ class	KX_PhysicsObjectWrapper : public PyObjectPlus
 	Py_Header;
 
 	virtual PyObject*		py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int 			py_setattro(PyObject *attr, PyObject *value);
 public:
 	KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type);
 	virtual ~KX_PhysicsObjectWrapper();
 	
-	KX_PYMETHOD(KX_PhysicsObjectWrapper , SetPosition);
-	KX_PYMETHOD(KX_PhysicsObjectWrapper,SetLinearVelocity);
-	KX_PYMETHOD(KX_PhysicsObjectWrapper,SetAngularVelocity);
-	KX_PYMETHOD(KX_PhysicsObjectWrapper,SetActive);
+	KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetPosition);
+	KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetLinearVelocity);
+	KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetAngularVelocity);
+	KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetActive);
 
 private:
 	class PHY_IPhysicsController*	m_ctrl;
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp
index 6f74c3ed3f901782cfed79c00380bf8fa788e5e3..b56b5500c39fe419ceb86e365633ad06c05e5a96 100644
--- a/source/gameengine/Ketsji/KX_PolyProxy.cpp
+++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp
@@ -39,12 +39,17 @@
 #include "KX_PyMath.h"
 
 PyTypeObject KX_PolyProxy::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_PolyProxy",
-	sizeof(KX_PolyProxy),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -59,8 +64,8 @@ PyTypeObject KX_PolyProxy::Type = {
 
 PyParentObject KX_PolyProxy::Parents[] = {
 	&KX_PolyProxy::Type,
-	&SCA_IObject::Type,
 	&CValue::Type,
+	&PyObjectPlus::Type,
 	NULL
 };
 
@@ -78,6 +83,18 @@ PyMethodDef KX_PolyProxy::Methods[] = {
 };
 
 PyAttributeDef KX_PolyProxy::Attributes[] = {
+	/* All dummy's so they come up in a dir() */
+	//KX_PYATTRIBUTE_TODO("DummyProps"),
+	KX_PYATTRIBUTE_DUMMY("matname"),
+	KX_PYATTRIBUTE_DUMMY("texture"),
+	KX_PYATTRIBUTE_DUMMY("material"),
+	KX_PYATTRIBUTE_DUMMY("matid"),
+	KX_PYATTRIBUTE_DUMMY("v1"),
+	KX_PYATTRIBUTE_DUMMY("v2"),
+	KX_PYATTRIBUTE_DUMMY("v3"),
+	KX_PYATTRIBUTE_DUMMY("v4"),
+	KX_PYATTRIBUTE_DUMMY("visible"),
+	KX_PYATTRIBUTE_DUMMY("collide"),
 	{ NULL }	//Sentinel
 };
 
@@ -98,14 +115,12 @@ PyObject* KX_PolyProxy::py_getattro(PyObject *attr)
 		if(polymat->GetFlag() & RAS_BLENDERMAT)
 		{
 			KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
-			Py_INCREF(mat);
-			return mat;
+			return mat->GetProxy();
 		}
 		else
 		{
 			KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
-			Py_INCREF(mat);
-			return mat;
+			return mat->GetProxy();
 		}
 	}
 	if (!strcmp(attr_str, "matid"))
@@ -114,7 +129,7 @@ PyObject* KX_PolyProxy::py_getattro(PyObject *attr)
 		// the one of the polygon
 		RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
 		unsigned int matid;
-		for (matid=0; matid<m_mesh->NumMaterials(); matid++)
+		for (matid=0; matid<(unsigned int)m_mesh->NumMaterials(); matid++)
 		{
 			RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid);
 			if (meshMat->m_bucket == polyBucket)
@@ -147,7 +162,11 @@ PyObject* KX_PolyProxy::py_getattro(PyObject *attr)
 	{
 		return PyInt_FromLong(m_polygon->IsCollider());
 	}
-	py_getattro_up(SCA_IObject);
+	py_getattro_up(CValue);
+}
+
+PyObject* KX_PolyProxy::py_getattro_dict() {
+	py_getattro_dict_up(CValue);
 }
 
 KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon)
@@ -166,12 +185,10 @@ CValue*		KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
 CValue*		KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}	
 STR_String	sPolyName="polygone";
 const STR_String &	KX_PolyProxy::GetText() {return sPolyName;};
-float		KX_PolyProxy::GetNumber() { return -1;}
-STR_String	KX_PolyProxy::GetName() { return sPolyName;}
-void		KX_PolyProxy::SetName(STR_String) { };
+double		KX_PolyProxy::GetNumber() { return -1;}
+STR_String&	KX_PolyProxy::GetName() { return sPolyName;}
+void		KX_PolyProxy::SetName(const char *) { };
 CValue*		KX_PolyProxy::GetReplica() { return NULL;}
-void		KX_PolyProxy::ReplicaSetName(STR_String) {};
-
 
 // stuff for python integration
 
@@ -180,7 +197,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex,
 {
 	RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
 	unsigned int matid;
-	for (matid=0; matid<m_mesh->NumMaterials(); matid++)
+	for (matid=0; matid<(unsigned int)m_mesh->NumMaterials(); matid++)
 	{
 		RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid);
 		if (meshMat->m_bucket == polyBucket)
@@ -227,13 +244,13 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
 "Note: getVertexIndex(3) on a triangle polygon returns 0\n")
 {
 	int index;
-	if (!PyArg_ParseTuple(args,"i",&index))
+	if (!PyArg_ParseTuple(args,"i:getVertexIndex",&index))
 	{
 		return NULL;
 	}
 	if (index < 0 || index > 3)
 	{
-		PyErr_SetString(PyExc_AttributeError, "Valid range for index is 0-3");
+		PyErr_SetString(PyExc_AttributeError, "poly.getVertexIndex(int): KX_PolyProxy, expected an index between 0-3");
 		return NULL;
 	}
 	if (index < m_polygon->VertexCount())
@@ -247,7 +264,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh,
 "getMesh() : returns a mesh proxy\n")
 {
 	KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh);
-	return meshproxy;
+	return meshproxy->NewProxy(true);
 }
 
 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial,
@@ -257,13 +274,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial,
 	if(polymat->GetFlag() & RAS_BLENDERMAT)
 	{
 		KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
-		Py_INCREF(mat);
-		return mat;
+		return mat->GetProxy();
 	}
 	else
 	{
 		KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
-		Py_INCREF(mat);
-		return mat;
+		return mat->GetProxy();
 	}
 }
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h
index a549d9841cc7761e39c9efdbd7f433abfcae4cc6..d8fd36fec6cb45d1cb8e83858a05f17b98f8420d 100644
--- a/source/gameengine/Ketsji/KX_PolyProxy.h
+++ b/source/gameengine/Ketsji/KX_PolyProxy.h
@@ -31,7 +31,7 @@
 
 #include "SCA_IObject.h"
 
-class KX_PolyProxy	: public SCA_IObject
+class KX_PolyProxy	: public CValue
 {
 	Py_Header;
 protected:
@@ -45,15 +45,15 @@ public:
 	CValue*		Calc(VALUE_OPERATOR op, CValue *val) ;
 	CValue*		CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
 	const STR_String &	GetText();
-	float		GetNumber();
-	STR_String	GetName();
-	void		SetName(STR_String name);								// Set the name of the value
-	void		ReplicaSetName(STR_String name);
+	double		GetNumber();
+	STR_String&	GetName();
+	void		SetName(const char *name);								// Set the name of the value
 	CValue*		GetReplica();
 
 
 // stuff for python integration
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 
 	KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex)
 	KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex)
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
index 6b9a6201d5c668b1d38e7ae716642919c814a85f..2aa0ef921e97b7c33170cbc4d95c4cdbb26b44aa 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
@@ -51,22 +51,37 @@
 
 #include "KX_PyMath.h"
 
-KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname,
-											   Material *material,
-											   int tile,
-											   int tilexrep,
-											   int tileyrep,
-											   int mode,
-											   int transp,
-											   bool alpha,
-											   bool zsort,
-											   int lightlayer,
-											   struct MTFace* tface,
-											   unsigned int* mcol,
-											   PyTypeObject *T)
+KX_PolygonMaterial::KX_PolygonMaterial(PyTypeObject *T) 
 		: PyObjectPlus(T),
-		  RAS_IPolyMaterial(texname,
-							STR_String(material?material->id.name:""),
+		  RAS_IPolyMaterial(),
+
+	m_tface(NULL),
+	m_mcol(NULL),
+	m_material(NULL),
+	m_pymaterial(NULL),
+	m_pass(0)
+{
+}
+
+void KX_PolygonMaterial::Initialize(
+		const STR_String &texname,
+		Material* ma,
+		int materialindex,
+		int tile,
+		int tilexrep,
+		int tileyrep,
+		int mode,
+		int transp,
+		bool alpha,
+		bool zsort,
+		int lightlayer,
+		struct MTFace* tface,
+		unsigned int* mcol)
+{
+	RAS_IPolyMaterial::Initialize(
+							texname,
+							ma?ma->id.name:"",
+							materialindex,
 							tile,
 							tilexrep,
 							tileyrep,
@@ -74,13 +89,12 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname,
 							transp,
 							alpha,
 							zsort,
-							lightlayer),
-		m_tface(tface),
-		m_mcol(mcol),
-		m_material(material),
-		m_pymaterial(0),
-		m_pass(0)
-{
+							lightlayer);
+	m_tface = tface;
+	m_mcol = mcol;
+	m_material = ma;
+	m_pymaterial = 0;
+	m_pass = 0;
 }
 
 KX_PolygonMaterial::~KX_PolygonMaterial()
@@ -98,8 +112,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI
 	{
 		PyObject *pyRasty = PyCObject_FromVoidPtr((void*)rasty, NULL);	/* new reference */
 		PyObject *pyCachingInfo = PyCObject_FromVoidPtr((void*) &cachingInfo, NULL); /* new reference */
-		
-		PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this);
+		PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy);
 		if (ret)
 		{
 			bool value = PyInt_AsLong(ret);
@@ -109,6 +122,8 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI
 		else
 		{
 			PyErr_Print();
+			PyErr_Clear();
+			PySys_SetObject( (char *)"last_traceback", NULL);
 		}
 	}
 	else
@@ -157,15 +172,32 @@ void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& c
 			rasty->SetLines(true);
 		else
 			rasty->SetLines(false);
+		rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
+		rasty->SetShinyness(m_shininess);
+		rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
+		if (m_material)
+			rasty->SetPolygonOffset(-m_material->zoffs, 0.0);
 	}
 
-	rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
-	rasty->SetShinyness(m_shininess);
-	rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
-	if (m_material)
-		rasty->SetPolygonOffset(-m_material->zoffs, 0.0);
+	//rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
+	//rasty->SetShinyness(m_shininess);
+	//rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
+	//if (m_material)
+	//	rasty->SetPolygonOffset(-m_material->zoffs, 0.0);
 }
 
+void KX_PolygonMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
+{
+	if (m_material) {
+		*rgba++ = (unsigned char) (m_material->r*255.0);
+		*rgba++ = (unsigned char) (m_material->g*255.0);
+		*rgba++ = (unsigned char) (m_material->b*255.0);
+		*rgba++ = (unsigned char) (m_material->alpha*255.0);
+	} else
+		RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
+}
+
+
 //----------------------------------------------------------------------------
 //Python
 
@@ -181,16 +213,43 @@ PyMethodDef KX_PolygonMaterial::Methods[] = {
 };
 
 PyAttributeDef KX_PolygonMaterial::Attributes[] = {
+	KX_PYATTRIBUTE_RO_FUNCTION("texture",	KX_PolygonMaterial, pyattr_get_texture),
+	KX_PYATTRIBUTE_RO_FUNCTION("material",	KX_PolygonMaterial, pyattr_get_material), /* should probably be .name ? */
+	
+	KX_PYATTRIBUTE_INT_RW("tile", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tile),
+	KX_PYATTRIBUTE_INT_RW("tilexrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tilexrep),
+	KX_PYATTRIBUTE_INT_RW("tileyrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tileyrep),
+	KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode),	
+	KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer),
+
+	KX_PYATTRIBUTE_BOOL_RW("transparent", KX_PolygonMaterial, m_alpha),
+	KX_PYATTRIBUTE_BOOL_RW("zsort", KX_PolygonMaterial, m_zsort),
+	
+	KX_PYATTRIBUTE_FLOAT_RW("shininess", 0.0f, 1000.0f, KX_PolygonMaterial, m_shininess),
+	KX_PYATTRIBUTE_FLOAT_RW("specularity", 0.0f, 1000.0f, KX_PolygonMaterial, m_specularity),
+	
+	KX_PYATTRIBUTE_RW_FUNCTION("diffuse", KX_PolygonMaterial, pyattr_get_texture, pyattr_set_diffuse),
+	KX_PYATTRIBUTE_RW_FUNCTION("specular",KX_PolygonMaterial, pyattr_get_specular, pyattr_set_specular),	
+	
+	KX_PYATTRIBUTE_RO_FUNCTION("tface",	KX_PolygonMaterial, pyattr_get_tface), /* How the heck is this even useful??? - Campbell */
+	KX_PYATTRIBUTE_RO_FUNCTION("gl_texture", KX_PolygonMaterial, pyattr_get_gl_texture), /* could be called 'bindcode' */
+	
+	/* triangle used to be an attribute, removed for 2.49, nobody should be using it */
 	{ NULL }	//Sentinel
 };
 
 PyTypeObject KX_PolygonMaterial::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_PolygonMaterial",
-		sizeof(KX_PolygonMaterial),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -210,158 +269,23 @@ PyParentObject KX_PolygonMaterial::Parents[] = {
 };
 
 PyObject* KX_PolygonMaterial::py_getattro(PyObject *attr)
-{
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "texture"))
-		return PyString_FromString(m_texturename.ReadPtr());
-	if (!strcmp(attr_str, "material"))
-		return PyString_FromString(m_materialname.ReadPtr());
-		
-	if (!strcmp(attr_str, "tface"))
-		return PyCObject_FromVoidPtr(m_tface, NULL);
-		
-	if (!strcmp(attr_str, "gl_texture"))
-	{
-		Image *ima = m_tface->tpage;
-		int bind = 0;
-		if (ima)
-			bind = ima->bindcode;
-		
-		return PyInt_FromLong(bind);
-	}
-	
-	if (!strcmp(attr_str, "tile"))
-		return PyInt_FromLong(m_tile);
-	if (!strcmp(attr_str, "tilexrep"))
-		return PyInt_FromLong(m_tilexrep);
-	if (!strcmp(attr_str, "tileyrep"))
-		return PyInt_FromLong(m_tileyrep);
-	
-	if (!strcmp(attr_str, "drawingmode"))
-		return PyInt_FromLong(m_drawingmode);
-	if (!strcmp(attr_str, "transparent"))
-		return PyInt_FromLong(m_alpha);
-	if (!strcmp(attr_str, "zsort"))
-		return PyInt_FromLong(m_zsort);
-	if (!strcmp(attr_str, "lightlayer"))
-		return PyInt_FromLong(m_lightlayer);
-	if (!strcmp(attr_str, "triangle"))
-		// deprecated, triangle/quads shouldn't have been a material property
-		return 0;
-		
-	if (!strcmp(attr_str, "diffuse"))
-		return PyObjectFrom(m_diffuse);
-	if (!strcmp(attr_str, "shininess"))
-		return PyFloat_FromDouble(m_shininess);
-	if (!strcmp(attr_str, "specular"))
-		return PyObjectFrom(m_specular);
-	if (!strcmp(attr_str, "specularity"))
-		return PyFloat_FromDouble(m_specularity);
-	
+{	
 	py_getattro_up(PyObjectPlus);
 }
 
-int KX_PolygonMaterial::py_setattro(PyObject *attr, PyObject *pyvalue)
-{
-	char *attr_str= PyString_AsString(attr);
-	if (PyFloat_Check(pyvalue))
-	{
-		float value = PyFloat_AsDouble(pyvalue);
-		if (!strcmp(attr_str, "shininess"))
-		{
-			m_shininess = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "specularity"))
-		{
-			m_specularity = value;
-			return 0;
-		}
-	}
-	
-	if (PyInt_Check(pyvalue))
-	{
-		int value = PyInt_AsLong(pyvalue);
-		if (!strcmp(attr_str, "tile"))
-		{
-			m_tile = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "tilexrep"))
-		{
-			m_tilexrep = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "tileyrep"))
-		{
-			m_tileyrep = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "drawingmode"))
-		{
-			m_drawingmode = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "transparent"))
-		{
-			m_alpha = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "zsort"))
-		{
-			m_zsort = value;
-			return 0;
-		}
-		
-		if (!strcmp(attr_str, "lightlayer"))
-		{
-			m_lightlayer = value;
-			return 0;
-		}
-		
-		// This probably won't work...
-		if (!strcmp(attr_str, "triangle"))
-		{
-			// deprecated, triangle/quads shouldn't have been a material property
-			return 0;
-		}
-	}
-	
-	if (PySequence_Check(pyvalue))
-	{
-		if (PySequence_Size(pyvalue) == 3)
-		{
-			MT_Vector3 value;
-			if (PyVecTo(pyvalue, value))
-			{
-				if (!strcmp(attr_str, "diffuse"))
-				{
-					m_diffuse = value;
-					return 0;
-				}
-				
-				if (!strcmp(attr_str, "specular"))
-				{
-					m_specular = value;
-					return 0;
-				}
-			}
-		}
-	}
+PyObject* KX_PolygonMaterial::py_getattro_dict() {
+	py_getattro_dict_up(PyObjectPlus);
+}
 
-	return PyObjectPlus::py_setattro(attr, pyvalue);
+int KX_PolygonMaterial::py_setattro(PyObject *attr, PyObject *value)
+{
+	py_setattro_up(PyObjectPlus);
 }
 
 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(material)")
 {
 	PyObject *material;
-	if (PyArg_ParseTuple(args, "O", &material))
+	if (PyArg_ParseTuple(args, "O:setCustomMaterial", &material))
 	{
 		if (m_pymaterial) {
 			Py_DECREF(m_pymaterial);
@@ -377,7 +301,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(mat
 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rasty)")
 {
 	PyObject *pyrasty, *pytface;
-	if (PyArg_ParseTuple(args, "O!O!", &PyCObject_Type, &pytface, &PyCObject_Type, &pyrasty))
+	if (PyArg_ParseTuple(args, "O!O!:updateTexture", &PyCObject_Type, &pytface, &PyCObject_Type, &pyrasty))
 	{
 		MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface);
 		RAS_IRasterizer *rasty = (RAS_IRasterizer*) PyCObject_AsVoidPtr(pyrasty);
@@ -393,7 +317,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rast
 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)")
 {
 	PyObject *pytface;
-	if (PyArg_ParseTuple(args, "O!", &PyCObject_Type, &pytface))
+	if (PyArg_ParseTuple(args, "O!:setTexture", &PyCObject_Type, &pytface))
 	{
 		MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface);
 		GPU_set_tpage(tface);
@@ -406,7 +330,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)")
 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)")
 {
 	PyObject *pyrasty, *pyCachingInfo;
-	if (PyArg_ParseTuple(args, "O!O!", &PyCObject_Type, &pyrasty, &PyCObject_Type, &pyCachingInfo))
+	if (PyArg_ParseTuple(args, "O!O!:activate", &PyCObject_Type, &pyrasty, &PyCObject_Type, &pyCachingInfo))
 	{
 		RAS_IRasterizer *rasty = static_cast<RAS_IRasterizer*>(PyCObject_AsVoidPtr(pyrasty));
 		TCachingInfo *cachingInfo = static_cast<TCachingInfo*>(PyCObject_AsVoidPtr(pyCachingInfo));
@@ -419,3 +343,69 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)")
 	
 	return NULL;
 }
+
+PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
+	return PyString_FromString(self->m_texturename.ReadPtr());
+}
+
+PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
+	return PyString_FromString(self->m_materialname.ReadPtr());
+}
+
+/* this does not seem useful */
+PyObject* KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
+	return PyCObject_FromVoidPtr(self->m_tface, NULL);
+}
+
+PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
+	int bindcode= 0;
+	if (self->m_tface && self->m_tface->tpage)
+		bindcode= self->m_tface->tpage->bindcode;
+	
+	return PyInt_FromLong(bindcode);
+}
+
+
+PyObject* KX_PolygonMaterial::pyattr_get_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
+	return PyObjectFrom(self->m_diffuse);
+}
+
+int KX_PolygonMaterial::pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
+	MT_Vector3 vec;
+	
+	if (!PyVecTo(value, vec))
+		return -1;
+	
+	self->m_diffuse= vec;
+	return 0;
+}
+
+PyObject* KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
+	return PyObjectFrom(self->m_specular);
+}
+
+int KX_PolygonMaterial::pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
+	MT_Vector3 vec;
+	
+	if (!PyVecTo(value, vec))
+		return -1;
+	
+	self->m_specular= vec;
+	return 0;
+}
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h
index f3eb1979f34b57c5a05502b35747db878776c138..89ecb026da91592ae9d3d5d3832a30b26fa955c9 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.h
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h
@@ -33,6 +33,7 @@
 
 #include "RAS_MaterialBucket.h"
 #include "RAS_IRasterizer.h"
+#include "DNA_ID.h"
 
 struct MTFace;
 struct Material;
@@ -52,14 +53,14 @@ private:
 	MTFace*			m_tface;
 	unsigned int*	m_mcol;
 	Material*		m_material;
-	
 	PyObject*		m_pymaterial;
 
 	mutable int		m_pass;
 public:
-	
-	KX_PolygonMaterial(const STR_String &texname,
+	KX_PolygonMaterial(PyTypeObject *T = &Type);
+	void Initialize(const STR_String &texname,
 		Material* ma,
+		int materialindex,
 		int tile,
 		int tilexrep,
 		int tileyrep,
@@ -69,8 +70,8 @@ public:
 		bool zsort,
 		int lightlayer,
 		struct MTFace* tface,
-		unsigned int* mcol,
-		PyTypeObject *T = &Type);
+		unsigned int* mcol);
+
 	virtual ~KX_PolygonMaterial();
 	
 	/**
@@ -106,8 +107,8 @@ public:
 	{
 		return m_mcol;
 	}
-	
-	
+	virtual void GetMaterialRGBAColor(unsigned char *rgba) const;
+
 	KX_PYMETHOD_DOC(KX_PolygonMaterial, updateTexture);
 	KX_PYMETHOD_DOC(KX_PolygonMaterial, setTexture);
 	KX_PYMETHOD_DOC(KX_PolygonMaterial, activate);
@@ -116,7 +117,20 @@ public:
 	KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram);
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int       py_setattro(PyObject *attr, PyObject *pyvalue);
+	virtual PyObject* py_repr(void) { return PyString_FromString(m_material ? ((ID *)m_material)->name+2 : ""); }
+	
+	static PyObject*	pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	
+	static PyObject*	pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	
+	static PyObject*	pyattr_get_diffuse(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);	
+	static int			pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_specular(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);	
+	static int			pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 };
 
 #endif // __KX_POLYGONMATERIAL_H__
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index fb37eded45044ecceea8ed6ec036649bc936b002..0f21b24489dae7d4c22b0e859aed0b1a5df42be6 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -381,7 +381,7 @@ static PyObject* gPyGetVehicleConstraint(PyObject* self,
 			if (vehicle)
 			{
 				KX_VehicleWrapper* pyWrapper = new KX_VehicleWrapper(vehicle,PHY_GetActiveEnvironment());
-				return pyWrapper;
+				return pyWrapper->NewProxy(true);
 			}
 
 		}
@@ -440,7 +440,7 @@ static PyObject* gPyCreateConstraint(PyObject* self,
 				KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment());
 				
 
-				return wrap;
+				return wrap->NewProxy(true);
 			}
 			
 			
@@ -565,6 +565,19 @@ static struct PyMethodDef physicsconstraints_methods[] = {
 };
 
 
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef PhysicsConstraints_module_def = {
+	{}, /* m_base */
+	"PhysicsConstraints",  /* m_name */
+	PhysicsConstraints_module_documentation,  /* m_doc */
+	0,  /* m_size */
+	physicsconstraints_methods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
 
 PyObject*	initPythonConstraintBinding()
 {
@@ -573,15 +586,30 @@ PyObject*	initPythonConstraintBinding()
   PyObject* m;
   PyObject* d;
 
-
-  m = Py_InitModule4("PhysicsConstraints", physicsconstraints_methods,
+	/* Use existing module where possible
+	 * be careful not to init any runtime vars after this */
+	m = PyImport_ImportModule( "PhysicsConstraints" );
+	if(m) {
+		Py_DECREF(m);
+		return m;
+	}
+	else {
+		PyErr_Clear();
+	
+#if (PY_VERSION_HEX >= 0x03000000)
+		m = PyModule_Create(&PhysicsConstraints_module_def);
+#else
+		m = Py_InitModule4("PhysicsConstraints", physicsconstraints_methods,
 		     PhysicsConstraints_module_documentation,
 		     (PyObject*)NULL,PYTHON_API_VERSION);
+#endif
+	}
 
   // Add some symbolic constants to the module
   d = PyModule_GetDict(m);
   ErrorObject = PyString_FromString("PhysicsConstraints.error");
   PyDict_SetItemString(d, "error", ErrorObject);
+  Py_DECREF(ErrorObject);
 
   // XXXX Add constants here
 
diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp
index 92f18590a7e04ddf44f86c759fddb6cacd578577..051d7ae7dbab2fd0fc8aafe42ea18871a7375d30 100644
--- a/source/gameengine/Ketsji/KX_PyMath.cpp
+++ b/source/gameengine/Ketsji/KX_PyMath.cpp
@@ -44,6 +44,7 @@
 #include "ListValue.h"
 
 #include "KX_Python.h"
+#include "KX_PyMath.h"
 
 bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank)
 {
@@ -74,6 +75,38 @@ bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank)
 	return false;
 }
 
+bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefix)
+{
+	int size= PySequence_Size(pyval);
+	
+	if (size == 4)
+	{
+		MT_Quaternion qrot;
+		if (PyVecTo(pyval, qrot))
+		{
+			rot.setRotation(qrot);
+			return true;
+		}
+	}
+	else if (size == 3) {
+		/* 3x3 matrix or euler */
+		MT_Vector3 erot;
+		if (PyVecTo(pyval, erot))
+		{
+			rot.setEuler(erot);
+			return true;
+		}
+		PyErr_Clear();
+		
+		if (PyMatTo(pyval, rot))
+		{
+			return true;
+		}
+	}
+	
+	PyErr_Format(PyExc_TypeError, "%s, could not set the orientation from a 3x3 matrix, quaternion or euler sequence", error_prefix);
+	return false;
+}
 
 PyObject* PyObjectFrom(const MT_Matrix4x4 &mat)
 {
@@ -93,7 +126,7 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat)
 		PyList_SET_ITEM(sublist, 0, PyFloat_FromDouble(mat[i][0]));
 		PyList_SET_ITEM(sublist, 1, PyFloat_FromDouble(mat[i][1]));
 		PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][2]));
-		PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][3]));
+		PyList_SET_ITEM(sublist, 3, PyFloat_FromDouble(mat[i][3]));
 		PyList_SET_ITEM(list, i, sublist);
 	}
 	
diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h
index 39c9c3587927e7d7ede497b5386fe1ef3040534f..00f7c5cad9346f0627c0873b77dcdd204dbbb8ca 100644
--- a/source/gameengine/Ketsji/KX_PyMath.h
+++ b/source/gameengine/Ketsji/KX_PyMath.h
@@ -92,18 +92,35 @@ bool PyMatTo(PyObject* pymat, T& mat)
 }
 
 /**
- *  Converts a python list to a MT class.
+ *  Converts a python sequence to a MT class.
  */
 template<class T>
 bool PyVecTo(PyObject* pyval, T& vec)
 {
-	if (PySequence_Check(pyval))
+
+	if(PyTuple_Check(pyval))
+	{
+		unsigned int numitems = PyTuple_GET_SIZE(pyval);
+		if (numitems != Size(vec)) {
+			PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", numitems, Size(vec));
+			return false;
+		}
+		
+		for (unsigned int x = 0; x < numitems; x++)
+			vec[x] = PyFloat_AsDouble(PyTuple_GET_ITEM(pyval, x)); /* borrow ref */
+		
+		if (PyErr_Occurred()) {
+			PyErr_SetString(PyExc_AttributeError, "one or more of the items in the sequence was not a float");
+			return false;
+		}
+		
+		return true;
+	}
+	else if (PySequence_Check(pyval))
 	{
 		unsigned int numitems = PySequence_Size(pyval);
 		if (numitems != Size(vec)) {
-			char err[128];
-			sprintf(err, "error setting vector, %d args, should be %d", numitems, Size(vec));
-			PyErr_SetString(PyExc_AttributeError, err);
+			PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", numitems, Size(vec));
 			return false;
 		}
 		
@@ -122,14 +139,14 @@ bool PyVecTo(PyObject* pyval, T& vec)
 		return true;
 	} else
 	{
-		char err[128];
-		sprintf(err, "not a sequence type, expected a sequence of numbers size %d", Size(vec));
-		PyErr_SetString(PyExc_AttributeError, err);
+		PyErr_Format(PyExc_AttributeError, "not a sequence type, expected a sequence of numbers size %d", Size(vec));
 	}
 	
 	return false;
 }
 
+bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix);
+
 /**
  * Converts an MT_Matrix4x4 to a python object.
  */
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index f065eb29c443d5f3df21577b09c034f4c38d2859..57f736a6c09910e0a591c28390807225160ea406 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -49,24 +49,32 @@
 #include "KX_KetsjiEngine.h"
 #include "KX_RadarSensor.h"
 #include "KX_RaySensor.h"
+#include "KX_SceneActuator.h"
+#include "KX_GameActuator.h"
+#include "KX_ParentActuator.h"
 #include "KX_SCA_DynamicActuator.h"
 
 #include "SCA_IInputDevice.h"
 #include "SCA_PropertySensor.h"
 #include "SCA_RandomActuator.h"
+#include "SCA_KeyboardSensor.h" /* IsPrintable, ToCharacter */
 #include "KX_ConstraintActuator.h"
 #include "KX_IpoActuator.h"
 #include "KX_SoundActuator.h"
+#include "KX_StateActuator.h"
 #include "BL_ActionActuator.h"
 #include "RAS_IRasterizer.h"
 #include "RAS_ICanvas.h"
 #include "RAS_BucketManager.h"
+#include "RAS_2DFilterManager.h"
 #include "MT_Vector3.h"
 #include "MT_Point3.h"
 #include "ListValue.h"
 #include "KX_Scene.h"
 #include "SND_DeviceManager.h"
 
+#include "NG_NetworkScene.h" //Needed for sendMessage()
+
 #include "BL_Shader.h"
 
 #include "KX_PyMath.h"
@@ -75,8 +83,17 @@
 
 #include "KX_PythonInitTypes.h" 
 
+/* we only need this to get a list of libraries from the main struct */
+#include "DNA_ID.h"
+#include "BKE_main.h"
+
 extern "C" {
+	#include "bpy_internal_import.h"  /* from the blender python api, but we want to import text too! */
+#if PY_VERSION_HEX < 0x03000000
 	#include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use.
+	#include "Geometry.h" // Blender.Geometry module copied here so the blenderlayer can use.
+	#include "BGL.h"
+#endif
 }
 
 #include "marshal.h" /* python header for loading/saving dicts */
@@ -95,7 +112,7 @@ extern "C" {
 #include "GPU_material.h"
 
 static void setSandbox(TPythonSecurityLevel level);
-
+static void clearGameModules();
 
 // 'local' copy of canvas ptr, for window height/width python scripts
 static RAS_ICanvas* gp_Canvas = NULL;
@@ -103,6 +120,7 @@ static KX_Scene*	gp_KetsjiScene = NULL;
 static KX_KetsjiEngine*	gp_KetsjiEngine = NULL;
 static RAS_IRasterizer* gp_Rasterizer = NULL;
 static char gp_GamePythonPath[FILE_MAXDIR + FILE_MAXFILE] = "";
+static PyObject *gp_OrigPythonSysPath= NULL;
 
 void	KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
 {
@@ -112,9 +130,9 @@ void	KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,cons
 
 /* Macro for building the keyboard translation */
 //#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(SCA_IInputDevice::KX_##name))
-#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(name))
+#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name)); Py_DECREF(item)
 /* For the defines for types from logic bricks, we do stuff explicitly... */
-#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, PyInt_FromLong(name2))
+#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name2)); Py_DECREF(item)
 
 
 // temporarily python stuff, will be put in another place later !
@@ -157,7 +175,7 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args)
 	char expanded[FILE_MAXDIR + FILE_MAXFILE];
 	char* filename;
 	
-	if (!PyArg_ParseTuple(args,"s",&filename))
+	if (!PyArg_ParseTuple(args,"s:ExpandPath",&filename))
 		return NULL;
 
 	BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE);
@@ -165,6 +183,28 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args)
 	return PyString_FromString(expanded);
 }
 
+static char gPySendMessage_doc[] = 
+"sendMessage(subject, [body, to, from])\n\
+sends a message in same manner as a message actuator\
+subject = Subject of the message\
+body = Message body\
+to = Name of object to send the message to\
+from = Name of object to sned the string from";
+
+static PyObject* gPySendMessage(PyObject*, PyObject* args)
+{
+	char* subject;
+	char* body = (char *)"";
+	char* to = (char *)"";
+	char* from = (char *)"";
+
+	if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to, &from))
+		return NULL;
+
+	gp_KetsjiScene->GetNetworkScene()->SendMessage(to, from, subject, body);
+
+	Py_RETURN_NONE;
+}
 
 static bool usedsp = false;
 
@@ -187,13 +227,13 @@ static PyObject* gPyGetSpectrum(PyObject*)
 
 		for (int index = 0; index < 512; index++)
 		{
-			PyList_SetItem(resultlist, index, PyFloat_FromDouble(spectrum[index]));
+			PyList_SET_ITEM(resultlist, index, PyFloat_FromDouble(spectrum[index]));
 		}
 	}
 	else {
 		for (int index = 0; index < 512; index++)
 		{
-			PyList_SetItem(resultlist, index, PyFloat_FromDouble(0.0));
+			PyList_SET_ITEM(resultlist, index, PyFloat_FromDouble(0.0));
 		}
 	}
 
@@ -241,7 +281,7 @@ static PyObject* gPyStopDSP(PyObject*, PyObject* args)
 static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args)
 {
 	float ticrate;
-	if (!PyArg_ParseTuple(args, "f", &ticrate))
+	if (!PyArg_ParseTuple(args, "f:setLogicTicRate", &ticrate))
 		return NULL;
 	
 	KX_KetsjiEngine::SetTicRate(ticrate);
@@ -253,10 +293,25 @@ static PyObject* gPyGetLogicTicRate(PyObject*)
 	return PyFloat_FromDouble(KX_KetsjiEngine::GetTicRate());
 }
 
+static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args)
+{
+	int frame;
+	if (!PyArg_ParseTuple(args, "i:setMaxLogicFrame", &frame))
+		return NULL;
+	
+	KX_KetsjiEngine::SetMaxLogicFrame(frame);
+	Py_RETURN_NONE;
+}
+
+static PyObject* gPyGetMaxLogicFrame(PyObject*)
+{
+	return PyInt_FromLong(KX_KetsjiEngine::GetMaxLogicFrame());
+}
+
 static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args)
 {
 	float ticrate;
-	if (!PyArg_ParseTuple(args, "f", &ticrate))
+	if (!PyArg_ParseTuple(args, "f:setPhysicsTicRate", &ticrate))
 		return NULL;
 	
 	PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate);
@@ -266,7 +321,7 @@ static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args)
 static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args)
 {
 	int debugMode;
-	if (!PyArg_ParseTuple(args, "i", &debugMode))
+	if (!PyArg_ParseTuple(args, "i:setPhysicsDebug", &debugMode))
 		return NULL;
 	
 	PHY_GetActiveEnvironment()->setDebugMode(debugMode);
@@ -294,7 +349,7 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args)
     DIR *dp;
     struct dirent *dirp;
 	
-	if (!PyArg_ParseTuple(args, "|s", &searchpath))
+	if (!PyArg_ParseTuple(args, "|s:getBlendFileList", &searchpath))
 		return NULL;
 	
 	list = PyList_New(0);
@@ -330,8 +385,7 @@ static STR_String gPyGetCurrentScene_doc =
 "Gets a reference to the current scene.\n";
 static PyObject* gPyGetCurrentScene(PyObject* self)
 {
-	Py_INCREF(gp_KetsjiScene);
-	return (PyObject*) gp_KetsjiScene;
+	return gp_KetsjiScene->GetProxy();
 }
 
 static STR_String gPyGetSceneList_doc =  
@@ -340,7 +394,6 @@ static STR_String gPyGetSceneList_doc =
 static PyObject* gPyGetSceneList(PyObject* self)
 {
 	KX_KetsjiEngine* m_engine = KX_GetActiveEngine();
-	//CListValue* list = new CListValue();
 	PyObject* list;
 	KX_SceneList* scenes = m_engine->CurrentScenes();
 	int numScenes = scenes->size();
@@ -351,13 +404,10 @@ static PyObject* gPyGetSceneList(PyObject* self)
 	for (i=0;i<numScenes;i++)
 	{
 		KX_Scene* scene = scenes->at(i);
-		//list->Add(scene);
-		PyList_SET_ITEM(list, i, scene);
-		Py_INCREF(scene);
-		
+		PyList_SET_ITEM(list, i, scene->GetProxy());
 	}
 	
-	return (PyObject*)list;
+	return list;
 }
 
 static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *)
@@ -434,6 +484,7 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *)
 
 static struct PyMethodDef game_methods[] = {
 	{"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, (PY_METHODCHAR)gPyExpandPath_doc},
+	{"sendMessage", (PyCFunction)gPySendMessage, METH_VARARGS, (PY_METHODCHAR)gPySendMessage_doc},
 	{"getCurrentController",
 	(PyCFunction) SCA_PythonController::sPyGetCurrentController,
 	METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::sPyGetCurrentController__doc__},
@@ -448,6 +499,8 @@ static struct PyMethodDef game_methods[] = {
 	{"setGravity",(PyCFunction) gPySetGravity, METH_O, (PY_METHODCHAR)"set Gravitation"},
 	{"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS, (PY_METHODCHAR)"get audio spectrum"},
 	{"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS, (PY_METHODCHAR)"stop using the audio dsp (for performance reasons)"},
+	{"getMaxLogicFrame", (PyCFunction) gPyGetMaxLogicFrame, METH_NOARGS, (PY_METHODCHAR)"Gets the max number of logic frame per render frame"},
+	{"setMaxLogicFrame", (PyCFunction) gPySetMaxLogicFrame, METH_VARARGS, (PY_METHODCHAR)"Sets the max number of logic frame per render frame"},
 	{"getLogicTicRate", (PyCFunction) gPyGetLogicTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the logic tic rate"},
 	{"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, (PY_METHODCHAR)"Sets the logic tic rate"},
 	{"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the physics tic rate"},
@@ -459,6 +512,127 @@ static struct PyMethodDef game_methods[] = {
 };
 
 
+static PyObject* gPyGetScreenPosition(PyObject*, PyObject* value)
+{
+	MT_Vector3 vect;
+	KX_GameObject *obj = NULL;
+
+	if (!PyVecTo(value, vect))
+	{
+		if(ConvertPythonToGameObject(value, &obj, true, ""))
+		{
+			PyErr_Clear();
+			vect = MT_Vector3(obj->NodeGetWorldPosition());
+		}
+		else
+		{
+			PyErr_SetString(PyExc_TypeError, "Error in getScreenPosition. Expected a Vector3 or a KX_GameObject or a string for a name of a KX_GameObject");
+			return NULL;
+		}
+	}
+
+	GLdouble modelMatrix[16];
+	GLdouble projMatrix[16];
+	GLint	viewport[4];
+	GLdouble win[3];
+
+	glGetIntegerv(GL_VIEWPORT, viewport);
+	glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
+	glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+
+	gluProject(vect[0], vect[1], vect[2], modelMatrix, projMatrix, viewport, &win[0], &win[1], &win[2]);
+
+	vect[0] =  win[0] / (viewport[0] + viewport[2]);
+	vect[1] =  win[1] / (viewport[1] + viewport[3]);
+
+	PyObject* ret = PyTuple_New(2);
+	if(ret){
+		PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(vect[0]));
+		PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(vect[1]));
+		return ret;
+	}
+
+	return NULL;
+}
+
+static PyObject* gPyGetScreenVect(PyObject*, PyObject* args)
+{
+	double x,y;
+	if (!PyArg_ParseTuple(args,"dd:getScreenVect",&x,&y))
+		return NULL;
+
+	MT_Vector3 vect;
+	MT_Point3 campos, screenpos;
+
+	GLdouble modelMatrix[16];
+	GLdouble projMatrix[16];
+	GLint	viewport[4];
+	GLdouble win[3];
+
+	glGetIntegerv(GL_VIEWPORT, viewport);
+	glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
+	glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+
+	vect[0] = x * viewport[2];
+	vect[1] = y * viewport[3];
+
+	vect[0] += viewport[0];
+	vect[1] += viewport[1];
+
+	glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &vect[2]);
+	gluUnProject(vect[0], vect[1], vect[2], modelMatrix, projMatrix, viewport, &win[0], &win[1], &win[2]);
+
+	campos    = gp_Rasterizer->GetCameraPosition();
+	screenpos = MT_Point3(win[0], win[1], win[2]);
+	vect = campos-screenpos;
+
+	vect.normalize();
+	return PyObjectFrom(vect);
+}
+
+static PyObject* gPyGetScreenRay(PyObject* self, PyObject* args)
+{
+	KX_Camera* cam;
+	MT_Vector3 vect;
+	double x,y,dist;
+	char *propName = NULL;
+
+	if (!PyArg_ParseTuple(args,"ddd|s:getScreenRay",&x,&y,&dist,&propName))
+		return NULL;
+
+	PyObject* argValue = PyTuple_New(2);
+	if (argValue) {
+		PyTuple_SET_ITEM(argValue, 0, PyFloat_FromDouble(x));
+		PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(y));
+	}
+
+	if(!PyVecTo(gPyGetScreenVect(self,argValue), vect))
+	{
+		Py_DECREF(argValue);
+		PyErr_SetString(PyExc_TypeError,
+			"Error in getScreenRay. Invalid 2D coordinate. Expected a normalized 2D screen coordinate and an optional property argument");
+		return NULL;
+	}
+	Py_DECREF(argValue);
+
+	cam = gp_KetsjiScene->GetActiveCamera();
+	dist *= -1.0;
+
+	argValue = (propName?PyTuple_New(3):PyTuple_New(2));
+	if (argValue) {
+		PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect));
+		PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist));
+		if (propName)
+			PyTuple_SET_ITEM(argValue, 2, PyString_FromString(propName));
+
+		PyObject* ret= cam->PyrayCastTo(argValue,NULL);
+		Py_DECREF(argValue);
+		return ret;
+	}
+
+	return NULL;
+}
+
 static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args)
 {
 	return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0));
@@ -479,7 +653,7 @@ bool gUseVisibilityTemp = false;
 static PyObject* gPyEnableVisibility(PyObject*, PyObject* args)
 {
 	int visible;
-	if (!PyArg_ParseTuple(args,"i",&visible))
+	if (!PyArg_ParseTuple(args,"i:enableVisibility",&visible))
 		return NULL;
 	
 	gUseVisibilityTemp = (visible != 0);
@@ -491,7 +665,7 @@ static PyObject* gPyEnableVisibility(PyObject*, PyObject* args)
 static PyObject* gPyShowMouse(PyObject*, PyObject* args)
 {
 	int visible;
-	if (!PyArg_ParseTuple(args,"i",&visible))
+	if (!PyArg_ParseTuple(args,"i:showMouse",&visible))
 		return NULL;
 	
 	if (visible)
@@ -512,7 +686,7 @@ static PyObject* gPyShowMouse(PyObject*, PyObject* args)
 static PyObject* gPySetMousePosition(PyObject*, PyObject* args)
 {
 	int x,y;
-	if (!PyArg_ParseTuple(args,"ii",&x,&y))
+	if (!PyArg_ParseTuple(args,"ii:setMousePosition",&x,&y))
 		return NULL;
 	
 	if (gp_Canvas)
@@ -524,11 +698,11 @@ static PyObject* gPySetMousePosition(PyObject*, PyObject* args)
 static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args)
 {
 	float sep;
-	if (!PyArg_ParseTuple(args, "f", &sep))
+	if (!PyArg_ParseTuple(args, "f:setEyeSeparation", &sep))
 		return NULL;
 
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setEyeSeparation(float), Rasterizer not available");
 		return NULL;
 	}
 	
@@ -537,10 +711,10 @@ static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args)
 	Py_RETURN_NONE;
 }
 
-static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*)
+static PyObject* gPyGetEyeSeparation(PyObject*)
 {
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getEyeSeparation(), Rasterizer not available");
 		return NULL;
 	}
 	
@@ -550,11 +724,11 @@ static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*)
 static PyObject* gPySetFocalLength(PyObject*, PyObject* args)
 {
 	float focus;
-	if (!PyArg_ParseTuple(args, "f", &focus))
+	if (!PyArg_ParseTuple(args, "f:setFocalLength", &focus))
 		return NULL;
 	
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setFocalLength(float), Rasterizer not available");
 		return NULL;
 	}
 
@@ -566,7 +740,7 @@ static PyObject* gPySetFocalLength(PyObject*, PyObject* args)
 static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*)
 {
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getFocalLength(), Rasterizer not available");
 		return NULL;
 	}
 	
@@ -599,7 +773,7 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* value)
 		return NULL;
 	
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available");
 		return NULL;
 	}	
 	gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]);
@@ -607,17 +781,28 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* value)
 	Py_RETURN_NONE;
 }
 
+static PyObject* gPyDisableMist(PyObject*)
+{
+	
+	if (!gp_Rasterizer) {
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available");
+		return NULL;
+	}	
+	gp_Rasterizer->DisableFog();
+	
+	Py_RETURN_NONE;
+}
 
 
 static PyObject* gPySetMistStart(PyObject*, PyObject* args)
 {
 
 	float miststart;
-	if (!PyArg_ParseTuple(args,"f",&miststart))
+	if (!PyArg_ParseTuple(args,"f:setMistStart",&miststart))
 		return NULL;
 	
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistStart(float), Rasterizer not available");
 		return NULL;
 	}
 	
@@ -632,11 +817,11 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args)
 {
 
 	float mistend;
-	if (!PyArg_ParseTuple(args,"f",&mistend))
+	if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistend))
 		return NULL;
 	
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistEnd(float), Rasterizer not available");
 		return NULL;
 	}
 	
@@ -654,7 +839,7 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* value)
 		return NULL;
 	
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available");
 		return NULL;
 	}	
 	gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]);
@@ -668,7 +853,7 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* value)
 static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args)
 {
 	char* filename;
-	if (!PyArg_ParseTuple(args,"s",&filename))
+	if (!PyArg_ParseTuple(args,"s:makeScreenshot",&filename))
 		return NULL;
 	
 	if (gp_Canvas)
@@ -682,11 +867,11 @@ static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args)
 static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args)
 {
 	float motionblurvalue;
-	if (!PyArg_ParseTuple(args,"f",&motionblurvalue))
+	if (!PyArg_ParseTuple(args,"f:enableMotionBlur",&motionblurvalue))
 		return NULL;
 	
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.enableMotionBlur(float), Rasterizer not available");
 		return NULL;
 	}
 	
@@ -695,10 +880,10 @@ static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args)
 	Py_RETURN_NONE;
 }
 
-static PyObject* gPyDisableMotionBlur(PyObject*, PyObject* args)
+static PyObject* gPyDisableMotionBlur(PyObject*)
 {
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.disableMotionBlur(), Rasterizer not available");
 		return NULL;
 	}
 	
@@ -732,13 +917,13 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*,
 	char *setting;
 	int enable, flag, fileflags;
 
-	if (!PyArg_ParseTuple(args,"si",&setting,&enable))
+	if (!PyArg_ParseTuple(args,"si:setGLSLMaterialSetting",&setting,&enable))
 		return NULL;
 	
 	flag = getGLSLSettingFlag(setting);
 	
 	if  (flag==-1) {
-		PyErr_SetString(PyExc_ValueError, "glsl setting is not known");
+		PyErr_SetString(PyExc_ValueError, "Rasterizer.setGLSLMaterialSetting(string): glsl setting is not known");
 		return NULL;
 	}
 
@@ -751,16 +936,17 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*,
 
 	/* display lists and GLSL materials need to be remade */
 	if(G.fileflags != fileflags) {
+		GPU_materials_free();
 		if(gp_KetsjiEngine) {
 			KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes();
 			KX_SceneList::iterator it;
 
 			for(it=scenes->begin(); it!=scenes->end(); it++)
-				if((*it)->GetBucketManager())
+				if((*it)->GetBucketManager()) {
 					(*it)->GetBucketManager()->ReleaseDisplayLists();
+					(*it)->GetBucketManager()->ReleaseMaterials();
+				}
 		}
-
-		GPU_materials_free();
 	}
 
 	Py_RETURN_NONE;
@@ -773,13 +959,13 @@ static PyObject* gPyGetGLSLMaterialSetting(PyObject*,
 	char *setting;
 	int enabled = 0, flag;
 
-	if (!PyArg_ParseTuple(args,"s",&setting))
+	if (!PyArg_ParseTuple(args,"s:getGLSLMaterialSetting",&setting))
 		return NULL;
 	
 	flag = getGLSLSettingFlag(setting);
 	
 	if  (flag==-1) {
-		PyErr_SetString(PyExc_ValueError, "glsl setting is not known");
+		PyErr_SetString(PyExc_ValueError, "Rasterizer.getGLSLMaterialSetting(string): glsl setting is not known");
 		return NULL;
 	}
 
@@ -797,7 +983,7 @@ static PyObject* gPySetMaterialType(PyObject*,
 {
 	int flag, type;
 
-	if (!PyArg_ParseTuple(args,"i",&type))
+	if (!PyArg_ParseTuple(args,"i:setMaterialType",&type))
 		return NULL;
 
 	if(type == KX_BLENDER_GLSL_MATERIAL)
@@ -807,7 +993,7 @@ static PyObject* gPySetMaterialType(PyObject*,
 	else if(type == KX_TEXFACE_MATERIAL)
 		flag = 0;
 	else {
-		PyErr_SetString(PyExc_ValueError, "material type is not known");
+		PyErr_SetString(PyExc_ValueError, "Rasterizer.setMaterialType(int): material type is not known");
 		return NULL;
 	}
 
@@ -821,7 +1007,7 @@ static PyObject* gPyGetMaterialType(PyObject*)
 {
 	int flag;
 
-	if(G.fileflags & (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL))
+	if(G.fileflags & G_FILE_GAME_MAT_GLSL)
 		flag = KX_BLENDER_GLSL_MATERIAL;
 	else if(G.fileflags & G_FILE_GAME_MAT)
 		flag = KX_BLENDER_MULTITEX_MATERIAL;
@@ -838,11 +1024,11 @@ static PyObject* gPyDrawLine(PyObject*, PyObject* args)
 	PyObject* ob_color;
 
 	if (!gp_Rasterizer) {
-		PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+		PyErr_SetString(PyExc_RuntimeError, "Rasterizer.drawLine(obFrom, obTo, color): Rasterizer not available");
 		return NULL;
 	}
 
-	if (!PyArg_ParseTuple(args,"OOO",&ob_from,&ob_to,&ob_color))
+	if (!PyArg_ParseTuple(args,"OOO:drawLine",&ob_from,&ob_to,&ob_color))
 		return NULL;
 
 	MT_Vector3 from;
@@ -861,6 +1047,12 @@ static PyObject* gPyDrawLine(PyObject*, PyObject* args)
 }
 
 static struct PyMethodDef rasterizer_methods[] = {
+  {"getScreenPosition",(PyCFunction) gPyGetScreenPosition,
+   METH_O, "getScreenPosition doc"},
+  {"getScreenVect",(PyCFunction) gPyGetScreenVect,
+   METH_VARARGS, "getScreenVect doc"},
+  {"getScreenRay",(PyCFunction) gPyGetScreenRay,
+   METH_VARARGS, "getScreenRay doc"},
   {"getWindowWidth",(PyCFunction) gPyGetWindowWidth,
    METH_VARARGS, "getWindowWidth doc"},
    {"getWindowHeight",(PyCFunction) gPyGetWindowHeight,
@@ -875,15 +1067,16 @@ static struct PyMethodDef rasterizer_methods[] = {
    METH_VARARGS, "setMousePosition(int x,int y)"},
   {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"},
 	{"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"},
+ {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"},
  {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"},
   {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"},
   {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"},
   {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"},
-  {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_VARARGS,"disable motion blur"},
+  {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"},
 
   
   {"setEyeSeparation", (PyCFunction) gPySetEyeSeparation, METH_VARARGS, "set the eye separation for stereo mode"},
-  {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_VARARGS, "get the eye separation for stereo mode"},
+  {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_NOARGS, "get the eye separation for stereo mode"},
   {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"},
   {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"},
   {"setMaterialMode",(PyCFunction) gPySetMaterialType,
@@ -909,32 +1102,64 @@ static char Rasterizer_module_documentation[] =
 "This is the Python API for the game engine of Rasterizer"
 ;
 
-
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef GameLogic_module_def = {
+	{}, /* m_base */
+	"GameLogic",  /* m_name */
+	GameLogic_module_documentation,  /* m_doc */
+	0,  /* m_size */
+	game_methods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
 
 PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook
 {
 	PyObject* m;
 	PyObject* d;
-
+	PyObject* item; /* temp PyObject* storage */
+	
 	gp_KetsjiEngine = engine;
 	gp_KetsjiScene = scene;
 
 	gUseVisibilityTemp=false;
-
-	// Create the module and add the functions
-	m = Py_InitModule4("GameLogic", game_methods,
-					   GameLogic_module_documentation,
-					   (PyObject*)NULL,PYTHON_API_VERSION);
-
+	
+	PyObjectPlus::ClearDeprecationWarning(); /* Not that nice to call here but makes sure warnings are reset between loading scenes */
+	
+	/* Use existing module where possible
+	 * be careful not to init any runtime vars after this */
+	m = PyImport_ImportModule( "GameLogic" );
+	if(m) {
+		Py_DECREF(m);
+		return m;
+	}
+	else {
+		PyErr_Clear();
+		
+		// Create the module and add the functions	
+#if (PY_VERSION_HEX >= 0x03000000)
+		m = PyModule_Create(&GameLogic_module_def);
+#else
+		m = Py_InitModule4("GameLogic", game_methods,
+						   GameLogic_module_documentation,
+						   (PyObject*)NULL,PYTHON_API_VERSION);
+#endif
+	}
+	
 	// Add some symbolic constants to the module
 	d = PyModule_GetDict(m);
 	
 	// can be overwritten later for gameEngine instances that can load new blend files and re-initialize this module
 	// for now its safe to make sure it exists for other areas such as the web plugin
-	PyDict_SetItemString(d, "globalDict", PyDict_New());
+	
+	PyDict_SetItemString(d, "globalDict", item=PyDict_New()); Py_DECREF(item);
 
 	ErrorObject = PyString_FromString("GameLogic.error");
 	PyDict_SetItemString(d, "error", ErrorObject);
+	Py_DECREF(ErrorObject);
 	
 	// XXXX Add constants here
 	/* To use logic bricks, we need some sort of constants. Here, we associate */
@@ -967,6 +1192,12 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
 	KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX);
 	KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIY);
 	KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIZ);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPX);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPY);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPZ);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNX);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNY);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNZ);
 
 	/* 4. Ipo actuator, simple part                                            */
 	KX_MACRO_addTypesToDict(d, KX_IPOACT_PLAY,     KX_IpoActuator::KX_ACT_IPO_PLAY);
@@ -1089,6 +1320,73 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
 	KX_MACRO_addTypesToDict(d, KX_DYN_DISABLE_RIGID_BODY, KX_SCA_DynamicActuator::KX_DYN_DISABLE_RIGID_BODY);
 	KX_MACRO_addTypesToDict(d, KX_DYN_SET_MASS, KX_SCA_DynamicActuator::KX_DYN_SET_MASS);
 
+	/* Input & Mouse Sensor */
+	KX_MACRO_addTypesToDict(d, KX_INPUT_NONE, SCA_InputEvent::KX_NO_INPUTSTATUS);
+	KX_MACRO_addTypesToDict(d, KX_INPUT_JUST_ACTIVATED, SCA_InputEvent::KX_JUSTACTIVATED);
+	KX_MACRO_addTypesToDict(d, KX_INPUT_ACTIVE, SCA_InputEvent::KX_ACTIVE);
+	KX_MACRO_addTypesToDict(d, KX_INPUT_JUST_RELEASED, SCA_InputEvent::KX_JUSTRELEASED);
+	
+	KX_MACRO_addTypesToDict(d, KX_MOUSE_BUT_LEFT, SCA_IInputDevice::KX_LEFTMOUSE);
+	KX_MACRO_addTypesToDict(d, KX_MOUSE_BUT_MIDDLE, SCA_IInputDevice::KX_MIDDLEMOUSE);
+	KX_MACRO_addTypesToDict(d, KX_MOUSE_BUT_RIGHT, SCA_IInputDevice::KX_RIGHTMOUSE);
+
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_ENABLED, RAS_2DFilterManager::RAS_2DFILTER_ENABLED);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_DISABLED, RAS_2DFilterManager::RAS_2DFILTER_DISABLED);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_NOFILTER, RAS_2DFilterManager::RAS_2DFILTER_NOFILTER);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_MOTIONBLUR, RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_BLUR, RAS_2DFilterManager::RAS_2DFILTER_BLUR);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_SHARPEN, RAS_2DFilterManager::RAS_2DFILTER_SHARPEN);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_DILATION, RAS_2DFilterManager::RAS_2DFILTER_DILATION);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_EROSION, RAS_2DFilterManager::RAS_2DFILTER_EROSION);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_LAPLACIAN, RAS_2DFilterManager::RAS_2DFILTER_LAPLACIAN);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_SOBEL, RAS_2DFilterManager::RAS_2DFILTER_SOBEL);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_PREWITT, RAS_2DFilterManager::RAS_2DFILTER_PREWITT);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_GRAYSCALE, RAS_2DFilterManager::RAS_2DFILTER_GRAYSCALE);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_SEPIA, RAS_2DFilterManager::RAS_2DFILTER_SEPIA);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_INVERT, RAS_2DFilterManager::RAS_2DFILTER_INVERT);
+	KX_MACRO_addTypesToDict(d, RAS_2DFILTER_CUSTOMFILTER, RAS_2DFilterManager::RAS_2DFILTER_CUSTOMFILTER);
+		
+	KX_MACRO_addTypesToDict(d, KX_SOUNDACT_PLAYSTOP, KX_SoundActuator::KX_SOUNDACT_PLAYSTOP);
+	KX_MACRO_addTypesToDict(d, KX_SOUNDACT_PLAYEND, KX_SoundActuator::KX_SOUNDACT_PLAYEND);
+	KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPSTOP, KX_SoundActuator::KX_SOUNDACT_LOOPSTOP);
+	KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPEND, KX_SoundActuator:: KX_SOUNDACT_LOOPEND);
+	KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPBIDIRECTIONAL, KX_SoundActuator::KX_SOUNDACT_LOOPBIDIRECTIONAL);
+	KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP, KX_SoundActuator::KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP);
+
+	KX_MACRO_addTypesToDict(d, KX_STATE_OP_CPY, KX_StateActuator::OP_CPY);
+	KX_MACRO_addTypesToDict(d, KX_STATE_OP_SET, KX_StateActuator::OP_SET);
+	KX_MACRO_addTypesToDict(d, KX_STATE_OP_CLR, KX_StateActuator::OP_CLR);
+	KX_MACRO_addTypesToDict(d, KX_STATE_OP_NEG, KX_StateActuator::OP_NEG);
+
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_NORMAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_NORMAL);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_MATERIAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_MATERIAL);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_PERMANENT, KX_ConstraintActuator::KX_ACT_CONSTRAINT_PERMANENT);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DISTANCE, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DISTANCE);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_LOCAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCAL);
+	KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DOROTFH, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DOROTFH);
+
+	/* Game Actuator Modes */
+	KX_MACRO_addTypesToDict(d, KX_GAME_LOAD, KX_GameActuator::KX_GAME_LOAD);
+	KX_MACRO_addTypesToDict(d, KX_GAME_START, KX_GameActuator::KX_GAME_START);
+	KX_MACRO_addTypesToDict(d, KX_GAME_RESTART, KX_GameActuator::KX_GAME_RESTART);
+	KX_MACRO_addTypesToDict(d, KX_GAME_QUIT, KX_GameActuator::KX_GAME_QUIT);
+	KX_MACRO_addTypesToDict(d, KX_GAME_SAVECFG, KX_GameActuator::KX_GAME_SAVECFG);
+	KX_MACRO_addTypesToDict(d, KX_GAME_LOADCFG, KX_GameActuator::KX_GAME_LOADCFG);
+
+	/* Scene Actuator Modes */
+	KX_MACRO_addTypesToDict(d, KX_SCENE_RESTART, KX_SceneActuator::KX_SCENE_RESTART);
+	KX_MACRO_addTypesToDict(d, KX_SCENE_SET_SCENE, KX_SceneActuator::KX_SCENE_SET_SCENE);
+	KX_MACRO_addTypesToDict(d, KX_SCENE_SET_CAMERA, KX_SceneActuator::KX_SCENE_SET_CAMERA);
+	KX_MACRO_addTypesToDict(d, KX_SCENE_ADD_FRONT_SCENE, KX_SceneActuator::KX_SCENE_ADD_FRONT_SCENE);
+	KX_MACRO_addTypesToDict(d, KX_SCENE_ADD_BACK_SCENE, KX_SceneActuator::KX_SCENE_ADD_BACK_SCENE);
+	KX_MACRO_addTypesToDict(d, KX_SCENE_REMOVE_SCENE, KX_SceneActuator::KX_SCENE_REMOVE_SCENE);
+	KX_MACRO_addTypesToDict(d, KX_SCENE_SUSPEND, KX_SceneActuator::KX_SCENE_SUSPEND);
+	KX_MACRO_addTypesToDict(d, KX_SCENE_RESUME, KX_SceneActuator::KX_SCENE_RESUME);
+
+	/* Parent Actuator Modes */
+	KX_MACRO_addTypesToDict(d, KX_PARENT_SET, KX_ParentActuator::KX_PARENT_SET);
+	KX_MACRO_addTypesToDict(d, KX_PARENT_REMOVE, KX_ParentActuator::KX_PARENT_REMOVE);
+
 	// Check for errors
 	if (PyErr_Occurred())
     {
@@ -1107,11 +1405,6 @@ PyObject *KXpy_open(PyObject *self, PyObject *args) {
 	return NULL;
 }
 
-PyObject *KXpy_reload(PyObject *self, PyObject *args) {
-	PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function.");
-	return NULL;
-}
-
 PyObject *KXpy_file(PyObject *self, PyObject *args) {
 	PyErr_SetString(PyExc_RuntimeError, "Sandbox: file() function disabled!\nGame Scripts should not use this function.");
 	return NULL;
@@ -1130,6 +1423,7 @@ PyObject *KXpy_compile(PyObject *self, PyObject *args) {
 PyObject *KXpy_import(PyObject *self, PyObject *args)
 {
 	char *name;
+	int found;
 	PyObject *globals = NULL;
 	PyObject *locals = NULL;
 	PyObject *fromlist = NULL;
@@ -1159,14 +1453,45 @@ PyObject *KXpy_import(PyObject *self, PyObject *args)
 	/* quick hack for GamePython modules 
 		TODO: register builtin modules properly by ExtendInittab */
 	if (!strcmp(name, "GameLogic") || !strcmp(name, "GameKeys") || !strcmp(name, "PhysicsConstraints") ||
-		!strcmp(name, "Rasterizer") || !strcmp(name, "Mathutils")) {
+		!strcmp(name, "Rasterizer") || !strcmp(name, "Mathutils") || !strcmp(name, "BGL") || !strcmp(name, "Geometry")) {
 		return PyImport_ImportModuleEx(name, globals, locals, fromlist);
 	}
-		
-	PyErr_Format(PyExc_ImportError,
-		 "Import of external Module %.20s not allowed.", name);
+	
+	/* Import blender texts as python modules */
+	m= bpy_text_import(name, &found);
+	if (m)
+		return m;
+	
+	if(found==0) /* if its found but could not import then it has its own error */
+		PyErr_Format(PyExc_ImportError, "Import of external Module %.20s not allowed.", name);
+	
+	return NULL;
+
+}
+
+PyObject *KXpy_reload(PyObject *self, PyObject *args) {
+	
+	/* Used to be sandboxed, bettet to allow importing of internal text only */ 
+#if 0
+	PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function.");
 	return NULL;
+#endif
+	int found;
+	PyObject *module = NULL;
+	PyObject *newmodule = NULL;
 
+	/* check for a module arg */
+	if( !PyArg_ParseTuple( args, "O:bpy_reload_meth", &module ) )
+		return NULL;
+	
+	newmodule= bpy_text_reimport( module, &found );
+	if (newmodule)
+		return newmodule;
+	
+	if (found==0) /* if its found but could not import then it has its own error */
+		PyErr_SetString(PyExc_ImportError, "reload(module): failed to reload from blenders internal text");
+	
+	return newmodule;
 }
 
 /* override python file type functions */
@@ -1201,18 +1526,18 @@ void setSandbox(TPythonSecurityLevel level)
 {
     PyObject *m = PyImport_AddModule("__builtin__");
     PyObject *d = PyModule_GetDict(m);
-
+	PyObject *item;
 	switch (level) {
 	case psl_Highest:
 		//if (!g_security) {
 			//g_oldopen = PyDict_GetItemString(d, "open");
 	
 			// functions we cant trust
-			PyDict_SetItemString(d, "open", PyCFunction_New(meth_open, NULL));
-			PyDict_SetItemString(d, "reload", PyCFunction_New(meth_reload, NULL));
-			PyDict_SetItemString(d, "file", PyCFunction_New(meth_file, NULL));
-			PyDict_SetItemString(d, "execfile", PyCFunction_New(meth_execfile, NULL));
-			PyDict_SetItemString(d, "compile", PyCFunction_New(meth_compile, NULL));
+			PyDict_SetItemString(d, "open", item=PyCFunction_New(meth_open, NULL));			Py_DECREF(item);
+			PyDict_SetItemString(d, "reload", item=PyCFunction_New(meth_reload, NULL));		Py_DECREF(item);
+			PyDict_SetItemString(d, "file", item=PyCFunction_New(meth_file, NULL));			Py_DECREF(item);
+			PyDict_SetItemString(d, "execfile", item=PyCFunction_New(meth_execfile, NULL));	Py_DECREF(item);
+			PyDict_SetItemString(d, "compile", item=PyCFunction_New(meth_compile, NULL));		Py_DECREF(item);
 			
 			// our own import
 			PyDict_SetItemString(d, "__import__", PyCFunction_New(meth_import, NULL));
@@ -1241,59 +1566,246 @@ void setSandbox(TPythonSecurityLevel level)
 		}
 	*/
 	default:
+			/* Allow importing internal text, from bpy_internal_import.py */
+			PyDict_SetItemString(d, "reload", item=PyCFunction_New(bpy_reload_meth, NULL));		Py_DECREF(item);
+			PyDict_SetItemString(d, "__import__", item=PyCFunction_New(bpy_import_meth, NULL));	Py_DECREF(item);
 		break;
 	}
 }
 
+/* Explanation of 
+ * 
+ * - backupPySysPath()		: stores sys.path in gp_OrigPythonSysPath
+ * - initPySysPath(main)	: initializes the blendfile and library paths
+ * - restorePySysPath()		: restores sys.path from gp_OrigPythonSysPath
+ * 
+ * These exist so the current blend dir "//" can always be used to import modules from.
+ * the reason we need a few functions for this is that python is not only used by the game engine
+ * so we cant just add to sys.path all the time, it would leave pythons state in a mess.
+ * It would also be incorrect since loading blend files for new levels etc would alwasy add to sys.path
+ * 
+ * To play nice with blenders python, the sys.path is backed up and the current blendfile along
+ * with all its lib paths are added to the sys path.
+ * When loading a new blendfile, the original sys.path is restored and the new paths are added over the top.
+ */
+
+/**
+ * So we can have external modules mixed with our blend files.
+ */
+static void backupPySysPath(void)
+{
+	PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
+	
+	/* just incase its set */
+	Py_XDECREF(gp_OrigPythonSysPath);
+	gp_OrigPythonSysPath= NULL;
+	
+	gp_OrigPythonSysPath = PyList_GetSlice(sys_path, 0, INT_MAX); /* copy the list */
+}
+
+/* for initPySysPath only,
+ * takes a blend path and adds a scripts dir from it
+ *
+ * "/home/me/foo.blend" -> "/home/me/scripts"
+ */
+static void initPySysPath__append(PyObject *sys_path, char *filename)
+{
+	PyObject *item;
+	char expanded[FILE_MAXDIR + FILE_MAXFILE] = "//";
+	
+	BLI_convertstringcode(expanded, filename);
+	
+	item= PyString_FromString(expanded);
+	
+	if(PySequence_Index(sys_path, item) == -1) {
+		PyList_Insert(sys_path, 0, item);
+	}
+	
+	Py_DECREF(item);
+}
+static void initPySysPath(Main *maggie)
+{
+	PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
+	
+	if (gp_OrigPythonSysPath==NULL) {
+		/* backup */
+		backupPySysPath();
+	}
+	else {
+		/* get the original sys path when the BGE started */
+		PyList_SetSlice(sys_path, 0, INT_MAX, gp_OrigPythonSysPath);
+	}
+	
+	Library *lib= (Library *)maggie->library.first;
+	
+	while(lib) {
+		initPySysPath__append(sys_path, lib->name);
+		lib= (Library *)lib->id.next;
+	}
+	
+	initPySysPath__append(sys_path, gp_GamePythonPath);
+	
+//	fprintf(stderr, "\nNew Path: %d ", PyList_Size(sys_path));
+//	PyObject_Print(sys_path, stderr, 0);
+}
+
+static void restorePySysPath(void)
+{
+	if (gp_OrigPythonSysPath==NULL)
+		return;
+	
+	PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
+	
+	PyList_SetSlice(sys_path, 0, INT_MAX, gp_OrigPythonSysPath);
+	Py_DECREF(gp_OrigPythonSysPath);
+	gp_OrigPythonSysPath= NULL;
+	
+//	fprintf(stderr, "\nRestore Path: %d ", PyList_Size(sys_path));
+//	PyObject_Print(sys_path, stderr, 0);
+}
+
 /**
  * Python is not initialised.
  */
-PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level)
+PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv)
 {
+	/* Yet another gotcha in the py api
+	 * Cant run PySys_SetArgv more then once because this adds the
+	 * binary dir to the sys.path each time.
+	 * Id have thaught python being totally restarted would make this ok but
+	 * somehow it remembers the sys.path - Campbell
+	 */
+	static bool first_time = true;
+	
+#if (PY_VERSION_HEX < 0x03000000)
 	STR_String pname = progname;
 	Py_SetProgramName(pname.Ptr());
+#endif
 	Py_NoSiteFlag=1;
 	Py_FrozenFlag=1;
 	Py_Initialize();
-
+	
+#if (PY_VERSION_HEX < 0x03000000)	
+	if(argv && first_time) /* browser plugins dont currently set this */
+		PySys_SetArgv(argc, argv);
+#endif
 	//importBlenderModules()
 	
 	setSandbox(level);
 	initPyTypes();
-
+	
+	bpy_import_main_set(maggie);
+	
+	initPySysPath(maggie);
+	
+	first_time = false;
+	
+	PyObjectPlus::ClearDeprecationWarning();
+	
 	PyObject* moduleobj = PyImport_AddModule("__main__");
 	return PyModule_GetDict(moduleobj);
 }
 
 void exitGamePlayerPythonScripting()
 {
+	//clearGameModules(); // were closing python anyway
+	
+	/* since python restarts we cant let the python backup of the sys.path hang around in a global pointer */
+	restorePySysPath(); /* get back the original sys.path and clear the backup */
+	
 	Py_Finalize();
+	bpy_import_main_set(NULL);
+	PyObjectPlus::ClearDeprecationWarning();
 }
 
+
+
 /**
  * Python is already initialized.
  */
-PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level)
+PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie)
 {
+#if (PY_VERSION_HEX < 0x03000000)
 	STR_String pname = progname;
 	Py_SetProgramName(pname.Ptr());
+#endif
 	Py_NoSiteFlag=1;
 	Py_FrozenFlag=1;
 
 	setSandbox(level);
 	initPyTypes();
+	
+	bpy_import_main_set(maggie);
+	
+	initPySysPath(maggie);
+	
+	/* clear user defined modules that may contain data from the last run */
+	clearGameModules();
 
+	PyObjectPlus::NullDeprecationWarning();
+	
 	PyObject* moduleobj = PyImport_AddModule("__main__");
 	return PyModule_GetDict(moduleobj);
 }
 
-
-
-void exitGamePythonScripting()
+static void clearModule(PyObject *modules, const char *name)
 {
+	PyObject *mod= PyDict_GetItemString(modules, name);
+	
+	if (mod==NULL)
+		return;
+	
+	PyDict_Clear(PyModule_GetDict(mod)); /* incase there are any circular refs */
+	PyDict_DelItemString(modules, name);
 }
 
+static void clearGameModules()
+{
+	/* references to invalid BGE data is better supported in 2.49+ so dont clear dicts */
+#if 0
+	/* Note, user modules could still reference these modules
+	 * but since the dict's are cleared their members wont be accessible */
+	
+	PyObject *modules= PySys_GetObject((char *)"modules");
+	clearModule(modules, "Expression");
+	clearModule(modules, "CValue");	
+	clearModule(modules, "PhysicsConstraints");	
+	clearModule(modules, "GameLogic");	
+	clearModule(modules, "Rasterizer");	
+	clearModule(modules, "GameKeys");	
+	clearModule(modules, "VideoTexture");
+	clearModule(modules, "Mathutils");	
+	clearModule(modules, "Geometry");	
+	clearModule(modules, "BGL");	
+	PyErr_Clear(); // incase some of these were alredy removed.
+#endif
+	
+	/* clear user defined modules, arg '1' for clear external py modules too */
+	bpy_text_clear_modules(1);
+}
 
+void exitGamePythonScripting()
+{
+	clearGameModules();
+	restorePySysPath(); /* get back the original sys.path and clear the backup */
+	bpy_import_main_set(NULL);
+	PyObjectPlus::ClearDeprecationWarning();
+}
+
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef Rasterizer_module_def = {
+	{}, /* m_base */
+	"Rasterizer",  /* m_name */
+	Rasterizer_module_documentation,  /* m_doc */
+	0,  /* m_size */
+	rasterizer_methods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
 
 PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
 {
@@ -1303,16 +1815,33 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
 
   PyObject* m;
   PyObject* d;
-
-  // Create the module and add the functions
-  m = Py_InitModule4("Rasterizer", rasterizer_methods,
+  PyObject* item;
+
+	/* Use existing module where possible
+	 * be careful not to init any runtime vars after this */
+	m = PyImport_ImportModule( "Rasterizer" );
+	if(m) {
+		Py_DECREF(m);
+		return m;
+	}
+	else {
+		PyErr_Clear();
+	
+		// Create the module and add the functions
+#if (PY_VERSION_HEX >= 0x03000000)
+		m = PyModule_Create(&Rasterizer_module_def);
+#else
+		m = Py_InitModule4("Rasterizer", rasterizer_methods,
 		     Rasterizer_module_documentation,
 		     (PyObject*)NULL,PYTHON_API_VERSION);
+#endif
+	}
 
   // Add some symbolic constants to the module
   d = PyModule_GetDict(m);
   ErrorObject = PyString_FromString("Rasterizer.error");
   PyDict_SetItemString(d, "error", ErrorObject);
+  Py_DECREF(ErrorObject);
 
   /* needed for get/setMaterialType */
   KX_MACRO_addTypesToDict(d, KX_TEXFACE_MATERIAL, KX_TEXFACE_MATERIAL);
@@ -1341,7 +1870,7 @@ static char GameKeys_module_documentation[] =
 ;
 
 static char gPyEventToString_doc[] =
-"Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
+"EventToString(event) - Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
 ;
 
 static PyObject* gPyEventToString(PyObject*, PyObject* value)
@@ -1356,7 +1885,12 @@ static PyObject* gPyEventToString(PyObject*, PyObject* value)
 	dict = PyModule_GetDict(mod);
 	
 	while (PyDict_Next(dict, &pos, &key, &val)) {
+#if (PY_VERSION_HEX >= 0x03000000)
+		if (PyObject_RichCompareBool(value, val, Py_EQ)) {
+#else
 		if (PyObject_Compare(value, val)==0) {
+#endif
+			
 			ret = key;
 			break;
 		}
@@ -1364,28 +1898,78 @@ static PyObject* gPyEventToString(PyObject*, PyObject* value)
 	
 	PyErr_Clear(); // incase there was an error clearing
 	Py_DECREF(mod);
-	if (!ret)	PyErr_SetString(PyExc_ValueError, "expected a valid int keyboard event");
+	if (!ret)	PyErr_SetString(PyExc_ValueError, "GameKeys.EventToString(int): expected a valid int keyboard event");
 	else		Py_INCREF(ret);
 	
 	return ret;
 }
 
+static char gPyEventToCharacter_doc[] =
+"EventToCharacter(event, is_shift) - Take a valid event from the GameKeys module or Keyboard Sensor and return a character"
+;
+
+static PyObject* gPyEventToCharacter(PyObject*, PyObject* args)
+{
+	int event, shift;
+	if (!PyArg_ParseTuple(args,"ii:EventToCharacter", &event, &shift))
+		return NULL;
+	
+	if(IsPrintable(event)) {
+		char ch[2] = {'\0', '\0'};
+		ch[0] = ToCharacter(event, (bool)shift);
+		return PyString_FromString(ch);
+	}
+	else {
+		return PyString_FromString("");
+	}
+}
+
+
 static struct PyMethodDef gamekeys_methods[] = {
+	{"EventToCharacter", (PyCFunction)gPyEventToCharacter, METH_VARARGS, (PY_METHODCHAR)gPyEventToCharacter_doc},
 	{"EventToString", (PyCFunction)gPyEventToString, METH_O, (PY_METHODCHAR)gPyEventToString_doc},
 	{ NULL, (PyCFunction) NULL, 0, NULL }
 };
 
 
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef GameKeys_module_def = {
+	{}, /* m_base */
+	"GameKeys",  /* m_name */
+	GameKeys_module_documentation,  /* m_doc */
+	0,  /* m_size */
+	gamekeys_methods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
 
 PyObject* initGameKeys()
 {
 	PyObject* m;
 	PyObject* d;
-
-	// Create the module and add the functions
-	m = Py_InitModule4("GameKeys", gamekeys_methods,
+	PyObject* item;
+	
+	/* Use existing module where possible */
+	m = PyImport_ImportModule( "GameKeys" );
+	if(m) {
+		Py_DECREF(m);
+		return m;
+	}
+	else {
+		PyErr_Clear();
+	
+		// Create the module and add the functions
+#if (PY_VERSION_HEX >= 0x03000000)
+		m = PyModule_Create(&GameKeys_module_def);
+#else
+		m = Py_InitModule4("GameKeys", gamekeys_methods,
 					   GameKeys_module_documentation,
 					   (PyObject*)NULL,PYTHON_API_VERSION);
+#endif
+	}
 
 	// Add some symbolic constants to the module
 	d = PyModule_GetDict(m);
@@ -1505,7 +2089,6 @@ PyObject* initGameKeys()
 	KX_MACRO_addTypesToDict(d, PAGEDOWNKEY, SCA_IInputDevice::KX_PAGEDOWNKEY);
 	KX_MACRO_addTypesToDict(d, ENDKEY, SCA_IInputDevice::KX_ENDKEY);
 
-
 	// Check for errors
 	if (PyErr_Occurred())
     {
@@ -1515,11 +2098,27 @@ PyObject* initGameKeys()
 	return d;
 }
 
+#if PY_VERSION_HEX < 0x03000000
 PyObject* initMathutils()
 {
 	return Mathutils_Init("Mathutils"); // Use as a top level module in BGE
 }
 
+PyObject* initGeometry()
+{
+	return Geometry_Init("Geometry"); // Use as a top level module in BGE
+}
+
+PyObject* initBGL()
+{
+	return BGL_Init("BGL"); // Use as a top level module in BGE
+}
+#else // TODO Py3k conversion
+PyObject* initMathutils() {Py_INCREF(Py_None);return Py_None;}
+PyObject* initGeometry() {Py_INCREF(Py_None);return Py_None;}
+PyObject* initBGL() {Py_INCREF(Py_None);return Py_None;}
+#endif
+
 void KX_SetActiveScene(class KX_Scene* scene)
 {
 	gp_KetsjiScene = scene;
diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h
index 57ee0be9400310c001acfd80a69e405311681260..3253ac8f711888960c3341fce8ec575fe05e30f5 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.h
+++ b/source/gameengine/Ketsji/KX_PythonInit.h
@@ -43,11 +43,13 @@ extern bool gUseVisibilityTemp;
 PyObject*	initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene* ketsjiscene);
 PyObject*	initGameKeys();
 PyObject*	initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas);
-PyObject*	initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level);
+PyObject*	initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie, int argc, char** argv);
 PyObject*	initMathutils();
+PyObject*	initGeometry();
+PyObject*	initBGL();
 PyObject*	initVideoTexture(void); 
 void		exitGamePlayerPythonScripting();
-PyObject*	initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level);
+PyObject*	initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie);
 void		exitGamePythonScripting();
 
 void		setGamePythonPath(char *path);
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
index e2ff4ced12256f5e9c54c922b65395964d1b8329..cd21663f41d7df244dcd294be353a51cd78cc65e 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
@@ -1,5 +1,5 @@
 /**
- * $Id: PyObjectPlus.h 19511 2009-04-03 02:16:56Z campbellbarton $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -80,9 +80,11 @@
 #include "KX_SCA_DynamicActuator.h"
 #include "KX_SoundActuator.h"
 #include "KX_TouchSensor.h"
+#include "KX_VisibilityActuator.h"
 #include "SCA_PropertySensor.h"
 #include "SCA_PythonController.h"
 #include "SCA_RandomActuator.h"
+#include "SCA_IController.h"
 
 
 void initPyObjectPlusType(PyTypeObject **parents)
@@ -97,7 +99,7 @@ void initPyObjectPlusType(PyTypeObject **parents)
 		}
 
 #if 0
-		PyObject_Print((PyObject *)parents[i], stderr, 0);
+		PyObject_Print(reinterpret_cast<PyObject *>parents[i], stderr, 0);
 		fprintf(stderr, "\n");
 		PyObject_Print(parents[i]->tp_dict, stderr, 0);
 		fprintf(stderr, "\n\n");
@@ -116,7 +118,7 @@ void initPyObjectPlusType(PyTypeObject **parents)
 		 dict= parents[i]->tp_dict;
 
 #if 1
-		PyObject_Print((PyObject *)parents[i], stderr, 0);
+		PyObject_Print(reinterpret_cast<PyObject *>(parents[i]), stderr, 0);
 		fprintf(stderr, "\n");
 		PyObject_Print(parents[i]->tp_dict, stderr, 0);
 		fprintf(stderr, "\n\n");
@@ -128,6 +130,26 @@ void initPyObjectPlusType(PyTypeObject **parents)
 
 
 
+static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *attributes)
+{
+	PyAttributeDef *attr;
+	PyObject *item;
+	
+	PyType_Ready(tp);
+	PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast<PyObject *>(tp));
+	
+	/* store attr defs in the tp_dict for to avoid string lookups */
+	for(attr= attributes; attr->m_name; attr++) {
+		item= PyCObject_FromVoidPtr(attr, NULL);
+		PyDict_SetItemString(tp->tp_dict, attr->m_name, item);
+		Py_DECREF(item);
+	}
+	
+}
+
+
+#define PyType_Ready_Attr(d, n)   PyType_Ready_ADD(d, &n::Type, n::Attributes)
+
 void initPyTypes(void)
 {
 	
@@ -137,68 +159,74 @@ void initPyTypes(void)
 */
 
 	/* For now just do PyType_Ready */
-
-	PyType_Ready(&BL_ActionActuator::Type);
-	PyType_Ready(&BL_Shader::Type);
-	PyType_Ready(&BL_ShapeActionActuator::Type);
-	PyType_Ready(&CListValue::Type);
-	PyType_Ready(&CValue::Type);
-	PyType_Ready(&KX_BlenderMaterial::Type);
-	PyType_Ready(&KX_CDActuator::Type);
-	PyType_Ready(&KX_Camera::Type);
-	PyType_Ready(&KX_CameraActuator::Type);
-	PyType_Ready(&KX_ConstraintActuator::Type);
-	PyType_Ready(&KX_ConstraintWrapper::Type);
-	PyType_Ready(&KX_GameActuator::Type);
-	PyType_Ready(&KX_GameObject::Type);
-	PyType_Ready(&KX_IpoActuator::Type);
-	PyType_Ready(&KX_LightObject::Type);
-	PyType_Ready(&KX_MeshProxy::Type);
-	PyType_Ready(&KX_MouseFocusSensor::Type);
-	PyType_Ready(&KX_NearSensor::Type);
-	PyType_Ready(&KX_NetworkMessageActuator::Type);
-	PyType_Ready(&KX_NetworkMessageSensor::Type);
-	PyType_Ready(&KX_ObjectActuator::Type);
-	PyType_Ready(&KX_ParentActuator::Type);
-	PyType_Ready(&KX_PhysicsObjectWrapper::Type);
-	PyType_Ready(&KX_PolyProxy::Type);
-	PyType_Ready(&KX_PolygonMaterial::Type);
-	PyType_Ready(&KX_RadarSensor::Type);
-	PyType_Ready(&KX_RaySensor::Type);
-	PyType_Ready(&KX_SCA_AddObjectActuator::Type);
-	PyType_Ready(&KX_SCA_DynamicActuator::Type);
-	PyType_Ready(&KX_SCA_EndObjectActuator::Type);
-	PyType_Ready(&KX_SCA_ReplaceMeshActuator::Type);
-	PyType_Ready(&KX_Scene::Type);
-	PyType_Ready(&KX_SceneActuator::Type);
-	PyType_Ready(&KX_SoundActuator::Type);
-	PyType_Ready(&KX_StateActuator::Type);
-	PyType_Ready(&KX_TouchSensor::Type);
-	PyType_Ready(&KX_TrackToActuator::Type);
-	PyType_Ready(&KX_VehicleWrapper::Type);
-	PyType_Ready(&KX_VertexProxy::Type);
-	PyType_Ready(&PyObjectPlus::Type);
-	PyType_Ready(&SCA_2DFilterActuator::Type);
-	PyType_Ready(&SCA_ANDController::Type);
-	PyType_Ready(&SCA_ActuatorSensor::Type);
-	PyType_Ready(&SCA_AlwaysSensor::Type);
-	PyType_Ready(&SCA_DelaySensor::Type);
-	PyType_Ready(&SCA_ILogicBrick::Type);
-	PyType_Ready(&SCA_IObject::Type);
-	PyType_Ready(&SCA_ISensor::Type);
-	PyType_Ready(&SCA_JoystickSensor::Type);
-	PyType_Ready(&SCA_KeyboardSensor::Type);
-	PyType_Ready(&SCA_MouseSensor::Type);
-	PyType_Ready(&SCA_NANDController::Type);
-	PyType_Ready(&SCA_NORController::Type);
-	PyType_Ready(&SCA_ORController::Type);
-	PyType_Ready(&SCA_PropertyActuator::Type);
-	PyType_Ready(&SCA_PropertySensor::Type);
-	PyType_Ready(&SCA_PythonController::Type);
-	PyType_Ready(&SCA_RandomActuator::Type);
-	PyType_Ready(&SCA_RandomSensor::Type);
-	PyType_Ready(&SCA_XNORController::Type);
-	PyType_Ready(&SCA_XORController::Type);
+	PyObject *mod= PyModule_New("GameTypes");
+	PyObject *dict= PyModule_GetDict(mod);
+	PyDict_SetItemString(PySys_GetObject((char *)"modules"), (char *)"GameTypes", mod);
+	Py_DECREF(mod);
+	
+	PyType_Ready_Attr(dict, BL_ActionActuator);
+	PyType_Ready_Attr(dict, BL_Shader);
+	PyType_Ready_Attr(dict, BL_ShapeActionActuator);
+	PyType_Ready_Attr(dict, CListValue);
+	PyType_Ready_Attr(dict, CValue);
+	PyType_Ready_Attr(dict, KX_BlenderMaterial);
+	PyType_Ready_Attr(dict, KX_CDActuator);
+	PyType_Ready_Attr(dict, KX_Camera);
+	PyType_Ready_Attr(dict, KX_CameraActuator);
+	PyType_Ready_Attr(dict, KX_ConstraintActuator);
+	PyType_Ready_Attr(dict, KX_ConstraintWrapper);
+	PyType_Ready_Attr(dict, KX_GameActuator);
+	PyType_Ready_Attr(dict, KX_GameObject);
+	PyType_Ready_Attr(dict, KX_IpoActuator);
+	PyType_Ready_Attr(dict, KX_LightObject);
+	PyType_Ready_Attr(dict, KX_MeshProxy);
+	PyType_Ready_Attr(dict, KX_MouseFocusSensor);
+	PyType_Ready_Attr(dict, KX_NearSensor);
+	PyType_Ready_Attr(dict, KX_NetworkMessageActuator);
+	PyType_Ready_Attr(dict, KX_NetworkMessageSensor);
+	PyType_Ready_Attr(dict, KX_ObjectActuator);
+	PyType_Ready_Attr(dict, KX_ParentActuator);
+	PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper);
+	PyType_Ready_Attr(dict, KX_PolyProxy);
+	PyType_Ready_Attr(dict, KX_PolygonMaterial);
+	PyType_Ready_Attr(dict, KX_RadarSensor);
+	PyType_Ready_Attr(dict, KX_RaySensor);
+	PyType_Ready_Attr(dict, KX_SCA_AddObjectActuator);
+	PyType_Ready_Attr(dict, KX_SCA_DynamicActuator);
+	PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator);
+	PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator);
+	PyType_Ready_Attr(dict, KX_Scene);
+	PyType_Ready_Attr(dict, KX_SceneActuator);
+	PyType_Ready_Attr(dict, KX_SoundActuator);
+	PyType_Ready_Attr(dict, KX_StateActuator);
+	PyType_Ready_Attr(dict, KX_TouchSensor);
+	PyType_Ready_Attr(dict, KX_TrackToActuator);
+	PyType_Ready_Attr(dict, KX_VehicleWrapper);
+	PyType_Ready_Attr(dict, KX_VertexProxy);
+	PyType_Ready_Attr(dict, KX_VisibilityActuator);
+	PyType_Ready_Attr(dict, PyObjectPlus);
+	PyType_Ready_Attr(dict, SCA_2DFilterActuator);
+	PyType_Ready_Attr(dict, SCA_ANDController);
+	PyType_Ready_Attr(dict, SCA_ActuatorSensor);
+	PyType_Ready_Attr(dict, SCA_AlwaysSensor);
+	PyType_Ready_Attr(dict, SCA_DelaySensor);
+	PyType_Ready_Attr(dict, SCA_ILogicBrick);
+	PyType_Ready_Attr(dict, SCA_IObject);
+	PyType_Ready_Attr(dict, SCA_ISensor);
+	PyType_Ready_Attr(dict, SCA_JoystickSensor);
+	PyType_Ready_Attr(dict, SCA_KeyboardSensor);
+	PyType_Ready_Attr(dict, SCA_MouseSensor);
+	PyType_Ready_Attr(dict, SCA_NANDController);
+	PyType_Ready_Attr(dict, SCA_NORController);
+	PyType_Ready_Attr(dict, SCA_ORController);
+	PyType_Ready_Attr(dict, SCA_PropertyActuator);
+	PyType_Ready_Attr(dict, SCA_PropertySensor);
+	PyType_Ready_Attr(dict, SCA_PythonController);
+	PyType_Ready_Attr(dict, SCA_RandomActuator);
+	PyType_Ready_Attr(dict, SCA_RandomSensor);
+	PyType_Ready_Attr(dict, SCA_XNORController);
+	PyType_Ready_Attr(dict, SCA_XORController);
+	PyType_Ready_Attr(dict, SCA_IController);
 }
 
 #endif
\ No newline at end of file
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.h b/source/gameengine/Ketsji/KX_PythonInitTypes.h
index b30f0334b6e30c383dd3f591d7b7ec38b66c2a29..6da79be930127612e0c3414dcefb291b137428c8 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.h
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.h
@@ -1,5 +1,5 @@
 /**
- * $Id: PyObjectPlus.h 19511 2009-04-03 02:16:56Z campbellbarton $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cc8021fc2e4e2b9acb036efb615d711f9252bed2
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp
@@ -0,0 +1,382 @@
+/**
+ * $Id: 
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: none of this file.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * Readonly sequence wrapper for lookups on logic bricks
+ */
+
+
+#include "KX_PythonSeq.h"
+#include "KX_GameObject.h"
+#include "SCA_ISensor.h"
+#include "SCA_IController.h"
+#include "SCA_IActuator.h"
+
+
+PyObject *KX_PythonSeq_CreatePyObject( PyObject *base, short type )
+{
+	KX_PythonSeq *seq = PyObject_NEW( KX_PythonSeq, &KX_PythonSeq_Type);
+	seq->base = base;
+	Py_INCREF(base); /* so we can always access to check if its valid */
+	seq->type = type;
+	seq->iter = -1; /* init */
+	return (PyObject *)seq;
+ }
+ 
+ static void KX_PythonSeq_dealloc( KX_PythonSeq * self )
+{
+	Py_DECREF(self->base);
+	PyObject_DEL( self );
+}
+
+static Py_ssize_t KX_PythonSeq_len( PyObject * self )
+{
+	PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
+	 
+	if(self_plus==NULL) {
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+		return -1;
+	}
+	
+	switch(((KX_PythonSeq *)self)->type) {
+	case KX_PYGENSEQ_CONT_TYPE_SENSORS:
+		return ((SCA_IController *)self_plus)->GetLinkedSensors().size();
+	case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
+		return ((SCA_IController *)self_plus)->GetLinkedActuators().size();
+	case KX_PYGENSEQ_OB_TYPE_SENSORS:
+		return ((KX_GameObject *)self_plus)->GetSensors().size();
+	case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
+		return ((KX_GameObject *)self_plus)->GetControllers().size();
+	case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
+		return ((KX_GameObject *)self_plus)->GetActuators().size();
+	default:
+		/* Should never happen */
+		PyErr_SetString(PyExc_SystemError, "invalid type, internal error");
+		return -1;
+	}
+}
+
+static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index)
+{
+	PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
+	 
+	if(self_plus==NULL) {
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
+	switch(((KX_PythonSeq *)self)->type) {
+		case KX_PYGENSEQ_CONT_TYPE_SENSORS:
+		{
+			vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors();
+			if(index<0) index += linkedsensors.size();
+			if(index<0 || index>= linkedsensors.size()) {
+				PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+				return NULL;
+			}
+			return linkedsensors[index]->GetProxy();
+		}
+		case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
+		{
+			vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators();
+			if(index<0) index += linkedactuators.size();
+			if(index<0 || index>= linkedactuators.size()) {
+				PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+				return NULL;
+			}
+			return linkedactuators[index]->GetProxy();
+		}
+		case KX_PYGENSEQ_OB_TYPE_SENSORS:
+		{
+			SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors();
+			if(index<0) index += linkedsensors.size();
+			if(index<0 || index>= linkedsensors.size()) {
+				PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+				return NULL;
+			}
+			return linkedsensors[index]->GetProxy();
+		}
+		case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
+		{
+			SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers();
+			if(index<0) index += linkedcontrollers.size();
+			if(index<0 || index>= linkedcontrollers.size()) {
+				PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+				return NULL;
+			}
+			return linkedcontrollers[index]->GetProxy();
+		}
+		case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
+		{
+			SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators();
+			if(index<0) index += linkedactuators.size();
+			if(index<0 || index>= linkedactuators.size()) {
+				PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+				return NULL;
+			}
+			return linkedactuators[index]->GetProxy();
+		}
+	}
+	
+	PyErr_SetString(PyExc_SystemError, "invalid sequence type, this is a bug");
+	return NULL;
+}
+
+
+static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key)
+{
+	PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
+	char *name = NULL;
+	
+	if(self_plus==NULL) {
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
+	if (PyInt_Check(key)) {
+		return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key ));
+	} else if ( PyString_Check(key) ) {
+		name = PyString_AsString( key );
+	} else {
+		PyErr_SetString( PyExc_TypeError, "expected a string or an index" );
+		return NULL;
+	}
+	
+	switch(((KX_PythonSeq *)self)->type) {
+		case KX_PYGENSEQ_CONT_TYPE_SENSORS:
+		{
+			vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors();
+			SCA_ISensor* sensor;
+			for (unsigned int index=0;index<linkedsensors.size();index++) {
+				sensor = linkedsensors[index];
+				if (sensor->GetName() == name)
+					return sensor->GetProxy();
+			}
+			break;
+		}
+		case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
+		{
+			vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators();
+			SCA_IActuator* actuator;
+			for (unsigned int index=0;index<linkedactuators.size();index++) {
+				actuator = linkedactuators[index];
+				if (actuator->GetName() == name)
+					return actuator->GetProxy();
+			}
+			break;
+		}
+		case KX_PYGENSEQ_OB_TYPE_SENSORS:
+		{
+			SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors();
+			SCA_ISensor *sensor;
+			for (unsigned int index=0;index<linkedsensors.size();index++) {
+				sensor= linkedsensors[index];
+				if (sensor->GetName() == name)
+					return sensor->GetProxy();
+			}
+			break;
+		}
+		case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
+		{
+			SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers();
+			SCA_IController *controller;
+			for (unsigned int index=0;index<linkedcontrollers.size();index++) {
+				controller= linkedcontrollers[index];
+				if (controller->GetName() == name)
+					return controller->GetProxy();
+			}
+			break;
+		}
+		case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
+		{
+			SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators();
+			SCA_IActuator *actuator;
+			for (unsigned int index=0;index<linkedactuators.size();index++) {
+				actuator= linkedactuators[index];
+				if (actuator->GetName() == name)
+					return actuator->GetProxy();
+			}
+			break;
+		}
+	}
+	
+	PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name);
+	return NULL;
+}
+
+static PyMappingMethods KX_PythonSeq_as_mapping = {
+	KX_PythonSeq_len,	/* mp_length */
+	KX_PythonSeq_subscript,	/* mp_subscript */
+	0,	/* mp_ass_subscript */
+};
+
+
+/*
+ * Initialize the interator index
+ */
+
+static PyObject *KX_PythonSeq_getIter(KX_PythonSeq *self)
+{
+	if(BGE_PROXY_REF(self->base)==NULL) {
+		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+		return NULL;
+	}
+	
+	/* create a new iterator if were alredy using this one */
+	if (self->iter == -1) {
+		self->iter = 0;
+		Py_INCREF(self);
+		return (PyObject *)self;
+	} else {
+		return KX_PythonSeq_CreatePyObject(self->base, self->type);
+ 	}
+ }
+ 
+
+/*
+ * Return next KX_PythonSeq iter.
+ */
+ 
+static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self)
+{
+	PyObject *object = KX_PythonSeq_getIndex((PyObject *)self, self->iter);
+	
+	self->iter++;
+	if( object==NULL ) {
+		self->iter= -1; /* for reuse */
+		PyErr_SetString(PyExc_StopIteration,	"iterator at end");
+	}
+	return object; /* can be NULL for end of iterator */
+}
+
+
+static int KX_PythonSeq_compare( KX_PythonSeq * a, KX_PythonSeq * b ) /* TODO - python3.x wants richcmp */
+{
+	return ( a->type == b->type && a->base == b->base) ? 0 : -1;	
+}
+
+/*
+ * repr function
+ * convert to a list and get its string value
+ */
+static PyObject *KX_PythonSeq_repr( KX_PythonSeq * self )
+{
+	PyObject *list = PySequence_List((PyObject *)self);
+	PyObject *repr = PyObject_Repr(list);
+	Py_DECREF(list);
+	return repr;
+}
+
+
+/*****************************************************************************/
+/* Python KX_PythonSeq_Type structure definition:                               */
+/*****************************************************************************/
+PyTypeObject KX_PythonSeq_Type = {
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
+	/*  For printing, in format "<module>.<name>" */
+	"KX_PythonSeq",           /* char *tp_name; */
+	sizeof( KX_PythonSeq ),       /* int tp_basicsize; */
+	0,                          /* tp_itemsize;  For allocation */
+
+	/* Methods to implement standard operations */
+
+	( destructor ) KX_PythonSeq_dealloc, /* destructor tp_dealloc; */
+	NULL,                       /* printfunc tp_print; */
+	NULL,                       /* getattrfunc tp_getattr; */
+	NULL,                       /* setattrfunc tp_setattr; */
+	( cmpfunc ) KX_PythonSeq_compare, /* cmpfunc tp_compare; */
+	( reprfunc ) KX_PythonSeq_repr,   /* reprfunc tp_repr; */
+
+	/* Method suites for standard classes */
+
+	NULL,                       /* PyNumberMethods *tp_as_number; */
+	NULL,	    /* PySequenceMethods *tp_as_sequence; */
+	&KX_PythonSeq_as_mapping,                       /* PyMappingMethods *tp_as_mapping; */
+
+	/* More standard operations (here for binary compatibility) */
+
+	NULL,                       /* hashfunc tp_hash; */
+	NULL,                       /* ternaryfunc tp_call; */
+	NULL,                       /* reprfunc tp_str; */
+	NULL,                       /* getattrofunc tp_getattro; */
+	NULL,                       /* setattrofunc tp_setattro; */
+
+	/* Functions to access object as input/output buffer */
+	NULL,                       /* PyBufferProcs *tp_as_buffer; */
+
+  /*** Flags to define presence of optional/expanded features ***/
+	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
+
+	NULL,                       /*  char *tp_doc;  Documentation string */
+  /*** Assigned meaning in release 2.0 ***/
+	/* call function for all accessible objects */
+	NULL,                       /* traverseproc tp_traverse; */
+
+	/* delete references to contained objects */
+	NULL,                       /* inquiry tp_clear; */
+
+  /***  Assigned meaning in release 2.1 ***/
+  /*** rich comparisons ***/
+	NULL,                       /* richcmpfunc tp_richcompare; */
+
+  /***  weak reference enabler ***/
+	0,                          /* long tp_weaklistoffset; */
+
+  /*** Added in release 2.2 ***/
+	/*   Iterators */
+	( getiterfunc) KX_PythonSeq_getIter, /* getiterfunc tp_iter; */
+	( iternextfunc ) KX_PythonSeq_nextIter, /* iternextfunc tp_iternext; */
+
+  /*** Attribute descriptor and subclassing stuff ***/
+	NULL,       /* struct PyMethodDef *tp_methods; */
+	NULL,                       /* struct PyMemberDef *tp_members; */
+	NULL,       /* struct PyGetSetDef *tp_getset; */
+	NULL,                       /* struct _typeobject *tp_base; */
+	NULL,                       /* PyObject *tp_dict; */
+	NULL,                       /* descrgetfunc tp_descr_get; */
+	NULL,                       /* descrsetfunc tp_descr_set; */
+	0,                          /* long tp_dictoffset; */
+	NULL,                       /* initproc tp_init; */
+	NULL,                       /* allocfunc tp_alloc; */
+	NULL,                       /* newfunc tp_new; */
+	/*  Low-level free-memory routine */
+	NULL,                       /* freefunc tp_free;  */
+	/* For PyObject_IS_GC */
+	NULL,                       /* inquiry tp_is_gc;  */
+	NULL,                       /* PyObject *tp_bases; */
+	/* method resolution order */
+	NULL,                       /* PyObject *tp_mro;  */
+	NULL,                       /* PyObject *tp_cache; */
+	NULL,                       /* PyObject *tp_subclasses; */
+	NULL,                       /* PyObject *tp_weaklist; */
+	NULL
+};
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.h b/source/gameengine/Ketsji/KX_PythonSeq.h
new file mode 100644
index 0000000000000000000000000000000000000000..15a016224a938a9e74794c9118d5c2d43310736a
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PythonSeq.h
@@ -0,0 +1,60 @@
+/**
+ * $Id: 
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * Readonly sequence wrapper for lookups on logic bricks
+ */
+ 
+#ifndef _adr_py_seq_h_				// only process once,
+#define _adr_py_seq_h_				// even if multiply included
+
+#include "PyObjectPlus.h"
+
+// -------------------------
+enum KX_PYGENSEQ_TYPE {
+	KX_PYGENSEQ_CONT_TYPE_SENSORS,
+	KX_PYGENSEQ_CONT_TYPE_ACTUATORS,
+	KX_PYGENSEQ_OB_TYPE_SENSORS,
+	KX_PYGENSEQ_OB_TYPE_CONTROLLERS,
+	KX_PYGENSEQ_OB_TYPE_ACTUATORS
+};
+
+/* The Main PyType Object defined in Main.c */
+extern PyTypeObject KX_PythonSeq_Type;
+
+#define BPy_KX_PythonSeq_Check(v) \
+    ((v)->ob_type == &KX_PythonSeq_Type)
+
+typedef struct {
+	PyObject_VAR_HEAD
+	PyObject *base;
+	short type;
+	short iter;
+} KX_PythonSeq;
+
+PyObject *KX_PythonSeq_CreatePyObject(PyObject *base, short type);
+
+#endif // _adr_py_seq_h_
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp
index 77cde79b54db4c68a2f5916031ef1f3c1bd54065..4532224a81e1980007dcbd9e570d4cb56dbed65a 100644
--- a/source/gameengine/Ketsji/KX_RadarSensor.cpp
+++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp
@@ -80,33 +80,15 @@ KX_RadarSensor::~KX_RadarSensor()
 CValue* KX_RadarSensor::GetReplica()
 {
 	KX_RadarSensor* replica = new KX_RadarSensor(*this);
-	replica->m_colliders = new CListValue();
-	replica->Init();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-	
-	replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::RADAR);
-	
-	if (replica->m_physCtrl)
-	{
-		replica->m_physCtrl = replica->m_physCtrl->GetReplica();
-		if (replica->m_physCtrl)
-		{
-			replica->m_physCtrl->setNewClientInfo(replica->m_client_info);
-		}
-	}
-
-	//todo: make sure replication works fine!
-	//>m_sumoObj = new SM_Object(DT_NewCone(m_coneradius, m_coneheight),NULL,NULL,NULL);
-	//replica->m_sumoObj->setMargin(m_Margin);
-	//replica->m_sumoObj->setClientObject(replica->m_client_info);
-	
-	((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL);
-	replica->SynchronizeTransform();
-	
+	replica->ProcessReplica();
 	return replica;
 }
 
+void KX_RadarSensor::ProcessReplica()
+{
+	KX_NearSensor::ProcessReplica();
+	m_client_info->m_type = KX_ClientObjectInfo::RADAR;
+}
 
 /**
  *	Transforms the collision object. A cone is not correctly centered
@@ -206,14 +188,14 @@ const char KX_RadarSensor::GetConeOrigin_doc[] =
 "getConeOrigin()\n"
 "\tReturns the origin of the cone with which to test. The origin\n"
 "\tis in the middle of the cone.";
-PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self) {
+PyObject* KX_RadarSensor::PyGetConeOrigin() {
 	ShowDeprecationWarning("getConeOrigin()", "the coneOrigin property");
 
 	PyObject *retVal = PyList_New(3);
 	
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_origin[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_origin[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_origin[2]));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_cone_origin[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_cone_origin[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_cone_origin[2]));
 	
 	return retVal;
 }
@@ -222,14 +204,14 @@ PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self) {
 const char KX_RadarSensor::GetConeTarget_doc[] = 
 "getConeTarget()\n"
 "\tReturns the center of the bottom face of the cone with which to test.\n";
-PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self) {
+PyObject* KX_RadarSensor::PyGetConeTarget() {
 	ShowDeprecationWarning("getConeTarget()", "the coneTarget property");
 
 	PyObject *retVal = PyList_New(3);
 	
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_target[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_target[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_target[2]));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_cone_target[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_cone_target[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_cone_target[2]));
 	
 	return retVal;
 }
@@ -238,7 +220,7 @@ PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self) {
 const char KX_RadarSensor::GetConeHeight_doc[] = 
 "getConeHeight()\n"
 "\tReturns the height of the cone with which to test.\n";
-PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self) {
+PyObject* KX_RadarSensor::PyGetConeHeight() {
 											  
 	ShowDeprecationWarning("getConeHeight()", "the distance property");
 
@@ -250,12 +232,17 @@ PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self) {
 /* Python Integration Hooks                                                  */
 /* ------------------------------------------------------------------------- */
 PyTypeObject KX_RadarSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_RadarSensor",
-	sizeof(KX_RadarSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -293,6 +280,7 @@ PyMethodDef KX_RadarSensor::Methods[] = {
 PyAttributeDef KX_RadarSensor::Attributes[] = {
 	KX_PYATTRIBUTE_FLOAT_ARRAY_RO("coneOrigin", KX_RadarSensor, m_cone_origin, 3),
 	KX_PYATTRIBUTE_FLOAT_ARRAY_RO("coneTarget", KX_RadarSensor, m_cone_target, 3),
+	KX_PYATTRIBUTE_FLOAT_RO("distance", KX_RadarSensor, m_coneheight),
 	KX_PYATTRIBUTE_FLOAT_RW("angle", 0, 360, KX_RadarSensor, m_coneradius),
 	KX_PYATTRIBUTE_INT_RW("axis", 0, 5, true, KX_RadarSensor, m_axis),
 	{NULL} //Sentinel
@@ -300,18 +288,14 @@ PyAttributeDef KX_RadarSensor::Attributes[] = {
 
 PyObject* KX_RadarSensor::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
-
 	py_getattro_up(KX_NearSensor);
 }
 
+PyObject* KX_RadarSensor::py_getattro_dict() {
+	py_getattro_dict_up(KX_NearSensor);
+}
+
 int KX_RadarSensor::py_setattro(PyObject *attr, PyObject* value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-
-	return KX_NearSensor::py_setattro(attr, value);
+	py_setattro_up(KX_NearSensor);
 }
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h
index c3a941696ce940a93cd639b76ab107a6820a889b..b4268797f85e438caf5721bd388f8a919a6b819d 100644
--- a/source/gameengine/Ketsji/KX_RadarSensor.h
+++ b/source/gameengine/Ketsji/KX_RadarSensor.h
@@ -76,6 +76,7 @@ public:
 	virtual ~KX_RadarSensor();
 	virtual void SynchronizeTransform();
 	virtual CValue* GetReplica();
+	virtual void ProcessReplica();
 
 	/* --------------------------------------------------------------------- */
 	/* Python interface ---------------------------------------------------- */
@@ -90,6 +91,7 @@ public:
 	};
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject* value);
 
 	//Deprecated ----->
diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp
index 974d4b992a647443b8f3f2d5235f87d378db53bb..8c7612bf6630c8c7f8ff5dcf39a707cfedfe40d6 100644
--- a/source/gameengine/Ketsji/KX_RayCast.cpp
+++ b/source/gameengine/Ketsji/KX_RayCast.cpp
@@ -56,12 +56,15 @@ void KX_RayCast::reportHit(PHY_RayCastResult* result)
 
 bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback)
 {
+	if(physics_environment==NULL) return false; /* prevents crashing in some cases */
+	
 	// Loops over all physics objects between frompoint and topoint,
 	// calling callback.RayHit for each one.
 	//
 	// callback.RayHit should return true to stop looking, or false to continue.
 	//
 	// returns true if an object was found, false if not.
+	
 	MT_Point3 frompoint(_frompoint);
 	const MT_Vector3 todir( (topoint - frompoint).safe_normalized() );
 	MT_Point3 prevpoint(_frompoint+todir*(-1.f));
diff --git a/source/gameengine/Ketsji/KX_RayEventManager.cpp b/source/gameengine/Ketsji/KX_RayEventManager.cpp
index 1af29151adf654f11a1f462ac719f87c964ddf8f..50fa4f5e310044f40f2f68ccb6efa0b234d40c40 100644
--- a/source/gameengine/Ketsji/KX_RayEventManager.cpp
+++ b/source/gameengine/Ketsji/KX_RayEventManager.cpp
@@ -44,9 +44,10 @@ using namespace std;
 
 void KX_RayEventManager::NextFrame()
 {
-	for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+	SG_DList::iterator<SCA_ISensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
 	{
-		(*i)->Activate(m_logicmgr, NULL);
+		(*it)->Activate(m_logicmgr);
 	}
 }
 
diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp
index cdcb5d74f303266050633d65499fbc62b5bbaa92..fdde5fdcf7b580df729017f6f8cc701b1fe2598c 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.cpp
+++ b/source/gameengine/Ketsji/KX_RaySensor.cpp
@@ -88,8 +88,7 @@ KX_RaySensor::~KX_RaySensor()
 CValue* KX_RaySensor::GetReplica()
 {
 	KX_RaySensor* replica = new KX_RaySensor(*this);
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	replica->Init();
 
 	return replica;
@@ -179,7 +178,7 @@ bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo* client)
 	return true;
 }
 
-bool KX_RaySensor::Evaluate(CValue* event)
+bool KX_RaySensor::Evaluate()
 {
 	bool result = false;
 	bool reset = m_reset && m_level;
@@ -321,12 +320,17 @@ bool KX_RaySensor::Evaluate(CValue* event)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_RaySensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_RaySensor",
-	sizeof(KX_RaySensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -375,7 +379,7 @@ PyObject* KX_RaySensor::pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_
 {
 	KX_RaySensor* self = static_cast<KX_RaySensor*>(self_v);
 	if (self->m_hitObject)
-		return self->m_hitObject->AddRef();
+		return self->m_hitObject->GetProxy();
 
 	Py_RETURN_NONE;
 }
@@ -384,12 +388,12 @@ PyObject* KX_RaySensor::pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_
 const char KX_RaySensor::GetHitObject_doc[] = 
 "getHitObject()\n"
 "\tReturns the name of the object that was hit by this ray.\n";
-PyObject* KX_RaySensor::PyGetHitObject(PyObject* self)
+PyObject* KX_RaySensor::PyGetHitObject()
 {
 	ShowDeprecationWarning("getHitObject()", "the hitObject property");
 	if (m_hitObject)
 	{
-		return m_hitObject->AddRef();
+		return m_hitObject->GetProxy();
 	}
 	Py_RETURN_NONE;
 }
@@ -398,15 +402,15 @@ PyObject* KX_RaySensor::PyGetHitObject(PyObject* self)
 const char KX_RaySensor::GetHitPosition_doc[] = 
 "getHitPosition()\n"
 "\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n";
-PyObject* KX_RaySensor::PyGetHitPosition(PyObject* self)
+PyObject* KX_RaySensor::PyGetHitPosition()
 {
 	ShowDeprecationWarning("getHitPosition()", "the hitPosition property");
 
 	PyObject *retVal = PyList_New(3);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_hitPosition[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_hitPosition[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_hitPosition[2]));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_hitPosition[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_hitPosition[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_hitPosition[2]));
 
 	return retVal;
 }
@@ -414,15 +418,15 @@ PyObject* KX_RaySensor::PyGetHitPosition(PyObject* self)
 const char KX_RaySensor::GetRayDirection_doc[] = 
 "getRayDirection()\n"
 "\tReturns the direction from the ray (in worldcoordinates) .\n";
-PyObject* KX_RaySensor::PyGetRayDirection(PyObject* self)
+PyObject* KX_RaySensor::PyGetRayDirection()
 {
 	ShowDeprecationWarning("getRayDirection()", "the rayDirection property");
 
 	PyObject *retVal = PyList_New(3);
 	
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_rayDirection[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_rayDirection[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_rayDirection[2]));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_rayDirection[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_rayDirection[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_rayDirection[2]));
 
 	return retVal;
 }
@@ -430,15 +434,15 @@ PyObject* KX_RaySensor::PyGetRayDirection(PyObject* self)
 const char KX_RaySensor::GetHitNormal_doc[] = 
 "getHitNormal()\n"
 "\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n";
-PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self)
+PyObject* KX_RaySensor::PyGetHitNormal()
 {
 	ShowDeprecationWarning("getHitNormal()", "the hitNormal property");
 
 	PyObject *retVal = PyList_New(3);
 
-	PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_hitNormal[0]));
-	PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_hitNormal[1]));
-	PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_hitNormal[2]));
+	PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_hitNormal[0]));
+	PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_hitNormal[1]));
+	PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_hitNormal[2]));
 
 	return retVal;
 }
@@ -446,17 +450,15 @@ PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self)
 
 
 PyObject* KX_RaySensor::py_getattro(PyObject *attr) {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_ISensor);
 }
 
+PyObject* KX_RaySensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 int KX_RaySensor::py_setattro(PyObject *attr, PyObject *value) {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_ISensor::py_setattro(attr, value);
+	py_setattro_up(SCA_ISensor);
 }
 
-// <----- Deprecated
\ No newline at end of file
+// <----- Deprecated
diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h
index a5d7d15c60caa962e2d6b6b17120dafe79f9c456..9efb046742ffe1c390bb5df7909c792333d42a47 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.h
+++ b/source/gameengine/Ketsji/KX_RaySensor.h
@@ -67,7 +67,7 @@ public:
 	virtual ~KX_RaySensor();
 	virtual CValue* GetReplica();
 
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual bool IsPositiveTrigger();
 	virtual void Init();
 
@@ -87,6 +87,7 @@ public:
 
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 	
 	// Deprecated ----->
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
index 1dd642e0966f0deda5a9d203381a90a7e477574f..3c72eac3e62a42890bbba330896f1e5696e0060b 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -87,7 +87,7 @@ KX_SCA_AddObjectActuator::~KX_SCA_AddObjectActuator()
 	if (m_OriginalObject)
 		m_OriginalObject->UnregisterActuator(this);
 	if (m_lastCreatedObject)
-		m_lastCreatedObject->Release();
+		m_lastCreatedObject->UnregisterActuator(this);
 } 
 
 
@@ -125,7 +125,6 @@ CValue* KX_SCA_AddObjectActuator::GetReplica()
 
 	// this will copy properties and so on...
 	replica->ProcessReplica();
-	CValue::AddDataToReplica(replica);
 
 	return replica;
 }
@@ -146,6 +145,12 @@ bool KX_SCA_AddObjectActuator::UnlinkObject(SCA_IObject* clientobj)
 		m_OriginalObject = NULL;
 		return true;
 	}
+	if (clientobj == m_lastCreatedObject)
+	{
+		// this object is being deleted, we cannot continue to track it.
+		m_lastCreatedObject = NULL;
+		return true;
+	}
 	return false;
 }
 
@@ -167,12 +172,17 @@ void KX_SCA_AddObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_SCA_AddObjectActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_SCA_AddObjectActuator",
-	sizeof(KX_SCA_AddObjectActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -223,7 +233,7 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct K
 	if (!actuator->m_OriginalObject)	
 		Py_RETURN_NONE;
 	else
-		return actuator->m_OriginalObject->AddRef();
+		return actuator->m_OriginalObject->GetProxy();
 }
 
 int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -231,7 +241,7 @@ int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYAT
 	KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
 	KX_GameObject *gameobj;
 		
-	if (!ConvertPythonToGameObject(value, &gameobj, true))
+	if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SCA_AddObjectActuator"))
 		return 1; // ConvertPythonToGameObject sets the error
 		
 	if (actuator->m_OriginalObject != NULL)
@@ -251,24 +261,22 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, con
 	if (!actuator->m_lastCreatedObject)
 		Py_RETURN_NONE;
 	else
-		return actuator->m_lastCreatedObject->AddRef();
+		return actuator->m_lastCreatedObject->GetProxy();
 }
 
 
 PyObject* KX_SCA_AddObjectActuator::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_SCA_AddObjectActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_SCA_AddObjectActuator::py_setattro(PyObject *attr, PyObject* value) 
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 /* 1. setObject */
@@ -277,13 +285,13 @@ const char KX_SCA_AddObjectActuator::SetObject_doc[] =
 "\t- object: KX_GameObject, string or None\n"
 "\tSets the object that will be added. There has to be an object\n"
 "\tof this name. If not, this function does nothing.\n";
-PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self, PyObject* value)
+PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* value)
 {
 	KX_GameObject *gameobj;
 	
 	ShowDeprecationWarning("setObject()", "the object property");
 	
-	if (!ConvertPythonToGameObject(value, &gameobj, true))
+	if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_SCA_AddObjectActuator"))
 		return NULL; // ConvertPythonToGameObject sets the error
 	
 	if (m_OriginalObject != NULL)
@@ -306,7 +314,7 @@ const char KX_SCA_AddObjectActuator::SetTime_doc[] =
 "\tIf the duration is negative, it is set to 0.\n";
 
 
-PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, PyObject* value)
+PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* value)
 {
 	ShowDeprecationWarning("setTime()", "the time property");
 	int deltatime = PyInt_AsLong(value);
@@ -329,7 +337,7 @@ const char KX_SCA_AddObjectActuator::GetTime_doc[] =
 "\tReturns the lifetime of the object that will be added.\n";
 
 
-PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self)
+PyObject* KX_SCA_AddObjectActuator::PyGetTime()
 {
 	ShowDeprecationWarning("getTime()", "the time property");
 	return PyInt_FromLong(m_timeProp);
@@ -341,22 +349,22 @@ const char KX_SCA_AddObjectActuator::GetObject_doc[] =
 "getObject(name_only = 1)\n"
 "name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
 "\tReturns the name of the object that will be added.\n";
-PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self, PyObject* args)
+PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* args)
 {
 	int ret_name_only = 1;
 	
 	ShowDeprecationWarning("getObject()", "the object property");
 	
-	if (!PyArg_ParseTuple(args, "|i", &ret_name_only))
+	if (!PyArg_ParseTuple(args, "|i:getObject", &ret_name_only))
 		return NULL;
 	
 	if (!m_OriginalObject)
 		Py_RETURN_NONE;
 	
 	if (ret_name_only)
-		return PyString_FromString(m_OriginalObject->GetName());
+		return PyString_FromString(m_OriginalObject->GetName().ReadPtr());
 	else
-		return m_OriginalObject->AddRef();
+		return m_OriginalObject->GetProxy();
 }
 
 
@@ -367,7 +375,7 @@ const char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] =
 "\tReturns the linear velocity that will be assigned to \n"
 "\tthe created object.\n";
 
-PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self)
+PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity()
 {
 	ShowDeprecationWarning("getLinearVelocity()", "the linearVelocity property");
 	PyObject *retVal = PyList_New(3);
@@ -390,12 +398,12 @@ const char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] =
 "\t- local: bool\n"
 "\tAssign this velocity to the created object. \n";
 
-PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, PyObject* args)
+PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* args)
 {
 	ShowDeprecationWarning("setLinearVelocity()", "the linearVelocity property");
 	
 	float vecArg[3];
-	if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2]))
+	if (!PyArg_ParseTuple(args, "fff:setLinearVelocity", &vecArg[0], &vecArg[1], &vecArg[2]))
 		return NULL;
 
 	m_linear_velocity[0] = vecArg[0];
@@ -410,7 +418,7 @@ const char KX_SCA_AddObjectActuator::GetAngularVelocity_doc[] =
 "\tReturns the angular velocity that will be assigned to \n"
 "\tthe created object.\n";
 
-PyObject* KX_SCA_AddObjectActuator::PyGetAngularVelocity(PyObject* self)
+PyObject* KX_SCA_AddObjectActuator::PyGetAngularVelocity()
 {
 	ShowDeprecationWarning("getAngularVelocity()", "the angularVelocity property");
 	PyObject *retVal = PyList_New(3);
@@ -433,12 +441,12 @@ const char KX_SCA_AddObjectActuator::SetAngularVelocity_doc[] =
 "\t- local: bool\n"
 "\tAssign this angular velocity to the created object. \n";
 
-PyObject* KX_SCA_AddObjectActuator::PySetAngularVelocity(PyObject* self, PyObject* args)
+PyObject* KX_SCA_AddObjectActuator::PySetAngularVelocity(PyObject* args)
 {
 	ShowDeprecationWarning("setAngularVelocity()", "the angularVelocity property");
 	
 	float vecArg[3];
-	if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2]))
+	if (!PyArg_ParseTuple(args, "fff:setAngularVelocity", &vecArg[0], &vecArg[1], &vecArg[2]))
 		return NULL;
 
 	m_angular_velocity[0] = vecArg[0];
@@ -462,19 +470,27 @@ void	KX_SCA_AddObjectActuator::InstantAddObject()
 		// keep a copy of the last object, to allow python scripters to change it
 		if (m_lastCreatedObject)
 		{
-			//careful with destruction, it might still have outstanding collision callbacks
-			m_scene->DelayedReleaseObject(m_lastCreatedObject);
-			m_lastCreatedObject->Release();
+			//Let's not keep a reference to the object: it's bad, if the object is deleted
+			//this will force to keep a "zombie" in the game for no good reason.
+			//m_scene->DelayedReleaseObject(m_lastCreatedObject);
+			//m_lastCreatedObject->Release();
+
+			//Instead we use the registration mechanism
+			m_lastCreatedObject->UnregisterActuator(this);
+			m_lastCreatedObject = NULL;
 		}
 		
 		m_lastCreatedObject = replica;
-		m_lastCreatedObject->AddRef();
+		// no reference
+		//m_lastCreatedObject->AddRef();
+		// but registration
+		m_lastCreatedObject->RegisterActuator(this);
 		// finished using replica? then release it
 		replica->Release();
 	}
 }
 
-PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self)
+PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject()
 {
 	InstantAddObject();
 
@@ -489,7 +505,7 @@ const char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] =
 "\tReturn the last created object. \n";
 
 
-PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self)
+PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject()
 {
 	ShowDeprecationWarning("getLastCreatedObject()", "the objectLastCreated property");
 	SCA_IObject* result = this->GetLastCreatedObject();
@@ -498,8 +514,7 @@ PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self)
 	// it means the object has ended, The BGE python api crashes in many places if the object is returned.
 	if (result && (static_cast<KX_GameObject *>(result))->GetSGNode()) 
 	{
-		result->AddRef();
-		return result;
+		return result->GetProxy();
 	}
 	// don't return NULL to python anymore, it gives trouble in the scripts
 	Py_RETURN_NONE;
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
index 4ece5a6d83b16171990a8b071ac6f9475f834b2c..6746b7d1bc6e3d8716f5939d1799e9b4e243e749 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
@@ -111,6 +111,7 @@ public:
 	Update();
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject* value);
 
 		SCA_IObject*	
diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
index ae21209fc4e956519386d813b78c3aec7daeadc3..af5631b44032c2c4a898829740e0b09e58de7ece 100644
--- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
@@ -51,12 +51,17 @@
 	PyTypeObject 
 
 KX_SCA_DynamicActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_SCA_DynamicActuator",
-	sizeof(KX_SCA_DynamicActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -94,18 +99,16 @@ PyAttributeDef KX_SCA_DynamicActuator::Attributes[] = {
 
 PyObject* KX_SCA_DynamicActuator::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_SCA_DynamicActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_SCA_DynamicActuator::py_setattro(PyObject *attr, PyObject* value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 
@@ -122,7 +125,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation,
 	ShowDeprecationWarning("setOperation()", "the operation property");
 	int dyn_operation;
 	
-	if (!PyArg_ParseTuple(args, "i", &dyn_operation))
+	if (!PyArg_ParseTuple(args, "i:setOperation", &dyn_operation))
 	{
 		return NULL;	
 	}
@@ -217,10 +220,6 @@ CValue* KX_SCA_DynamicActuator::GetReplica()
 		return NULL;
 
 	replica->ProcessReplica();
-
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-
 	return replica;
 };
 
diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h
index 99855124bdb27536c15f4b71568b31eb1902baa0..4add707f8cddeafcddc37397335896b8e091b3d9 100644
--- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h
@@ -75,6 +75,7 @@ class KX_SCA_DynamicActuator : public SCA_IActuator
 
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	/* 1. setOperation */
diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
index 0db9e1c49305ba2c695b2f7e3095cd9ca30782c9..728254e7f48bc2d133494b6289ce324400dfd47a 100644
--- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
@@ -82,8 +82,6 @@ CValue* KX_SCA_EndObjectActuator::GetReplica()
 	if (replica == NULL) return NULL;
 
 	replica->ProcessReplica();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
 	return replica;
 };
 
@@ -94,12 +92,17 @@ CValue* KX_SCA_EndObjectActuator::GetReplica()
 /* ------------------------------------------------------------------------- */
 
 PyTypeObject KX_SCA_EndObjectActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_SCA_EndObjectActuator",
-	sizeof(KX_SCA_EndObjectActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -136,4 +139,8 @@ PyObject* KX_SCA_EndObjectActuator::py_getattro(PyObject *attr)
   py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_SCA_EndObjectActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 /* eof */
diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h
index 2940246f443bfa6a2288031eddc71d2bc2280cca..70d72f1f8da3c5065417b5e000fe330bb5fb98b0 100644
--- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h
@@ -65,6 +65,7 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+ 	virtual PyObject* py_getattro_dict();
 	
 }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */
 
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
index 0cac07b45856737ddcf61e6ce609ade41869c37d..730d1ed49e64bce5abaf9c9c01a1bd81da38fa00 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
@@ -53,12 +53,17 @@
 	PyTypeObject 
 
 KX_SCA_ReplaceMeshActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_SCA_ReplaceMeshActuator",
-	sizeof(KX_SCA_ReplaceMeshActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -96,18 +101,16 @@ PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = {
 
 PyObject* KX_SCA_ReplaceMeshActuator::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_SCA_ReplaceMeshActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_SCA_ReplaceMeshActuator::py_setattro(PyObject *attr, PyObject* value) 
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
@@ -116,28 +119,18 @@ PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct K
 	if (!actuator->m_mesh)
 		Py_RETURN_NONE;
 	KX_MeshProxy* meshproxy = new KX_MeshProxy(actuator->m_mesh);
-	return meshproxy;
+	return meshproxy->NewProxy(true);
 }
 
 int KX_SCA_ReplaceMeshActuator::pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
 	KX_SCA_ReplaceMeshActuator* actuator = static_cast<KX_SCA_ReplaceMeshActuator*>(self);
-	if (value == Py_None) {
-		actuator->m_mesh = NULL;
-	} else if (PyString_Check(value)) {
-		void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(PyString_AsString(value)));
-		if (mesh==NULL) {
-			PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist");
-			return 1;
-		}
-		actuator->m_mesh= (class RAS_MeshObject*)mesh;
-	} else if PyObject_TypeCheck(value, &KX_MeshProxy::Type) {
-		KX_MeshProxy* proxy = (KX_MeshProxy*)value;
-		actuator->m_mesh= proxy->GetMesh();
-	} else {
-		PyErr_SetString(PyExc_ValueError, "Expected the name of a mesh, a mesh proxy or None");
+	RAS_MeshObject* new_mesh;
+	
+	if (!ConvertPythonToMesh(value, &new_mesh, true, "actuator.mesh = value: KX_SCA_ReplaceMeshActuator"))
 		return 1;
-	}
+	
+	actuator->m_mesh = new_mesh;
 	return 0;
 }
 
@@ -147,26 +140,15 @@ const char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] =
 	"\t- name: string or None\n"
 	"\tSet the mesh that will be substituted for the current one.\n";
 
-PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, PyObject* value)
+PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* value)
 {
 	ShowDeprecationWarning("setMesh()", "the mesh property");
-	if (value == Py_None) {
-		m_mesh = NULL;
-	} else {
-		char* meshname = PyString_AsString(value);
-		if (!meshname) {
-			PyErr_SetString(PyExc_ValueError, "Expected the name of a mesh or None");
-			return NULL;
-		}
-		void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname));
-		
-		if (mesh==NULL) {
-			PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist");
-			return NULL;
-		}
-		m_mesh= (class RAS_MeshObject*)mesh;
-	}
+	RAS_MeshObject* new_mesh;
+	
+	if (!ConvertPythonToMesh(value, &new_mesh, true, "actuator.mesh = value: KX_SCA_ReplaceMeshActuator"))
+		return NULL;
 	
+	m_mesh = new_mesh;
 	Py_RETURN_NONE;
 }
 
@@ -240,9 +222,6 @@ CValue* KX_SCA_ReplaceMeshActuator::GetReplica()
 
 	replica->ProcessReplica();
 
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-
 	return replica;
 };
 
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
index 7a18df2356d198cb84e9b457fa192696c589f8d4..0e7f7852701c0213dd756c78ef48023400dde0b0 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
@@ -72,6 +72,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator
 	void	InstantReplaceMesh();
 
 	virtual PyObject* py_getattro(PyObject *attr);
+ 	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject* value);
 
 	static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
index 151270cbd68fd2e662f9a6564b34a2fafd4f4191..cb933419c57a22cd50916d76150ccd1f0dac9c95 100644
--- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
+++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
@@ -57,7 +57,8 @@ New(Bone* bone
 KX_BoneParentRelation::
 UpdateChildCoordinates(
 	SG_Spatial * child,
-	const SG_Spatial * parent
+	const SG_Spatial * parent,
+	bool& parentUpdated	
 ){
 	MT_assert(child != NULL);
 	
@@ -67,6 +68,8 @@ UpdateChildCoordinates(
 	const MT_Vector3 & child_scale = child->GetLocalScale();
 	const MT_Point3 & child_pos = child->GetLocalPosition();
 	const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
+	// we don't know if the armature has been updated or not, assume yes
+	parentUpdated = true;
 
 	// the childs world locations which we will update.	
 	
@@ -122,7 +125,9 @@ UpdateChildCoordinates(
 	else {
 		child->SetWorldFromLocalTransform();
 	}
-	
+	child->ClearModified();
+	// this node must always be updated, so reschedule it for next time
+	child->ActivateRecheduleUpdateCallback();
 	return valid_parent_transform;
 }
 
diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
index 2a19d8a1784282743f8db849f4211fcf0f2a4195..c9baf2288557a0d057d6e162f6123208ca59e0b3 100644
--- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
+++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h
@@ -82,7 +82,8 @@ public :
 		bool
 	UpdateChildCoordinates(
 		SG_Spatial * child,
-		const SG_Spatial * parent
+		const SG_Spatial * parent,
+		bool& parentUpdated
 	);
 
 	/**
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
index 0729ec8a9025badf3d9f6a3202533ce41ad70865..c49b6d671a7b0be0e580689084adba331e59d69f 100644
--- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp
@@ -51,13 +51,20 @@ New(
 KX_NormalParentRelation::
 UpdateChildCoordinates(
 	SG_Spatial * child,
-	const SG_Spatial * parent
+	const SG_Spatial * parent,
+	bool& parentUpdated	
 ){
 	MT_assert(child != NULL);
 
+	if (!parentUpdated && !child->IsModified())
+		return false;
+
+	parentUpdated = true;
+
 	if (parent==NULL) { /* Simple case */
 		child->SetWorldFromLocalTransform();
-		return false;
+		child->ClearModified();
+		return true; //false;
 	}
 	else {
 		// the childs world locations which we will update.	
@@ -68,6 +75,7 @@ UpdateChildCoordinates(
 		child->SetWorldScale(p_world_scale * child->GetLocalScale());
 		child->SetWorldOrientation(p_world_rotation * child->GetLocalOrientation());
 		child->SetWorldPosition(p_world_pos + p_world_scale * (p_world_rotation * child->GetLocalPosition()));
+		child->ClearModified();
 		return true;
 	}
 }
@@ -112,10 +120,15 @@ New(
 KX_VertexParentRelation::
 UpdateChildCoordinates(
 	SG_Spatial * child,
-	const SG_Spatial * parent
+	const SG_Spatial * parent,
+	bool& parentUpdated	
 ){
 
 	MT_assert(child != NULL);
+
+	if (!parentUpdated && !child->IsModified())
+		return false;
+
 	child->SetWorldScale(child->GetLocalScale());
 	
 	if (parent)
@@ -124,7 +137,8 @@ UpdateChildCoordinates(
 		child->SetWorldPosition(child->GetLocalPosition());
 	
 	child->SetWorldOrientation(child->GetLocalOrientation());
-	return parent != NULL;
+	child->ClearModified();
+	return true; //parent != NULL;
 }
 
 /** 
@@ -172,10 +186,14 @@ New(
 KX_SlowParentRelation::
 UpdateChildCoordinates(
 	SG_Spatial * child,
-	const SG_Spatial * parent
+	const SG_Spatial * parent,
+	bool& parentUpdated	
 ){
 	MT_assert(child != NULL);
 
+	// the child will move even if the parent is not
+	parentUpdated = true;
+
 	const MT_Vector3 & child_scale = child->GetLocalScale();
 	const MT_Point3 & child_pos = child->GetLocalPosition();
 	const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation();
@@ -217,23 +235,12 @@ UpdateChildCoordinates(
 			// now 'interpolate' the normal coordinates with the last 
 			// world coordinates to get the new world coordinates.
 
-			// problem 1:
-			// The child world scale needs to be initialized in some way for this 
-			// to make sense
-			// problem 2:
-			// This is way of doing interpolation is nonsense
-
-			int i;
-
 			MT_Scalar weight = MT_Scalar(1)/(m_relax + 1);
-			for (i=0;i <3 ;i++) {
-				child_w_scale[i] = (m_relax * child_w_scale[i] + child_n_scale[i]) * weight;
-				child_w_pos[i] = (m_relax * child_w_pos[i] + child_n_pos[i]) * weight;
-				child_w_rotation[0][i] = (m_relax * child_w_rotation[0][i] + child_n_rotation[0][i]) * weight;
-				child_w_rotation[1][i] = (m_relax * child_w_rotation[1][i] + child_n_rotation[1][i]) * weight;
-				child_w_rotation[2][i] = (m_relax * child_w_rotation[2][i] + child_n_rotation[2][i]) * weight;
-			}
-			
+			child_w_scale = (m_relax * child_w_scale + child_n_scale) * weight;
+			child_w_pos = (m_relax * child_w_pos + child_n_pos) * weight;
+			// for rotation we must go through quaternion
+			MT_Quaternion child_w_quat = child_w_rotation.getRotation().slerp(child_n_rotation.getRotation(), weight);
+			child_w_rotation.setRotation(child_w_quat);
 			//FIXME: update physics controller.
 		} else {
 			child_w_scale = child_n_scale;
@@ -252,8 +259,11 @@ UpdateChildCoordinates(
 	child->SetWorldScale(child_w_scale);
 	child->SetWorldPosition(child_w_pos);
 	child->SetWorldOrientation(child_w_rotation);
+	child->ClearModified();
+	// this node must always be updated, so reschedule it for next time
+	child->ActivateRecheduleUpdateCallback();
 	
-	return parent != NULL;
+	return true; //parent != NULL;
 }
 
 /** 
diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
index faa650106c800284de1e3d492ed4906de8182435..d8fb9211f214ff4d74c97d7deeffafe6f757a92b 100644
--- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
+++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h
@@ -71,7 +71,8 @@ public :
 		bool
 	UpdateChildCoordinates(
 		SG_Spatial * child,
-		const SG_Spatial * parent
+		const SG_Spatial * parent,
+		bool& parentUpdated	
 	);
 
 	/** 
@@ -115,7 +116,8 @@ public :
 		bool
 	UpdateChildCoordinates(
 		SG_Spatial * child,
-		const SG_Spatial * parent
+		const SG_Spatial * parent,
+		bool& parentUpdated	
 	);
 
 	/** 
@@ -166,7 +168,8 @@ public :
 		bool
 	UpdateChildCoordinates(
 		SG_Spatial * child,
-		const SG_Spatial * parent
+		const SG_Spatial * parent,
+		bool& parentUpdated	
 	);
 
 	/** 
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 94ea234f1bf3ce56821b95daa06f0f29a13d0e93..84c6d374386fa24806167b44e18f4f26166063c4 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -34,7 +34,7 @@
 
 #include "KX_Scene.h"
 #include "MT_assert.h"
-
+#include "SND_Scene.h"
 #include "KX_KetsjiEngine.h"
 #include "KX_BlenderMaterial.h"
 #include "RAS_IPolygonMaterial.h"
@@ -76,8 +76,11 @@
 #include "NG_NetworkScene.h"
 #include "PHY_IPhysicsEnvironment.h"
 #include "KX_IPhysicsController.h"
+#include "PHY_IGraphicController.h"
 #include "KX_BlenderSceneConverter.h"
+#include "KX_MotionState.h"
 
+#include "BL_ModifierDeformer.h"
 #include "BL_ShapeDeformer.h"
 #include "BL_DeformableGameObject.h"
 
@@ -89,6 +92,8 @@
 #include "CcdPhysicsController.h"
 #endif
 
+#include "KX_Light.h"
+
 void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
 {
 	KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj);
@@ -106,7 +111,22 @@ void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene)
 	return NULL;
 };
 
-SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(KX_SceneReplicationFunc,KX_SceneDestructionFunc,KX_GameObject::UpdateTransformFunc);
+bool KX_Scene::KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene)
+{
+	return ((SG_Node*)node)->Schedule(((KX_Scene*)scene)->m_sghead);
+}
+
+bool KX_Scene::KX_ScenegraphRescheduleFunc(SG_IObject* node,void* gameobj,void* scene)
+{
+	return ((SG_Node*)node)->Reschedule(((KX_Scene*)scene)->m_sghead);
+}
+
+SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(
+	KX_SceneReplicationFunc,
+	KX_SceneDestructionFunc,
+	KX_GameObject::UpdateTransformFunc,
+	KX_Scene::KX_ScenegraphUpdateFunc,
+	KX_Scene::KX_ScenegraphRescheduleFunc);
 
 // temporarily var until there is a button in the userinterface
 // (defined in KX_PythonInit.cpp)
@@ -133,6 +153,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
 	m_suspendedtime = 0.0;
 	m_suspendeddelta = 0.0;
 
+	m_dbvt_culling = false;
+	m_dbvt_occlusion_res = 0;
 	m_activity_culling = false;
 	m_suspend = false;
 	m_isclearingZbuffer = true;
@@ -142,7 +164,6 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
 	m_lightlist= new CListValue();
 	m_inactivelist = new CListValue();
 	m_euthanasyobjects = new CListValue();
-	m_delayReleaseObjects = new CListValue();
 
 	m_logicmgr = new SCA_LogicManager();
 	
@@ -190,7 +211,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
 	m_canvasDesignWidth = 0;
 	m_canvasDesignHeight = 0;
 	
-	m_attrlist = PyDict_New(); /* new ref */
+	m_attr_dict = PyDict_New(); /* new ref */
 }
 
 
@@ -225,8 +246,6 @@ KX_Scene::~KX_Scene()
 
 	if (m_euthanasyobjects)
 		m_euthanasyobjects->Release();
-	if (m_delayReleaseObjects)
-		m_delayReleaseObjects->Release();
 
 	if (m_logicmgr)
 		delete m_logicmgr;
@@ -244,16 +263,10 @@ KX_Scene::~KX_Scene()
 	{
 		delete m_bucketmanager;
 	}
-	//Py_DECREF(m_attrlist);
-}
-
-void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
-{
-	m_projectionmat = pmat;
+	PyDict_Clear(m_attr_dict);
+	Py_DECREF(m_attr_dict);
 }
 
-
-
 RAS_BucketManager* KX_Scene::GetBucketManager()
 {
 	return m_bucketmanager;
@@ -401,12 +414,19 @@ void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gam
 	KX_GameObject* orgobj = (KX_GameObject*)gameobj;	
 	if (NewRemoveObject(orgobj) != 0)
 	{
-		// object is not yet deleted (this can happen when it hangs in an add object actuator
-		// last object created reference. It's a bad situation, don't know how to fix it exactly
-		// The least I can do, is remove the reference to the node in the object as the node
-		// will in any case be deleted. This ensures that the object will not try to use the node
-		// when it is finally deleted (see KX_GameObject destructor)
+		// object is not yet deleted because a reference is hanging somewhere.
+		// This should not happen anymore since we use proxy object for Python
+		// confident enough to put an assert?
+		//assert(false);
+		printf("Zombie object! name=%s\n", orgobj->GetName().ReadPtr());
 		orgobj->SetSGNode(NULL);
+		PHY_IGraphicController* ctrl = orgobj->GetGraphicController();
+		if (ctrl)
+		{
+			// a graphic controller is set, we must delete it as the node will be deleted
+			delete ctrl;
+			orgobj->SetGraphicController(NULL);
+		}
 	}
 	if (node)
 		delete node;
@@ -463,6 +483,8 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
 
 	// this is the list of object that are send to the graphics pipeline
 	m_objectlist->Add(newobj->AddRef());
+	if (newobj->IsLight())
+		m_lightlist->Add(newobj->AddRef());
 	newobj->AddMeshUser();
 
 	// logic cannot be replicated, until the whole hierarchy is replicated.
@@ -485,7 +507,14 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
 			replicanode->AddSGController(replicacontroller);
 		}
 	}
-	
+	// replicate graphic controller
+	if (orgobj->GetGraphicController())
+	{
+		PHY_IMotionState* motionstate = new KX_MotionState(newobj->GetSGNode());
+		PHY_IGraphicController* newctrl = orgobj->GetGraphicController()->GetReplica(motionstate);
+		newctrl->setNewClientInfo(newobj->getClientInfo());
+		newobj->SetGraphicController(newctrl);
+	}
 	return newobj;
 }
 
@@ -516,8 +545,9 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj)
 		vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators();
 
 		// disconnect the sensors and actuators
-		cont->UnlinkAllSensors();
-		cont->UnlinkAllActuators();
+		// do it directly on the list at this controller is not connected to anything at this stage
+		cont->GetLinkedSensors().clear();
+		cont->GetLinkedActuators().clear();
 		
 		// now relink each sensor
 		for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());its++)
@@ -695,16 +725,20 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
 		// set the replica's relative scale with the rootnode's scale
 		replica->NodeSetRelativeScale(newscale);
 
-		MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation();
-		replica->NodeSetLocalOrientation(newori);
-
+		MT_Point3 offset(group->dupli_ofs);
 		MT_Point3 newpos = groupobj->NodeGetWorldPosition() + 
-			newscale*(groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldPosition());
+			newscale*(groupobj->NodeGetWorldOrientation() * (gameobj->NodeGetWorldPosition()-offset));
 		replica->NodeSetLocalPosition(newpos);
-
+		// set the orientation after position for softbody!
+		MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation();
+		replica->NodeSetLocalOrientation(newori);
+		// update scenegraph for entire tree of children
 		replica->GetSGNode()->UpdateWorldData(0);
 		replica->GetSGNode()->SetBBox(gameobj->GetSGNode()->BBox());
 		replica->GetSGNode()->SetRadius(gameobj->GetSGNode()->Radius());
+		// we can now add the graphic controller to the physic engine
+		replica->ActivateGraphicController(true,true);
+
 		// done with replica
 		replica->Release();
 	}
@@ -724,6 +758,12 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
 		(*git)->Relink(&m_map_gameobject_to_replica);
 		// add the object in the layer of the parent
 		(*git)->SetLayer(groupobj->GetLayer());
+		// If the object was a light, we need to update it's RAS_LightObject as well
+		if ((*git)->IsLight())
+		{
+			KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
+			lightobj->GetLightData()->m_layer = groupobj->GetLayer();
+		}
 	}
 
 	// replicate crosslinks etc. between logic bricks
@@ -792,6 +832,26 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
 			replica->GetSGNode()->AddChild(childreplicanode);
 	}
 
+	// At this stage all the objects in the hierarchy have been duplicated,
+	// we can update the scenegraph, we need it for the duplication of logic
+	MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition();
+	replica->NodeSetLocalPosition(newpos);
+
+	MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation();
+	replica->NodeSetLocalOrientation(newori);
+	
+	// get the rootnode's scale
+	MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
+
+	// set the replica's relative scale with the rootnode's scale
+	replica->NodeSetRelativeScale(newscale);
+
+	replica->GetSGNode()->UpdateWorldData(0);
+	replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
+	replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
+	// the size is correct, we can add the graphic controller to the physic engine
+	replica->ActivateGraphicController(true,true);
+
 	// now replicate logic
 	vector<KX_GameObject*>::iterator git;
 	for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
@@ -806,6 +866,12 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
 		(*git)->Relink(&m_map_gameobject_to_replica);
 		// add the object in the layer of the parent
 		(*git)->SetLayer(parentobj->GetLayer());
+		// If the object was a light, we need to update it's RAS_LightObject as well
+		if ((*git)->IsLight())
+		{
+			KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
+			lightobj->GetLightData()->m_layer = parentobj->GetLayer();
+		}
 	}
 
 	// replicate crosslinks etc. between logic bricks
@@ -814,21 +880,6 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
 		ReplicateLogic((*git));
 	}
 	
-	MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition();
-	replica->NodeSetLocalPosition(newpos);
-
-	MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation();
-	replica->NodeSetLocalOrientation(newori);
-	
-	// get the rootnode's scale
-	MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
-
-	// set the replica's relative scale with the rootnode's scale
-	replica->NodeSetRelativeScale(newscale);
-
-	replica->GetSGNode()->UpdateWorldData(0);
-	replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
-	replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
 	// check if there are objects with dupligroup in the hierarchy
 	vector<KX_GameObject*> duplilist;
 	for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
@@ -853,7 +904,7 @@ void KX_Scene::RemoveObject(class CValue* gameobj)
 {
 	KX_GameObject* newobj = (KX_GameObject*) gameobj;
 
-	// first disconnect child from parent
+	// disconnect child from parent
 	SG_Node* node = newobj->GetSGNode();
 
 	if (node)
@@ -867,12 +918,6 @@ void KX_Scene::RemoveObject(class CValue* gameobj)
 	//newobj->SetSGNode(0);
 }
 
-void KX_Scene::DelayedReleaseObject(CValue* gameobj)
-{
-	m_delayReleaseObjects->Add(gameobj->AddRef());
-}
-
-
 void KX_Scene::DelayedRemoveObject(class CValue* gameobj)
 {
 	//KX_GameObject* newobj = (KX_GameObject*) gameobj;
@@ -889,6 +934,13 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
 	int ret;
 	KX_GameObject* newobj = (KX_GameObject*) gameobj;
 
+	/* Invalidate the python reference, since the object may exist in script lists
+	 * its possible that it wont be automatically invalidated, so do it manually here,
+	 * 
+	 * if for some reason the object is added back into the scene python can always get a new Proxy
+	 */
+	newobj->InvalidateProxy();
+
 	// keep the blender->game object association up to date
 	// note that all the replicas of an object will have the same
 	// blender object, that's why we need to check the game object
@@ -918,7 +970,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
 	for (SCA_ActuatorList::iterator ita = actuators.begin();
 		 !(ita==actuators.end());ita++)
 	{
-		m_logicmgr->RemoveDestroyedActuator(*ita);
+		m_logicmgr->RemoveActuator(*ita);
 	}
 	// the sensors/controllers/actuators must also be released, this is done in ~SCA_IObject
 
@@ -936,7 +988,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
 	
 	newobj->RemoveMeshes();
 	ret = 1;
-	if (m_lightlist->RemoveValue(newobj)) // TODO - use newobj->IsLight() test when its merged in from apricot. - Campbell
+	if (newobj->IsLight() && m_lightlist->RemoveValue(newobj))
 		ret = newobj->Release();
 	if (m_objectlist->RemoveValue(newobj))
 		ret = newobj->Release();
@@ -962,6 +1014,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
 	if (m_sceneConverter)
 		m_sceneConverter->UnregisterGameObject(newobj);
 	// return value will be 0 if the object is actually deleted (all reference gone)
+	
 	return ret;
 }
 
@@ -1001,6 +1054,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
 			Object* oldblendobj = static_cast<struct Object*>(m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName()));
 			Mesh* blendmesh = mesh->GetMesh();
 
+			bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(blendobj);
 			bool bHasShapeKey = blendmesh->key != NULL && blendmesh->key->type==KEY_RELATIVE;
 			bool bHasDvert = blendmesh->dvert != NULL;
 			bool bHasArmature = 
@@ -1016,10 +1070,37 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
 			
 			if (oldblendobj==NULL) {
 				std::cout << "warning: ReplaceMesh() new mesh is not used in an object from the current scene, you will get incorrect behavior" << std::endl;
-				bHasShapeKey= bHasDvert= bHasArmature= false;
+				bHasShapeKey= bHasDvert= bHasArmature=bHasModifier= false;
 			}
 			
-			if (bHasShapeKey)
+			if (bHasModifier)
+			{
+				BL_ModifierDeformer* modifierDeformer;
+				if (bHasShapeKey || bHasArmature)
+				{
+					modifierDeformer = new BL_ModifierDeformer(
+						newobj,
+						oldblendobj, blendobj,
+						static_cast<BL_SkinMeshObject*>(mesh),
+						true,
+						static_cast<BL_ArmatureObject*>( parentobj )
+					);
+					releaseParent= false;
+					modifierDeformer->LoadShapeDrivers(blendobj->parent);
+				}
+				else
+				{
+					modifierDeformer = new BL_ModifierDeformer(
+						newobj,
+						oldblendobj, blendobj,
+						static_cast<BL_SkinMeshObject*>(mesh),
+						false,
+						NULL
+					);
+				}
+				newobj->SetDeformer(modifierDeformer);
+			} 
+			else 	if (bHasShapeKey)
 			{
 				BL_ShapeDeformer* shapeDeformer;
 				if (bHasArmature) 
@@ -1029,6 +1110,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
 						oldblendobj, blendobj,
 						static_cast<BL_SkinMeshObject*>(mesh),
 						true,
+						true,
 						static_cast<BL_ArmatureObject*>( parentobj )
 					);
 					releaseParent= false;
@@ -1041,6 +1123,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
 						oldblendobj, blendobj,
 						static_cast<BL_SkinMeshObject*>(mesh),
 						false,
+						true,
 						NULL
 					);
 				}
@@ -1053,6 +1136,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
 					oldblendobj, blendobj,
 					static_cast<BL_SkinMeshObject*>(mesh),
 					true,
+					true,
 					static_cast<BL_ArmatureObject*>( parentobj )
 				);
 				releaseParent= false;
@@ -1075,24 +1159,6 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
 	gameobj->AddMeshUser();
 }
 
-
-
-MT_CmMatrix4x4& KX_Scene::GetViewMatrix()
-{
-	MT_Scalar cammat[16];
-	m_active_camera->GetWorldToCamera().getValue(cammat);
-	m_viewmat = cammat;
-	return m_viewmat;
-}
-
-
-
-MT_CmMatrix4x4& KX_Scene::GetProjectionMatrix()
-{
-	return m_projectionmat;
-}
-
-
 KX_Camera* KX_Scene::FindCamera(KX_Camera* cam)
 {
 	list<KX_Camera*>::iterator it = m_cameras.begin();
@@ -1163,7 +1229,6 @@ void KX_Scene::UpdateMeshTransformations()
 	{
 		KX_GameObject* gameobj = (KX_GameObject*)m_objectlist->GetValue(i);
 		gameobj->GetOpenGLMatrix();
-//		gameobj->UpdateNonDynas();
 	}
 }
 
@@ -1298,21 +1363,47 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam
 	}
 }
 
+void KX_Scene::PhysicsCullingCallback(KX_ClientObjectInfo* objectInfo, void* cullingInfo)
+{
+	KX_GameObject* gameobj = objectInfo->m_gameobject;
+	if (!gameobj->GetVisible())
+		// ideally, invisible objects should be removed from the culling tree temporarily
+		return;
+	if(((CullingInfo*)cullingInfo)->m_layer && !(gameobj->GetLayer() & ((CullingInfo*)cullingInfo)->m_layer))
+		// used for shadow: object is not in shadow layer
+		return;
+
+	// make object visible
+	gameobj->SetCulled(false);
+	gameobj->UpdateBuckets(false);
+}
+
 void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int layer)
 {
-// FIXME: When tree is operational
-#if 1
-	// do this incrementally in the future
-	for (int i = 0; i < m_objectlist->GetCount(); i++)
+	bool dbvt_culling = false;
+	if (m_dbvt_culling) 
 	{
-		MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);
+		// test culling through Bullet
+		PHY__Vector4 planes[6];
+		// get the clip planes
+		MT_Vector4* cplanes = cam->GetNormalizedClipPlanes();
+		// and convert
+		planes[0].setValue(cplanes[4].getValue());	// near
+		planes[1].setValue(cplanes[5].getValue());	// far
+		planes[2].setValue(cplanes[0].getValue());	// left
+		planes[3].setValue(cplanes[1].getValue());	// right
+		planes[4].setValue(cplanes[2].getValue());	// top
+		planes[5].setValue(cplanes[3].getValue());	// bottom
+		CullingInfo info(layer);
+		dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res);
+	}
+	if (!dbvt_culling) {
+		// the physics engine couldn't help us, do it the hard way
+		for (int i = 0; i < m_objectlist->GetCount(); i++)
+		{
+			MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);
+		}
 	}
-#else
-	if (cam->GetFrustumCulling())
-		MarkVisible(m_objecttree, rasty, cam, layer);
-	else
-		MarkSubTreeVisible(m_objecttree, rasty, true, cam, layer);
-#endif
 }
 
 // logic stuff
@@ -1362,23 +1453,16 @@ void KX_Scene::LogicEndFrame()
 	m_logicmgr->EndFrame();
 	int numobj = m_euthanasyobjects->GetCount();
 	int i;
-	for (i = numobj - 1; i >= 0; i--)
-	{
-		KX_GameObject* gameobj = (KX_GameObject*)m_euthanasyobjects->GetValue(i);
-		// KX_Scene::RemoveObject will also remove the object from this list
-		// that's why we start from the end
-		this->RemoveObject(gameobj);
-	}
+	KX_GameObject* obj;
 
-	numobj=	m_delayReleaseObjects->GetCount();
-	for (i = numobj-1;i>=0;i--)
+	while ((numobj = m_euthanasyobjects->GetCount()) > 0)
 	{
-		KX_GameObject* gameobj = (KX_GameObject*)m_delayReleaseObjects->GetValue(i);
-		// This list is not for object removal, but just object release
-		gameobj->Release();
+		// remove the object from this list to make sure we will not hit it again
+		obj = (KX_GameObject*)m_euthanasyobjects->GetValue(numobj-1);
+		m_euthanasyobjects->Remove(numobj-1);
+		obj->Release();
+		RemoveObject(obj);
 	}
-	// empty the list as we have removed all references
-	m_delayReleaseObjects->Resize(0);	
 }
 
 
@@ -1388,15 +1472,28 @@ void KX_Scene::LogicEndFrame()
   */
 void KX_Scene::UpdateParents(double curtime)
 {
-//	int numrootobjects = GetRootParentList()->GetCount();
+	// we use the SG dynamic list
+	SG_Node* node;
 
-	for (int i=0; i<GetRootParentList()->GetCount(); i++)
+	while ((node = SG_Node::GetNextScheduled(m_sghead)) != NULL)
 	{
-		KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
-		parentobj->NodeUpdateGS(curtime,true);
+		node->UpdateWorldData(curtime);
 	}
-}
 
+	//for (int i=0; i<GetRootParentList()->GetCount(); i++)
+	//{
+	//	KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
+	//	parentobj->NodeUpdateGS(curtime);
+	//}
+
+	// the list must be empty here
+	assert(m_sghead.Empty());
+	// some nodes may be ready for reschedule, move them to schedule list for next time
+	while ((node = SG_Node::GetNextRescheduled(m_sghead)) != NULL)
+	{
+		node->Schedule(m_sghead);
+	}
+}
 
 
 RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool &bucketCreated)
@@ -1517,12 +1614,17 @@ double KX_Scene::getSuspendedDelta()
 //Python
 
 PyTypeObject KX_Scene::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_Scene",
-		sizeof(KX_Scene),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -1542,9 +1644,9 @@ PyParentObject KX_Scene::Parents[] = {
 };
 
 PyMethodDef KX_Scene::Methods[] = {
-	KX_PYMETHODTABLE(KX_Scene, getLightList),
-	KX_PYMETHODTABLE(KX_Scene, getObjectList),
-	KX_PYMETHODTABLE(KX_Scene, getName),
+	KX_PYMETHODTABLE_NOARGS(KX_Scene, getLightList),
+	KX_PYMETHODTABLE_NOARGS(KX_Scene, getObjectList),
+	KX_PYMETHODTABLE_NOARGS(KX_Scene, getName),
 	KX_PYMETHODTABLE(KX_Scene, addObject),
 	
 	{NULL,NULL} //Sentinel
@@ -1559,67 +1661,127 @@ PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attr
 PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_Scene* self= static_cast<KX_Scene*>(self_v);
-	return self->GetObjectList()->AddRef();
+	return self->GetObjectList()->GetProxy();
 }
 
-PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_Scene::pyattr_get_objects_inactive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_Scene* self= static_cast<KX_Scene*>(self_v);
-	return self->GetActiveCamera()->AddRef();
+	return self->GetInactiveList()->GetProxy();
 }
 
-/* __dict__ only for the purpose of giving useful dir() results */
-PyObject* KX_Scene::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 	KX_Scene* self= static_cast<KX_Scene*>(self_v);
-	/* Useually done by py_getattro_up but in this case we want to include m_attrlist dict */
-	PyObject *dict_str= PyString_FromString("__dict__");
-	PyObject *dict= _getattr_dict(self->PyObjectPlus::py_getattro(dict_str), KX_Scene::Methods, KX_Scene::Attributes);
-	Py_DECREF(dict_str);
+	return self->GetLightList()->GetProxy();
+}
+
+PyObject* KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	/* With refcounts in this case...
+	 * the new CListValue is owned by python, so its possible python holds onto it longer then the BGE
+	 * however this is the same with "scene.objects + []", when you make a copy by adding lists.
+	 */
 	
-	PyDict_Update(dict, self->m_attrlist);
-	return dict;
+	KX_Scene* self= static_cast<KX_Scene*>(self_v);
+	CListValue* clist = new CListValue();
+	
+	/* return self->GetCameras()->GetProxy(); */
+	
+	list<KX_Camera*>::iterator it = self->GetCameras()->begin();
+	while (it != self->GetCameras()->end()) {
+		clist->Add((*it)->AddRef());
+		it++;
+	}
+	
+	return clist->NewProxy(true);
+}
+
+PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Scene* self= static_cast<KX_Scene*>(self_v);
+	return self->GetActiveCamera()->GetProxy();
 }
 
 PyAttributeDef KX_Scene::Attributes[] = {
-	KX_PYATTRIBUTE_RO_FUNCTION("name",			KX_Scene, pyattr_get_name),
-	KX_PYATTRIBUTE_RO_FUNCTION("objects",		KX_Scene, pyattr_get_objects),
-	KX_PYATTRIBUTE_RO_FUNCTION("active_camera",	KX_Scene, pyattr_get_active_camera),
-	KX_PYATTRIBUTE_BOOL_RO("suspended",			KX_Scene, m_suspend),
-	KX_PYATTRIBUTE_BOOL_RO("activity_culling",	KX_Scene, m_activity_culling),
+	KX_PYATTRIBUTE_RO_FUNCTION("name",				KX_Scene, pyattr_get_name),
+	KX_PYATTRIBUTE_RO_FUNCTION("objects",			KX_Scene, pyattr_get_objects),
+	KX_PYATTRIBUTE_RO_FUNCTION("objects_inactive",	KX_Scene, pyattr_get_objects_inactive),	KX_PYATTRIBUTE_RO_FUNCTION("lights",			KX_Scene, pyattr_get_lights),
+	KX_PYATTRIBUTE_RO_FUNCTION("cameras",			KX_Scene, pyattr_get_cameras),
+	KX_PYATTRIBUTE_RO_FUNCTION("lights",			KX_Scene, pyattr_get_lights),
+	KX_PYATTRIBUTE_RO_FUNCTION("active_camera",		KX_Scene, pyattr_get_active_camera),
+	KX_PYATTRIBUTE_BOOL_RO("suspended",				KX_Scene, m_suspend),
+	KX_PYATTRIBUTE_BOOL_RO("activity_culling",		KX_Scene, m_activity_culling),
 	KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius),
-	KX_PYATTRIBUTE_RO_FUNCTION("__dict__",		KX_Scene, pyattr_get_dir_dict),
+	KX_PYATTRIBUTE_BOOL_RO("dbvt_culling",			KX_Scene, m_dbvt_culling),
 	{ NULL }	//Sentinel
 };
 
+
+PyObject* KX_Scene::py_getattro__internal(PyObject *attr)
+{	
+	py_getattro_up(PyObjectPlus);
+}
+
+int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *pyvalue)
+{
+	return PyObjectPlus::py_setattro(attr, pyvalue);
+}
+
 PyObject* KX_Scene::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
+	PyObject *object = py_getattro__internal(attr);
 	
-	object = PyDict_GetItem(m_attrlist, attr);
-	if (object)
+	if (object==NULL)
 	{
-		Py_INCREF(object);
-		return object;
+		PyErr_Clear();
+		object = PyDict_GetItem(m_attr_dict, attr);
+		if(object) {
+			Py_INCREF(object);
+		}
+		else {
+			PyErr_Format(PyExc_AttributeError, "value = scene.myAttr: KX_Scene, attribute \"%s\" not found", PyString_AsString(attr));
+		}
 	}
 	
-	py_getattro_up(PyObjectPlus);
+	return object;
 }
 
-int KX_Scene::py_delattro(PyObject *attr)
-{
-	PyDict_DelItem(m_attrlist, attr);
-	return 0;
+PyObject* KX_Scene::py_getattro_dict() {
+	//py_getattro_dict_up(PyObjectPlus);
+	
+	PyObject *dict= py_getattr_dict(PyObjectPlus::py_getattro_dict(), Type.tp_dict);
+	if(dict==NULL)
+		return NULL;
+	
+	/* normally just return this but KX_Scene has some more items */
+	
+	PyDict_Update(dict, m_attr_dict);
+	return dict;
 }
 
-int KX_Scene::py_setattro(PyObject *attr, PyObject *pyvalue)
+int KX_Scene::py_setattro(PyObject *attr, PyObject *value)
 {
-	if (!PyDict_SetItem(m_attrlist, attr, pyvalue))
-		return 0;
+	int ret= py_setattro__internal(attr, value);
+	
+	if (ret==PY_SET_ATTR_MISSING) {
+		if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
+			PyErr_Clear();
+			ret= PY_SET_ATTR_SUCCESS;
+		}
+		else {
+			PyErr_SetString(PyExc_AttributeError, "scene.UserAttr = value: KX_Scenes, failed assigning value to internal dictionary");
+			ret= PY_SET_ATTR_FAIL;
+		}
+	}
+	
+	return ret;
+}
 
-	return PyObjectPlus::py_setattro(attr, pyvalue);
+int KX_Scene::py_delattro(PyObject *attr)
+{
+	PyDict_DelItem(m_attr_dict, attr);
+	return 0;
 }
 
 KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList,
@@ -1627,7 +1789,8 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList,
 "Returns a list of all lights in the scene.\n"
 )
 {
-	return (PyObject*) m_lightlist->AddRef();
+	ShowDeprecationWarning("getLightList()", "the lights property");
+	return m_lightlist->GetProxy();
 }
 
 KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList,
@@ -1635,8 +1798,8 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList,
 "Returns a list of all game objects in the scene.\n"
 )
 {
-	// ShowDeprecationWarning("getObjectList()", "the objects property"); // XXX Grr, why doesnt this work?
-	return (PyObject*) m_objectlist->AddRef();
+	ShowDeprecationWarning("getObjectList()", "the objects property");
+	return m_objectlist->GetProxy();
 }
 
 KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName,
@@ -1644,6 +1807,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName,
 "Returns the name of the scene.\n"
 )
 {
+	ShowDeprecationWarning("getName()", "the name property");
 	return PyString_FromString(GetName());
 }
 
@@ -1656,15 +1820,18 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject,
 
 	int time = 0;
 
-	if (!PyArg_ParseTuple(args, "OO|i", &pyob, &pyother, &time))
+	if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time))
 		return NULL;
 
-	if (!ConvertPythonToGameObject(pyob, &ob, false)
-		|| !ConvertPythonToGameObject(pyother, &other, false))
+	if (	!ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") ||
+			!ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") )
 		return NULL;
 
 
 	SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time);
-	replica->AddRef();
-	return replica;
+	
+	// release here because AddReplicaObject AddRef's
+	// the object is added to the scene so we dont want python to own a reference
+	replica->Release();
+	return replica->GetProxy();
 }
\ No newline at end of file
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index df51fcec8f7ca19f52bd33ffb576e5ed920f7292..128f8d23135214e4f041ab50b2e31bb2b7f551c5 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -32,8 +32,6 @@
 
 #include "KX_PhysicsEngineEnums.h"
 
-#include "MT_CmMatrix4x4.h"
-
 #include <vector>
 #include <set>
 #include <list>
@@ -43,7 +41,7 @@
 #include "SG_IObject.h"
 #include "SCA_IScene.h"
 #include "MT_Transform.h"
-#include "SND_Scene.h"
+
 #include "RAS_FramingManager.h"
 #include "RAS_Rect.h"
 
@@ -85,6 +83,8 @@ class RAS_IRenderTools;
 class SCA_JoystickManager;
 class btCollisionShape;
 class KX_BlenderSceneConverter;
+struct KX_ClientObjectInfo;
+
 /**
  * The KX_Scene holds all data for an independent scene. It relates
  * KX_Objects to the specific objects in the modules.
@@ -92,6 +92,12 @@ class KX_BlenderSceneConverter;
 class KX_Scene : public PyObjectPlus, public SCA_IScene
 {
 	Py_Header;
+
+	struct CullingInfo {
+		int m_layer;
+		CullingInfo(int layer) : m_layer(layer) {}
+	};
+
 protected:
 	RAS_BucketManager*	m_bucketmanager;
 	CListValue*			m_tempObjectList;
@@ -102,16 +108,16 @@ protected:
 	 * LogicEndFrame() via a call to RemoveObject().
 	 */
 	CListValue*	m_euthanasyobjects;
-	/**
-	* The list of objects that couldn't be released during logic update.
-	* for example, AddObject actuator sometimes releases an object that was cached from previous frame
-	*/
-	CListValue*	m_delayReleaseObjects;
 
 	CListValue*			m_objectlist;
 	CListValue*			m_parentlist; // all 'root' parents
 	CListValue*			m_lightlist;
 	CListValue*			m_inactivelist;	// all objects that are not in the active layer
+	
+	SG_QList			m_sghead;		// list of nodes that needs scenegraph update
+										// the Dlist is not object that must be updated
+										// the Qlist is for objects that needs to be rescheduled
+										// for updates after udpate is over (slow parent, bone parent)
 
 	/**
 	 *  The tree of objects in the scene.
@@ -183,15 +189,6 @@ protected:
 	 */
 	KX_Camera* m_active_camera;
 
-	/** 
-	 * The projection and view matrices of this scene 
-	 * The projection matrix is computed externally by KX_Engine	
-	 * The view mat is stored as a side effect of GetViewMatrix()
-	 * and is totally unnessary.
-	 */
-	MT_CmMatrix4x4				m_projectionmat;
-	MT_CmMatrix4x4				m_viewmat;
-
 	/** Desired canvas width set at design time. */
 	unsigned int m_canvasDesignWidth;
 	/** Desired canvas height set at design time. */
@@ -251,6 +248,16 @@ protected:
 	 */
 	bool m_activity_culling;
 	
+	/**
+	 * Toggle to enable or disable culling via DBVT broadphase of Bullet.
+	 */
+	bool m_dbvt_culling;
+	
+	/**
+	 * Occlusion culling resolution
+	 */ 
+	int m_dbvt_occlusion_res;
+
 	/**
 	 * The framing settings used by this scene
 	 */
@@ -269,6 +276,7 @@ protected:
 	void MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera*cam,int layer=0);
 	void MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible, KX_Camera*cam,int layer=0);
 	void MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj, KX_Camera*cam, int layer=0);
+	static void PhysicsCullingCallback(KX_ClientObjectInfo* objectInfo, void* cullingInfo);
 
 	double				m_suspendedtime;
 	double				m_suspendeddelta;
@@ -276,7 +284,7 @@ protected:
 	/**
 	 * This stores anything from python
 	 */
-	PyObject* m_attrlist;
+	PyObject* m_attr_dict;
 
 	struct Scene* m_blenderScene;
 
@@ -299,6 +307,8 @@ public:
 	/**
 	 * Update all transforms according to the scenegraph.
 	 */
+	static bool KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene);
+	static bool KX_ScenegraphRescheduleFunc(SG_IObject* node,void* gameobj,void* scene);
 	void UpdateParents(double curtime);
 	void DupliGroupRecurse(CValue* gameobj, int level);
 	bool IsObjectInGroup(CValue* gameobj)
@@ -316,8 +326,6 @@ public:
 	void RemoveObject(CValue* gameobj);
 	void DelayedRemoveObject(CValue* gameobj);
 	
-	void DelayedReleaseObject(CValue* gameobj);
-
 	int NewRemoveObject(CValue* gameobj);
 	void ReplaceMesh(CValue* gameobj,
 					 void* meshobj);
@@ -403,25 +411,6 @@ public:
 		class KX_Camera*
 	);
 
-	/** Return the viewmatrix as used by the last frame. */
-		MT_CmMatrix4x4&			
-	GetViewMatrix(
-	);
-
-	/** 
-	 * Return the projectionmatrix as used by the last frame. This is
-	 * set by hand :) 
-	 */
-		MT_CmMatrix4x4&			
-	GetProjectionMatrix(
-	);
-
-	/** Sets the projection matrix. */
-		void					
-	SetProjectionMatrix(
-		MT_CmMatrix4x4& pmat
-	);
-
 	/**
 	 * Activates new desired canvas width set at design time.
 	 * @param width	The new desired width.
@@ -530,6 +519,11 @@ public:
 	bool IsSuspended();
 	bool IsClearingZBuffer();
 	void EnableZBufferClearing(bool isclearingZbuffer);
+	// use of DBVT tree for camera culling
+	void SetDbvtCulling(bool b) { m_dbvt_culling = b; };
+	bool GetDbvtCulling() { return m_dbvt_culling; };
+	void SetDbvtOcclusionRes(int i) { m_dbvt_occlusion_res = i; };
+	int GetDbvtOcclusionRes() { return m_dbvt_occlusion_res; };
 	
 	void SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter);
 
@@ -568,17 +562,20 @@ public:
 	/* attributes */
 	static PyObject*	pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static PyObject*	pyattr_get_objects(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_objects_inactive(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_lights(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_cameras(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static PyObject*	pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
-	
-	/* for dir(), python3 uses __dir__() */
-	static PyObject*	pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
-	
 
 	virtual PyObject* py_getattro(PyObject *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */
+	virtual PyObject* py_getattro_dict();
+	
 	virtual int py_setattro(PyObject *attr, PyObject *pyvalue);
 	virtual int py_delattro(PyObject *attr);
 	virtual PyObject* py_repr(void) { return PyString_FromString(GetName().ReadPtr()); }
 
+	PyObject* py_getattro__internal(PyObject *attr);
+	int py_setattro__internal(PyObject *attr, PyObject *pyvalue);
 		
 	/**
 	 * Sets the time the scene was suspended
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp
index 40a2ff2ef66bfefc8e9d761422371b760e816517..64edb6cd6d50526a62b1157612653e8bd63f78db 100644
--- a/source/gameengine/Ketsji/KX_SceneActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp
@@ -76,9 +76,6 @@ CValue* KX_SceneActuator::GetReplica()
 {
 	KX_SceneActuator* replica = new KX_SceneActuator(*this);
 	replica->ProcessReplica();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-	
 	return replica;
 }
 
@@ -226,12 +223,17 @@ KX_Scene* KX_SceneActuator::FindScene(char * sceneName)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_SceneActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_SceneActuator",
-		sizeof(KX_SceneActuator),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -263,9 +265,9 @@ PyMethodDef KX_SceneActuator::Methods[] =
 	{"setUseRestart", (PyCFunction) KX_SceneActuator::sPySetUseRestart, METH_VARARGS, (PY_METHODCHAR)SetUseRestart_doc},
 	{"setScene",      (PyCFunction) KX_SceneActuator::sPySetScene, METH_VARARGS, (PY_METHODCHAR)SetScene_doc},
 	{"setCamera",     (PyCFunction) KX_SceneActuator::sPySetCamera, METH_VARARGS, (PY_METHODCHAR)SetCamera_doc},
-	{"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_VARARGS, (PY_METHODCHAR)GetUseRestart_doc},
-	{"getScene",      (PyCFunction) KX_SceneActuator::sPyGetScene, METH_VARARGS, (PY_METHODCHAR)GetScene_doc},
-	{"getCamera",     (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_VARARGS, (PY_METHODCHAR)GetCamera_doc},
+	{"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_NOARGS, (PY_METHODCHAR)GetUseRestart_doc},
+	{"getScene",      (PyCFunction) KX_SceneActuator::sPyGetScene, METH_NOARGS, (PY_METHODCHAR)GetScene_doc},
+	{"getCamera",     (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_NOARGS, (PY_METHODCHAR)GetCamera_doc},
 	//<----- Deprecated
 	{NULL,NULL} //Sentinel
 };
@@ -273,23 +275,23 @@ PyMethodDef KX_SceneActuator::Methods[] =
 PyAttributeDef KX_SceneActuator::Attributes[] = {
 	KX_PYATTRIBUTE_STRING_RW("scene",0,32,true,KX_SceneActuator,m_nextSceneName),
 	KX_PYATTRIBUTE_RW_FUNCTION("camera",KX_SceneActuator,pyattr_get_camera,pyattr_set_camera),
+	KX_PYATTRIBUTE_BOOL_RW("useRestart", KX_SceneActuator, m_restart),
+	KX_PYATTRIBUTE_INT_RW("mode", KX_SCENE_NODEF+1, KX_SCENE_MAX-1, true, KX_SceneActuator, m_mode),
 	{ NULL }	//Sentinel
 };
 
 PyObject* KX_SceneActuator::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_SceneActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_SceneActuator::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
@@ -297,23 +299,39 @@ PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTR
 	KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self);
 	if (!actuator->m_camera)
 		Py_RETURN_NONE;
-	actuator->m_camera->AddRef();
-	return actuator->m_camera;
+	
+	return actuator->m_camera->GetProxy();
 }
 
 int KX_SceneActuator::pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
 	KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self);
 	KX_Camera *camOb;
-
+	
+	if(value==Py_None)
+	{
+		if (actuator->m_camera)
+			actuator->m_camera->UnregisterActuator(actuator);
+		
+		actuator->m_camera= NULL;
+		return 0;
+	}
+	
 	if (PyObject_TypeCheck(value, &KX_Camera::Type)) 
 	{
-		camOb = static_cast<KX_Camera*>(value);
+		KX_Camera *camOb= static_cast<KX_Camera*>BGE_PROXY_REF(value);
+		
+		if(camOb==NULL)
+		{
+			PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+			return 1;
+		}
+		
 		if (actuator->m_camera)
 			actuator->m_camera->UnregisterActuator(actuator);
+		
 		actuator->m_camera = camOb;
-		if (actuator->m_camera)
-			actuator->m_camera->RegisterActuator(actuator);
+		actuator->m_camera->RegisterActuator(actuator);
 		return 0;
 	}
 
@@ -343,14 +361,12 @@ const char KX_SceneActuator::SetUseRestart_doc[] =
 "setUseRestart(flag)\n"
 "\t- flag: 0 or 1.\n"
 "\tSet flag to 1 to restart the scene.\n" ;
-PyObject* KX_SceneActuator::PySetUseRestart(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_SceneActuator::PySetUseRestart(PyObject* args)
 {
-	ShowDeprecationWarning("setUseRestart()", "(no replacement)");
+	ShowDeprecationWarning("setUseRestart()", "the useRestart property");
 	int boolArg;
 	
-	if (!PyArg_ParseTuple(args, "i", &boolArg))
+	if (!PyArg_ParseTuple(args, "i:setUseRestart", &boolArg))
 	{
 		return NULL;
 	}
@@ -366,11 +382,9 @@ PyObject* KX_SceneActuator::PySetUseRestart(PyObject* self,
 const char KX_SceneActuator::GetUseRestart_doc[] = 
 "getUseRestart()\n"
 "\tReturn whether the scene will be restarted.\n" ;
-PyObject* KX_SceneActuator::PyGetUseRestart(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_SceneActuator::PyGetUseRestart()
 {
-	ShowDeprecationWarning("getUseRestart()", "(no replacement)");
+	ShowDeprecationWarning("getUseRestart()", "the useRestart property");
 	return PyInt_FromLong(!(m_restart == 0));
 }
 
@@ -381,15 +395,13 @@ const char KX_SceneActuator::SetScene_doc[] =
 "setScene(scene)\n"
 "\t- scene: string\n"
 "\tSet the name of scene the actuator will switch to.\n" ;
-PyObject* KX_SceneActuator::PySetScene(PyObject* self, 
-									   PyObject* args, 
-									   PyObject* kwds)
+PyObject* KX_SceneActuator::PySetScene(PyObject* args)
 {
 	ShowDeprecationWarning("setScene()", "the scene property");
 	/* one argument: a scene, ignore the rest */
 	char *scene_name;
 
-	if(!PyArg_ParseTuple(args, "s", &scene_name))
+	if(!PyArg_ParseTuple(args, "s:setScene", &scene_name))
 	{
 		return NULL;
 	}
@@ -406,9 +418,7 @@ PyObject* KX_SceneActuator::PySetScene(PyObject* self,
 const char KX_SceneActuator::GetScene_doc[] = 
 "getScene()\n"
 "\tReturn the name of the scene the actuator wants to switch to.\n" ;
-PyObject* KX_SceneActuator::PyGetScene(PyObject* self, 
-									   PyObject* args, 
-									   PyObject* kwds)
+PyObject* KX_SceneActuator::PyGetScene()
 {
 	ShowDeprecationWarning("getScene()", "the scene property");
 	return PyString_FromString(m_nextSceneName);
@@ -421,26 +431,34 @@ const char KX_SceneActuator::SetCamera_doc[] =
 "setCamera(camera)\n"
 "\t- camera: string\n"
 "\tSet the camera to switch to.\n" ;
-PyObject* KX_SceneActuator::PySetCamera(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_SceneActuator::PySetCamera(PyObject* args)
 {
 	ShowDeprecationWarning("setCamera()", "the camera property");
 	PyObject *cam;
-	if (PyArg_ParseTuple(args, "O!", &KX_Camera::Type, &cam))
+	if (PyArg_ParseTuple(args, "O!:setCamera", &KX_Camera::Type, &cam))
 	{
+		KX_Camera *new_camera;
+		
+		new_camera = static_cast<KX_Camera*>BGE_PROXY_REF(cam);
+		if(new_camera==NULL)
+		{
+			PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+			return NULL;
+		}
+		
 		if (m_camera)
 			m_camera->UnregisterActuator(this);
-		m_camera = (KX_Camera*) cam;
-		if (m_camera)
-			m_camera->RegisterActuator(this);
+		
+		m_camera= new_camera;
+		
+		m_camera->RegisterActuator(this);
 		Py_RETURN_NONE;
 	}
 	PyErr_Clear();
 
 	/* one argument: a scene, ignore the rest */
 	char *camName;
-	if(!PyArg_ParseTuple(args, "s", &camName))
+	if(!PyArg_ParseTuple(args, "s:setCamera", &camName))
 	{
 		return NULL;
 	}
@@ -463,11 +481,14 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self,
 const char KX_SceneActuator::GetCamera_doc[] = 
 "getCamera()\n"
 "\tReturn the name of the camera to switch to.\n" ;
-PyObject* KX_SceneActuator::PyGetCamera(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_SceneActuator::PyGetCamera()
 {
 	ShowDeprecationWarning("getCamera()", "the camera property");
-	return PyString_FromString(m_camera->GetName());
+	if (m_camera) {
+		return PyString_FromString(m_camera->GetName());
+	}
+	else {
+		Py_RETURN_NONE;
+	}
 }
 /* eof */
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h
index f1904f95c2abd6bc286728483c95f544b3bcfade..315e97e8f700f265cfe63b07df7891c96010ad26 100644
--- a/source/gameengine/Ketsji/KX_SceneActuator.h
+++ b/source/gameengine/Ketsji/KX_SceneActuator.h
@@ -93,23 +93,24 @@ class KX_SceneActuator : public SCA_IActuator
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	/* 1. set                                                                */
 	/* Removed */
 	  
 	/* 2. setUseRestart:                                                     */
-	KX_PYMETHOD_DOC(KX_SceneActuator,SetUseRestart);
+	KX_PYMETHOD_DOC_VARARGS(KX_SceneActuator,SetUseRestart);
 	/* 3. getUseRestart:                                                     */
-	KX_PYMETHOD_DOC(KX_SceneActuator,GetUseRestart);
+	KX_PYMETHOD_DOC_NOARGS(KX_SceneActuator,GetUseRestart);
 	/* 4. setScene:                                                          */
-	KX_PYMETHOD_DOC(KX_SceneActuator,SetScene);
+	KX_PYMETHOD_DOC_VARARGS(KX_SceneActuator,SetScene);
 	/* 5. getScene:                                                          */
-	KX_PYMETHOD_DOC(KX_SceneActuator,GetScene);
+	KX_PYMETHOD_DOC_NOARGS(KX_SceneActuator,GetScene);
 	/* 6. setCamera:                                                          */
-	KX_PYMETHOD_DOC(KX_SceneActuator,SetCamera);
+	KX_PYMETHOD_DOC_VARARGS(KX_SceneActuator,SetCamera);
 	/* 7. getCamera:                                                          */
-	KX_PYMETHOD_DOC(KX_SceneActuator,GetCamera);
+	KX_PYMETHOD_DOC_NOARGS(KX_SceneActuator,GetCamera);
 	
 	static PyObject* pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
 	static int pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index b8d660daa08396a0679de14e7a4e2d3d21f1235e..07a880c950b1f74885c88c6b7606659aa9a78fa0 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -35,6 +35,7 @@
 #include "KX_GameObject.h"
 #include "SND_SoundObject.h"
 #include "SND_Scene.h" // needed for replication
+#include "KX_PyMath.h" // needed for PyObjectFrom()
 #include <iostream>
 
 #ifdef HAVE_CONFIG_H
@@ -82,19 +83,19 @@ CValue* KX_SoundActuator::GetReplica()
 {
 	KX_SoundActuator* replica = new KX_SoundActuator(*this);
 	replica->ProcessReplica();
+	return replica;
+};
+
+void KX_SoundActuator::ProcessReplica()
+{
+	SCA_IActuator::ProcessReplica();
 	if (m_soundObject)
 	{
 	    SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject);
-		replica->setSoundObject(soundobj);
+		setSoundObject(soundobj);
 		m_soundScene->AddObject(soundobj);
 	}
-	
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
-	return replica;
-};
-
-
+}	
 
 bool KX_SoundActuator::Update(double curtime, bool frame)
 {
@@ -233,12 +234,17 @@ void KX_SoundActuator::setSoundObject(class SND_SoundObject* soundobject)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_SoundActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_SoundActuator",
-		sizeof(KX_SoundActuator),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -264,104 +270,332 @@ PyParentObject KX_SoundActuator::Parents[] = {
 
 
 PyMethodDef KX_SoundActuator::Methods[] = {
+	// Deprecated ----->
 	{"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL},
-	{"getFilename", (PyCFunction) KX_SoundActuator::sPyGetFilename, METH_VARARGS,NULL},
-	{"startSound",(PyCFunction) KX_SoundActuator::sPyStartSound,METH_VARARGS,NULL},
-	{"pauseSound",(PyCFunction) KX_SoundActuator::sPyPauseSound,METH_VARARGS,NULL},
-	{"stopSound",(PyCFunction) KX_SoundActuator::sPyStopSound,METH_VARARGS,NULL},
+	{"getFilename", (PyCFunction) KX_SoundActuator::sPyGetFilename, METH_NOARGS,NULL},
 	{"setGain",(PyCFunction) KX_SoundActuator::sPySetGain,METH_VARARGS,NULL},
-	{"getGain",(PyCFunction) KX_SoundActuator::sPyGetGain,METH_VARARGS,NULL},
+	{"getGain",(PyCFunction) KX_SoundActuator::sPyGetGain,METH_NOARGS,NULL},
 	{"setPitch",(PyCFunction) KX_SoundActuator::sPySetPitch,METH_VARARGS,NULL},
-	{"getPitch",(PyCFunction) KX_SoundActuator::sPyGetPitch,METH_VARARGS,NULL},
+	{"getPitch",(PyCFunction) KX_SoundActuator::sPyGetPitch,METH_NOARGS,NULL},
 	{"setRollOffFactor",(PyCFunction) KX_SoundActuator::sPySetRollOffFactor,METH_VARARGS,NULL},
-	{"getRollOffFactor",(PyCFunction) KX_SoundActuator::sPyGetRollOffFactor,METH_VARARGS,NULL},
+	{"getRollOffFactor",(PyCFunction) KX_SoundActuator::sPyGetRollOffFactor,METH_NOARGS,NULL},
 	{"setLooping",(PyCFunction) KX_SoundActuator::sPySetLooping,METH_VARARGS,NULL},
-	{"getLooping",(PyCFunction) KX_SoundActuator::sPyGetLooping,METH_VARARGS,NULL},
+	{"getLooping",(PyCFunction) KX_SoundActuator::sPyGetLooping,METH_NOARGS,NULL},
 	{"setPosition",(PyCFunction) KX_SoundActuator::sPySetPosition,METH_VARARGS,NULL},
 	{"setVelocity",(PyCFunction) KX_SoundActuator::sPySetVelocity,METH_VARARGS,NULL},
 	{"setOrientation",(PyCFunction) KX_SoundActuator::sPySetOrientation,METH_VARARGS,NULL},
 	{"setType",(PyCFunction) KX_SoundActuator::sPySetType,METH_VARARGS,NULL},
-	{"getType",(PyCFunction) KX_SoundActuator::sPyGetType,METH_VARARGS,NULL},
+	{"getType",(PyCFunction) KX_SoundActuator::sPyGetType,METH_NOARGS,NULL},
+	// <-----
+
+	KX_PYMETHODTABLE_NOARGS(KX_SoundActuator, startSound),
+	KX_PYMETHODTABLE_NOARGS(KX_SoundActuator, pauseSound),
+	KX_PYMETHODTABLE_NOARGS(KX_SoundActuator, stopSound),
 	{NULL,NULL,NULL,NULL} //Sentinel
 };
 
 PyAttributeDef KX_SoundActuator::Attributes[] = {
+	KX_PYATTRIBUTE_RW_FUNCTION("filename", KX_SoundActuator, pyattr_get_filename, pyattr_set_filename),
+	KX_PYATTRIBUTE_RW_FUNCTION("volume", KX_SoundActuator, pyattr_get_gain, pyattr_set_gain),
+	KX_PYATTRIBUTE_RW_FUNCTION("pitch", KX_SoundActuator, pyattr_get_pitch, pyattr_set_pitch),
+	KX_PYATTRIBUTE_RW_FUNCTION("rollOffFactor", KX_SoundActuator, pyattr_get_rollOffFactor, pyattr_set_rollOffFactor),
+	KX_PYATTRIBUTE_RW_FUNCTION("looping", KX_SoundActuator, pyattr_get_looping, pyattr_set_looping),
+	KX_PYATTRIBUTE_RW_FUNCTION("position", KX_SoundActuator, pyattr_get_position, pyattr_set_position),
+	KX_PYATTRIBUTE_RW_FUNCTION("velocity", KX_SoundActuator, pyattr_get_velocity, pyattr_set_velocity),
+	KX_PYATTRIBUTE_RW_FUNCTION("orientation", KX_SoundActuator, pyattr_get_orientation, pyattr_set_orientation),
+	KX_PYATTRIBUTE_ENUM_RW("type",KX_SoundActuator::KX_SOUNDACT_NODEF+1,KX_SoundActuator::KX_SOUNDACT_MAX-1,false,KX_SoundActuator,m_type),
 	{ NULL }	//Sentinel
 };
 
-PyObject* KX_SoundActuator::py_getattro(PyObject *attr)
+/* Methods ----------------------------------------------------------------- */
+KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound, 
+"startSound()\n"
+"\tStarts the sound.\n")
 {
-	py_getattro_up(SCA_IActuator);
-}
-
-
+	if (m_soundObject)
+		// This has no effect if the actuator is not active.
+		// To start the sound you must activate the actuator. 
+		// This function is to restart the sound.
+		m_soundObject->StartSound();	
+	Py_RETURN_NONE;
+}         
 
-PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObject* kwds)
+KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, pauseSound,
+"pauseSound()\n"
+"\tPauses the sound.\n")
 {
-	char *soundName = NULL;
-	// void *soundPointer = NULL; /*unused*/
-	
-	if (!PyArg_ParseTuple(args, "s", &soundName))
-		return NULL;
+	if (m_soundObject)
+		// unfortunately, openal does not implement pause correctly, it is equivalent to a stop
+		m_soundObject->PauseSound();	
+	Py_RETURN_NONE;
+} 
 
+KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound,
+"stopSound()\n"
+"\tStops the sound.\n")
+{
+	if (m_soundObject)
+		m_soundObject->StopSound();	
 	Py_RETURN_NONE;
 }
 
+/* Atribute setting and getting -------------------------------------------- */
+PyObject* KX_SoundActuator::py_getattro(PyObject *attr)
+{
+	py_getattro_up(SCA_IActuator);
+}
 
+PyObject* KX_SoundActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_SoundActuator::py_setattro(PyObject *attr, PyObject* value) {
+	py_setattro_up(SCA_IActuator);
+}
 
-PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
 {
-	if (!m_soundObject)
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	if (!actuator->m_soundObject)
 	{
 		return PyString_FromString("");
 	}
-	STR_String objectname = m_soundObject->GetObjectName();
+	STR_String objectname = actuator->m_soundObject->GetObjectName();
 	char* name = objectname.Ptr();
 	
 	if (!name) {
-		PyErr_SetString(PyExc_RuntimeError, "Unable to get sound filename");
+		PyErr_SetString(PyExc_RuntimeError, "value = actuator.filename: KX_SoundActuator, unable to get sound filename");
 		return NULL;
 	} else
 		return PyString_FromString(name);
 }
 
+PyObject* KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	float gain = (actuator->m_soundObject) ? actuator->m_soundObject->GetGain() : 1.0f;
 
+	PyObject* result = PyFloat_FromDouble(gain);
+	
+	return result;
+}
 
-PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
 {
-	if (m_soundObject)
-		// This has no effect if the actuator is not active.
-		// To start the sound you must activate the actuator. 
-		// This function is to restart the sound.
-		m_soundObject->StartSound();	
-	Py_RETURN_NONE;
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	float pitch = (actuator->m_soundObject) ? actuator->m_soundObject->GetPitch() : 1.0;
+	PyObject* result = PyFloat_FromDouble(pitch);
+	
+	return result;
+}
+
+PyObject* KX_SoundActuator::pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	float rollofffactor = (actuator->m_soundObject) ? actuator->m_soundObject->GetRollOffFactor() : 1.0;
+	PyObject* result = PyFloat_FromDouble(rollofffactor);
+	
+	return result;
+}
+
+PyObject* KX_SoundActuator::pyattr_get_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	int looping = (actuator->m_soundObject) ? actuator->m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF;
+	PyObject* result = PyInt_FromLong(looping);
+	
+	return result;
+}
+
+PyObject* KX_SoundActuator::pyattr_get_position(void * self, const struct KX_PYATTRIBUTE_DEF *attrdef) 
+{
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	MT_Vector3 pos(0.0, 0.0, 0.0);
+
+	if (actuator->m_soundObject)
+		pos = actuator->m_soundObject->GetPosition();
+
+	PyObject * result = PyObjectFrom(pos);
+	return result;
+}
+
+PyObject* KX_SoundActuator::pyattr_get_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	MT_Vector3 vel;
+
+	if (actuator->m_soundObject)
+		vel = actuator->m_soundObject->GetVelocity();
+
+	PyObject * result = PyObjectFrom(vel);
+	return result;
+}
+
+PyObject* KX_SoundActuator::pyattr_get_orientation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) 
+{
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	MT_Matrix3x3 ori;
+
+	if (actuator->m_soundObject)
+		ori = actuator->m_soundObject->GetOrientation();
+
+	PyObject * result = PyObjectFrom(ori);
+	return result;
+}
+
+int KX_SoundActuator::pyattr_set_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	char *soundName = NULL;
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator*> (self);
+	// void *soundPointer = NULL; /*unused*/
+	
+	if (!PyArg_Parse(value, "s", &soundName))
+		return 1;
+
+	if (actuator->m_soundObject) {
+		actuator->m_soundObject->SetObjectName(soundName);
+	}
+	
+	return 0;
+}
+
+
+int KX_SoundActuator::pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	float gain = 1.0;
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	if (!PyArg_Parse(value, "f", &gain))
+		return 1;
+	
+	if (actuator->m_soundObject)
+		actuator->m_soundObject->SetGain(gain);
+	
+	return 0;
 }         
 
+int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	float pitch = 1.0;
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	if (!PyArg_Parse(value, "f", &pitch))
+		return 1;
+	
+	if (actuator->m_soundObject)
+		actuator->m_soundObject->SetPitch(pitch);
+	
+	return 0;
+}         
 
+int KX_SoundActuator::pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	float rollofffactor = 1.0;
+	if (!PyArg_Parse(value, "f", &rollofffactor))
+		return 1;
+	
+	if (actuator->m_soundObject)
+		actuator->m_soundObject->SetRollOffFactor(rollofffactor);
 
-PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds)
+	return 0;
+}         
+
+int KX_SoundActuator::pyattr_set_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
-	if (m_soundObject)
-		// unfortunately, openal does not implement pause correctly, it is equivalent to a stop
-		m_soundObject->PauseSound();	
-	Py_RETURN_NONE;
-} 
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+	int looping = 1;
+	if (!PyArg_Parse(value, "i", &looping))
+		return 1;
+	
+	if (actuator->m_soundObject)
+		actuator->m_soundObject->SetLoopMode(looping);
+	
+	return 0;
+}         
+
+int KX_SoundActuator::pyattr_set_position(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	float pos[3];
+
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
 
+	if (!PyArg_ParseTuple(value, "fff", &pos[0], &pos[1], &pos[2]))
+		return 1;
+	
+	if (actuator->m_soundObject)
+		actuator->m_soundObject->SetPosition(MT_Vector3(pos));
+	
+	return 0;
+}         
+
+int KX_SoundActuator::pyattr_set_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	float vel[3];
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
 
 
-PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds)
+	if (!PyArg_ParseTuple(value, "fff", &vel[0], &vel[1], &vel[2]))
+		return 1;
+	
+	if (actuator->m_soundObject)
+		actuator->m_soundObject->SetVelocity(MT_Vector3(vel));
+	
+	return 0;
+
+}         
+
+int KX_SoundActuator::pyattr_set_orientation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
-	if (m_soundObject)
-		m_soundObject->StopSound();	
-	Py_RETURN_NONE;
+
+	MT_Matrix3x3 rot;
+	KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
+
+	/* if value is not a sequence PyOrientationTo makes an error */
+	if (!PyOrientationTo(value, rot, "actuator.orientation = value: KX_SoundActuator"))
+		return NULL;
+	
+	if (!actuator->m_soundObject)
+		return 0; /* Since not having m_soundObject didn't do anything in the old version,
+					* it probably should be kept that way  */
+	
+	actuator->m_soundObject->SetOrientation(rot);
+	return 0;
 }
 
+// Deprecated ----->
+PyObject* KX_SoundActuator::PySetFilename(PyObject* args)
+{
+	char *soundName = NULL;
+	ShowDeprecationWarning("setFilename()", "the filename property");
+	// void *soundPointer = NULL; /*unused*/
+	
+	if (!PyArg_ParseTuple(args, "s", &soundName))
+		return NULL;
 
+	Py_RETURN_NONE;
+}
 
-PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PyGetFilename()
 {
+	ShowDeprecationWarning("getFilename()", "the filename property");
+	if (!m_soundObject)
+	{
+		return PyString_FromString("");
+	}
+	STR_String objectname = m_soundObject->GetObjectName();
+	char* name = objectname.Ptr();
+	
+	if (!name) {
+		PyErr_SetString(PyExc_RuntimeError, "Unable to get sound filename");
+		return NULL;
+	} else
+		return PyString_FromString(name);
+}
+
+PyObject* KX_SoundActuator::PySetGain(PyObject* args)
+{
+	ShowDeprecationWarning("setGain()", "the volume property");
 	float gain = 1.0;
-	if (!PyArg_ParseTuple(args, "f", &gain))
+	if (!PyArg_ParseTuple(args, "f:setGain", &gain))
 		return NULL;
 	
 	if (m_soundObject)
@@ -372,8 +606,9 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject*
 
 
 
-PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PyGetGain()
 {
+	ShowDeprecationWarning("getGain()", "the volume property");
 	float gain = (m_soundObject) ? m_soundObject->GetGain() : 1.0f;
 	PyObject* result = PyFloat_FromDouble(gain);
 	
@@ -382,10 +617,11 @@ PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject*
 
 
 
-PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PySetPitch(PyObject* args)
 {
+	ShowDeprecationWarning("setPitch()", "the pitch property");
 	float pitch = 1.0;
-	if (!PyArg_ParseTuple(args, "f", &pitch))
+	if (!PyArg_ParseTuple(args, "f:setPitch", &pitch))
 		return NULL;
 	
 	if (m_soundObject)
@@ -396,8 +632,9 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject*
 
 
 
-PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PyGetPitch()
 {
+	ShowDeprecationWarning("getPitch()", "the pitch property");
 	float pitch = (m_soundObject) ? m_soundObject->GetPitch() : 1.0;
 	PyObject* result = PyFloat_FromDouble(pitch);
 	
@@ -406,10 +643,11 @@ PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject*
 
 
 
-PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* args)
 {
+	ShowDeprecationWarning("setRollOffFactor()", "the rollOffFactor property");
 	float rollofffactor = 1.0;
-	if (!PyArg_ParseTuple(args, "f", &rollofffactor))
+	if (!PyArg_ParseTuple(args, "f:setRollOffFactor", &rollofffactor))
 		return NULL;
 	
 	if (m_soundObject)
@@ -420,8 +658,9 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P
 
 
 
-PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PyGetRollOffFactor()
 {
+	ShowDeprecationWarning("getRollOffFactor()", "the rollOffFactor property");
 	float rollofffactor = (m_soundObject) ? m_soundObject->GetRollOffFactor() : 1.0;
 	PyObject* result = PyFloat_FromDouble(rollofffactor);
 	
@@ -430,10 +669,11 @@ PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, P
 
 
 
-PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PySetLooping(PyObject* args)
 {
+	ShowDeprecationWarning("setLooping()", "the looping property");
 	bool looping = 1;
-	if (!PyArg_ParseTuple(args, "i", &looping))
+	if (!PyArg_ParseTuple(args, "i:setLooping", &looping))
 		return NULL;
 	
 	if (m_soundObject)
@@ -444,8 +684,9 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec
 
 
 
-PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PyGetLooping()
 {
+	ShowDeprecationWarning("getLooping()", "the looping property");
 	int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF;
 	PyObject* result = PyInt_FromLong(looping);
 	
@@ -454,14 +695,15 @@ PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObjec
 
 
 
-PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PySetPosition(PyObject* args)
 {
 	MT_Point3 pos;
+	ShowDeprecationWarning("setPosition()", "the position property");
 	pos[0] = 0.0;
 	pos[1] = 0.0;
 	pos[2] = 0.0;
 
-	if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2]))
+	if (!PyArg_ParseTuple(args, "fff:setPosition", &pos[0], &pos[1], &pos[2]))
 		return NULL;
 	
 	if (m_soundObject)
@@ -472,14 +714,15 @@ PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObje
 
 
 
-PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PySetVelocity(PyObject* args)
 {
 	MT_Vector3 vel;
+	ShowDeprecationWarning("setVelocity()", "the velocity property");
 	vel[0] = 0.0;
 	vel[1] = 0.0;
 	vel[2] = 0.0;
 
-	if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2]))
+	if (!PyArg_ParseTuple(args, "fff:setVelocity", &vel[0], &vel[1], &vel[2]))
 		return NULL;
 	
 	if (m_soundObject)
@@ -490,9 +733,10 @@ PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObje
 
 
 
-PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PySetOrientation(PyObject* args)
 {
 	MT_Matrix3x3 ori;
+	ShowDeprecationWarning("setOrientation()", "the orientation property");
 	ori[0][0] = 1.0;
 	ori[0][1] = 0.0;
 	ori[0][2] = 0.0;
@@ -503,7 +747,7 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO
 	ori[2][1] = 0.0;
 	ori[2][2] = 1.0;
 
-	if (!PyArg_ParseTuple(args, "fffffffff", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2]))
+	if (!PyArg_ParseTuple(args, "fffffffff:setOrientation", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2]))
 		return NULL;
 	
 	if (m_soundObject)
@@ -512,11 +756,12 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PySetType(PyObject* args)
 {
 	int typeArg;
+	ShowDeprecationWarning("setType()", "the type property");
 
-	if (!PyArg_ParseTuple(args, "i", &typeArg)) {
+	if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) {
 		return NULL;
 	}
 
@@ -528,10 +773,10 @@ PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject*
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_SoundActuator::PyGetType(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_SoundActuator::PyGetType()
 {
+	ShowDeprecationWarning("getType()", "the type property");
 	return PyInt_FromLong(m_type);
 }
-
-
+// <-----
 
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h
index 3e4a4168434717d1b0d7fe8332c486c2934b67f6..a7491355667a6746796574beab259d2863a07815 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.h
+++ b/source/gameengine/Ketsji/KX_SoundActuator.h
@@ -75,31 +75,58 @@ public:
 	virtual bool Update(double curtime, bool frame);
 
 	CValue* GetReplica();
+	void ProcessReplica();
 
 	/* -------------------------------------------------------------------- */
 	/* Python interface --------------------------------------------------- */
 	/* -------------------------------------------------------------------- */
 
-	virtual PyObject*  py_getattro(PyObject *attr);
-
-	KX_PYMETHOD(KX_SoundActuator,SetFilename);
-	KX_PYMETHOD(KX_SoundActuator,GetFilename);
-	KX_PYMETHOD(KX_SoundActuator,StartSound);
-	KX_PYMETHOD(KX_SoundActuator,PauseSound);
-	KX_PYMETHOD(KX_SoundActuator,StopSound);
-	KX_PYMETHOD(KX_SoundActuator,SetGain);
-	KX_PYMETHOD(KX_SoundActuator,GetGain);
-	KX_PYMETHOD(KX_SoundActuator,SetPitch);
-	KX_PYMETHOD(KX_SoundActuator,GetPitch);
-	KX_PYMETHOD(KX_SoundActuator,SetRollOffFactor);
-	KX_PYMETHOD(KX_SoundActuator,GetRollOffFactor);
-	KX_PYMETHOD(KX_SoundActuator,SetLooping);
-	KX_PYMETHOD(KX_SoundActuator,GetLooping);
-	KX_PYMETHOD(KX_SoundActuator,SetPosition);
-	KX_PYMETHOD(KX_SoundActuator,SetVelocity);
-	KX_PYMETHOD(KX_SoundActuator,SetOrientation);
-	KX_PYMETHOD(KX_SoundActuator,SetType);
-	KX_PYMETHOD(KX_SoundActuator,GetType);
+	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
+	virtual int py_setattro(PyObject *attr, PyObject* value);
+
+	KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, startSound);
+	KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, pauseSound);
+	KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, stopSound);
+
+	static int pyattr_set_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static int pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static int pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static int pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static int pyattr_set_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static int pyattr_set_position(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static int pyattr_set_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static int pyattr_set_orientation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
+	static PyObject* pyattr_get_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject* pyattr_get_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject* pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject* pyattr_get_position(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject* pyattr_get_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject* pyattr_get_orientation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+
+	// Deprecated ----->
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetFilename);
+	KX_PYMETHOD_NOARGS(KX_SoundActuator,GetFilename);
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetGain);
+	KX_PYMETHOD_NOARGS(KX_SoundActuator,GetGain);
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetPitch);
+	KX_PYMETHOD_NOARGS(KX_SoundActuator,GetPitch);
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetRollOffFactor);
+	KX_PYMETHOD_NOARGS(KX_SoundActuator,GetRollOffFactor);
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetLooping);
+	KX_PYMETHOD_NOARGS(KX_SoundActuator,GetLooping);
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetPosition);
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetVelocity);
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetOrientation);
+	KX_PYMETHOD_VARARGS(KX_SoundActuator,SetType);
+	KX_PYMETHOD_NOARGS(KX_SoundActuator,GetType);
+	// <-----
+
 };
 
 #endif //__KX_SOUNDACTUATOR
diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp
index 31457230f60668474606f489a9ad08d0af35b907..2cbb42b3311b6a39389951aecf1f2cf18bd840cf 100644
--- a/source/gameengine/Ketsji/KX_StateActuator.cpp
+++ b/source/gameengine/Ketsji/KX_StateActuator.cpp
@@ -62,8 +62,6 @@ KX_StateActuator::GetReplica(
 {
 	KX_StateActuator* replica = new KX_StateActuator(*this);
 	replica->ProcessReplica();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
 	return replica;
 }
 
@@ -109,12 +107,17 @@ KX_StateActuator::Update()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_StateActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_StateActuator",
-	sizeof(KX_StateActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -138,22 +141,34 @@ KX_StateActuator::Parents[] = {
 
 PyMethodDef 
 KX_StateActuator::Methods[] = {
+	// deprecated -->
 	{"setOperation", (PyCFunction) KX_StateActuator::sPySetOperation, 
 	 METH_VARARGS, (PY_METHODCHAR)SetOperation_doc},
 	{"setMask", (PyCFunction) KX_StateActuator::sPySetMask, 
 	 METH_VARARGS, (PY_METHODCHAR)SetMask_doc},
+	 // <--
 	{NULL,NULL} //Sentinel
 };
 
 PyAttributeDef KX_StateActuator::Attributes[] = {
+	KX_PYATTRIBUTE_INT_RW("operation",KX_StateActuator::OP_NOP+1,KX_StateActuator::OP_COUNT-1,false,KX_StateActuator,m_operation),
+	KX_PYATTRIBUTE_INT_RW("mask",0,0x3FFFFFFF,false,KX_StateActuator,m_mask),
 	{ NULL }	//Sentinel
 };
 
 PyObject* KX_StateActuator::py_getattro(PyObject *attr)
 {
 	py_getattro_up(SCA_IActuator);
-};
+}
 
+PyObject* KX_StateActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
+int KX_StateActuator::py_setattro(PyObject *attr, PyObject* value)
+{
+	py_setattro_up(SCA_IActuator);
+}
 
 
 /* set operation ---------------------------------------------------------- */
@@ -165,12 +180,11 @@ KX_StateActuator::SetOperation_doc[] =
 "\tUse setMask() to specify the bits that will be modified.\n";
 PyObject* 
 
-KX_StateActuator::PySetOperation(PyObject* self, 
-				    PyObject* args, 
-				    PyObject* kwds) {
+KX_StateActuator::PySetOperation(PyObject* args) {
+	ShowDeprecationWarning("setOperation()", "the operation property");
 	int oper;
 
-	if(!PyArg_ParseTuple(args, "i", &oper)) {
+	if(!PyArg_ParseTuple(args, "i:setOperation", &oper)) {
 		return NULL;
 	}
 
@@ -190,12 +204,11 @@ KX_StateActuator::SetMask_doc[] =
 "\twhich copies the value to the object state.\n";
 PyObject* 
 
-KX_StateActuator::PySetMask(PyObject* self, 
-				    PyObject* args, 
-				    PyObject* kwds) {
+KX_StateActuator::PySetMask(PyObject* args) {
+	ShowDeprecationWarning("setMask()", "the mask property");
 	int mask;
 
-	if(!PyArg_ParseTuple(args, "i", &mask)) {
+	if(!PyArg_ParseTuple(args, "i:setMask", &mask)) {
 		return NULL;
 	}
 
diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h
index b6f1acf4a00b13d6cf406f599e9c59b2dd46f39d..7e7056bd6af42e38193394bd08e494fe1b715da6 100644
--- a/source/gameengine/Ketsji/KX_StateActuator.h
+++ b/source/gameengine/Ketsji/KX_StateActuator.h
@@ -39,13 +39,15 @@ class KX_StateActuator : public SCA_IActuator
 
 	/** Make visible? */
 	enum {
+		OP_NOP = -1,
 		OP_CPY = 0,
 		OP_SET,
 		OP_CLR,
-		OP_NEG
+		OP_NEG,
+		OP_COUNT
 	};
 	int				m_operation;
-	unsigned int	m_mask;
+	int				m_mask;
 
  public:
 	
@@ -74,9 +76,11 @@ class KX_StateActuator : public SCA_IActuator
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
+	virtual int py_setattro(PyObject *attr, PyObject* value);
 	//KX_PYMETHOD_DOC
-	KX_PYMETHOD_DOC(KX_StateActuator,SetOperation);
-	KX_PYMETHOD_DOC(KX_StateActuator,SetMask);
+	KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetOperation);
+	KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetMask);
 };
 
 #endif
diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
index 7631ee05b0b83d053282b493662321ebc9c814c1..fc053f05e63693783da7a7b0e0c0d14b6eeac921 100644
--- a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
@@ -209,6 +209,11 @@ void	KX_SumoPhysicsController::SetMass(MT_Scalar newmass)
 {
 }
 
+MT_Vector3  KX_SumoPhysicsController::GetLocalInertia()
+{
+    return MT_Vector3(0.f, 0.f, 0.f); // \todo
+}
+
 MT_Scalar	KX_SumoPhysicsController::GetRadius()
 {
 	return SumoPhysicsController::GetRadius();
diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h
index 46c8ba6df45736f1f80689fd4c43d3b7be160e9c..083d89896f63405611df290273f5c2143ebdad8a 100644
--- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h
@@ -88,10 +88,15 @@ public:
 	virtual	void setScaling(const MT_Vector3& scaling);
 	virtual	MT_Scalar	GetMass();
 	virtual	void		SetMass(MT_Scalar newmass);
+	virtual MT_Vector3	GetLocalInertia();
 	virtual	MT_Scalar	GetRadius();
 	virtual	MT_Vector3	getReactionForce();
 	virtual	void	setRigidBody(bool rigid);
 	
+	virtual	float GetLinVelocityMin() { return SumoPhysicsController::GetLinVelocityMin(); }
+	virtual void	SetLinVelocityMin(float val) { SumoPhysicsController::SetLinVelocityMin(val); }
+	virtual	float GetLinVelocityMax() { return SumoPhysicsController::GetLinVelocityMax(); }
+	virtual void	SetLinVelocityMax(float val) { SumoPhysicsController::SetLinVelocityMax(val); }
 
 	virtual	SG_Controller*	GetReplica(class SG_Node* destnode);
 
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
index 48d4cf59a2bf37691e0cc5c8dafbdbb6443f2408..8ae5fae8fa3074902e08e2b31648a9ceec08aabf 100644
--- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
@@ -100,7 +100,7 @@ bool	 KX_TouchEventManager::newBroadphaseResponse(void *client_data,
 void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor)
 {
 	KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor);
-	if (m_sensors.insert(touchsensor).second)
+	if (m_sensors.AddBack(touchsensor))
 		// the sensor was effectively inserted, register it
 		touchsensor->RegisterSumo(this);
 }
@@ -108,7 +108,7 @@ void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor)
 void KX_TouchEventManager::RemoveSensor(SCA_ISensor* sensor)
 {
 	KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor);
-	if (m_sensors.erase(touchsensor))
+	if (touchsensor->Delink())
 		// the sensor was effectively removed, unregister it
 		touchsensor->UnregisterSumo(this);
 }
@@ -117,12 +117,10 @@ void KX_TouchEventManager::RemoveSensor(SCA_ISensor* sensor)
 
 void KX_TouchEventManager::EndFrame()
 {
-	set<SCA_ISensor*>::iterator it;
-	for ( it = m_sensors.begin();
-	!(it==m_sensors.end());it++)
+	SG_DList::iterator<KX_TouchSensor> it(m_sensors);
+	for (it.begin();!it.end();++it)
 	{
-		((KX_TouchSensor*)*it)->EndFrame();
-
+		(*it)->EndFrame();
 	}
 }
 
@@ -130,12 +128,11 @@ void KX_TouchEventManager::EndFrame()
 
 void KX_TouchEventManager::NextFrame()
 {
-	if (m_sensors.size() > 0)
+	if (!m_sensors.Empty())
 	{
-		set<SCA_ISensor*>::iterator it;
-		
-		for (it = m_sensors.begin();!(it==m_sensors.end());++it)
-			static_cast<KX_TouchSensor*>(*it)->SynchronizeTransform();
+		SG_DList::iterator<KX_TouchSensor> it(m_sensors);
+		for (it.begin();!it.end();++it)
+			(*it)->SynchronizeTransform();
 		
 		for (std::set<NewCollision>::iterator cit = m_newCollisions.begin(); cit != m_newCollisions.end(); ++cit)
 		{
@@ -161,7 +158,7 @@ void KX_TouchEventManager::NextFrame()
 			
 		m_newCollisions.clear();
 			
-		for (it = m_sensors.begin();!(it==m_sensors.end());++it)
-			(*it)->Activate(m_logicmgr,NULL);
+		for (it.begin();!it.end();++it)
+			(*it)->Activate(m_logicmgr);
 	}
 }
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp
index 49d3d20dc3d43d90e4803a3ec34eb56e1cda88f4..2c02d949c63af52ad8cf16cc988f754730f49dce 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.cpp
+++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp
@@ -66,10 +66,10 @@ void KX_TouchSensor::UnregisterToManager()
 {
 	// before unregistering the sensor, make sure we release all references
 	EndFrame();
-	m_eventmgr->RemoveSensor(this);
+	SCA_ISensor::UnregisterToManager();
 }
 
-bool KX_TouchSensor::Evaluate(CValue* event)
+bool KX_TouchSensor::Evaluate()
 {
 	bool result = false;
 	bool reset = m_reset && m_level;
@@ -142,13 +142,17 @@ KX_TouchSensor::~KX_TouchSensor()
 CValue* KX_TouchSensor::GetReplica() 
 {
 	KX_TouchSensor* replica = new KX_TouchSensor(*this);
-	replica->m_colliders = new CListValue();
-	replica->Init();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
+	replica->ProcessReplica();
 	return replica;
 }
 
+void KX_TouchSensor::ProcessReplica()
+{
+	SCA_ISensor::ProcessReplica();
+	m_colliders = new CListValue();
+	Init();
+}
+
 void	KX_TouchSensor::ReParent(SCA_IObject* parent)
 {
 	KX_GameObject *gameobj = static_cast<KX_GameObject *>(parent);
@@ -242,12 +246,17 @@ bool	KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll
 /* ------------------------------------------------------------------------- */
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_TouchSensor::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_TouchSensor",
-	sizeof(KX_TouchSensor),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -286,36 +295,23 @@ PyAttributeDef KX_TouchSensor::Attributes[] = {
 	KX_PYATTRIBUTE_STRING_RW("property",0,100,false,KX_TouchSensor,m_touchedpropname),
 	KX_PYATTRIBUTE_BOOL_RW("useMaterial",KX_TouchSensor,m_bFindMaterial),
 	KX_PYATTRIBUTE_BOOL_RW("pulseCollisions",KX_TouchSensor,m_bTouchPulse),
-	KX_PYATTRIBUTE_DUMMY("objectHit"),
-	KX_PYATTRIBUTE_DUMMY("objectHitList"),
+	KX_PYATTRIBUTE_RO_FUNCTION("objectHit", KX_TouchSensor, pyattr_get_object_hit),
+	KX_PYATTRIBUTE_RO_FUNCTION("objectHitList", KX_TouchSensor, pyattr_get_object_hit_list),
 	{ NULL }	//Sentinel
 };
 
 PyObject* KX_TouchSensor::py_getattro(PyObject *attr)
-{	
-	PyObject* object= py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
-	
-	char *attr_str= PyString_AsString(attr);
-	if (!strcmp(attr_str, "objectHit")) {
-		if (m_hitObject)	return m_hitObject->AddRef();
-		else				Py_RETURN_NONE;
-	}
-	if (!strcmp(attr_str, "objectHitList")) {
-		return m_colliders->AddRef();
-	}
-	
+{
 	py_getattro_up(SCA_ISensor);
 }
 
+PyObject* KX_TouchSensor::py_getattro_dict() {
+	py_getattro_dict_up(SCA_ISensor);
+}
+
 int KX_TouchSensor::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	
-	return SCA_ISensor::py_setattro(attr, value);
+	py_setattro_up(SCA_ISensor);
 }
 
 /* Python API */
@@ -327,7 +323,7 @@ const char KX_TouchSensor::SetProperty_doc[] =
 "\tSet the property or material to collide with. Use\n"
 "\tsetTouchMaterial() to switch between properties and\n"
 "\tmaterials.";
-PyObject* KX_TouchSensor::PySetProperty(PyObject* self, PyObject* value)
+PyObject* KX_TouchSensor::PySetProperty(PyObject* value)
 {
 	ShowDeprecationWarning("setProperty()", "the propertyName property");
 	char *nameArg= PyString_AsString(value);
@@ -345,21 +341,21 @@ const char KX_TouchSensor::GetProperty_doc[] =
 "\tReturns the property or material to collide with. Use\n"
 "\tgetTouchMaterial() to find out whether this sensor\n"
 "\tlooks for properties or materials.";
-PyObject*  KX_TouchSensor::PyGetProperty(PyObject* self) {
+PyObject*  KX_TouchSensor::PyGetProperty() {
 	return PyString_FromString(m_touchedpropname);
 }
 
 const char KX_TouchSensor::GetHitObject_doc[] = 
 "getHitObject()\n"
 ;
-PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self)
+PyObject* KX_TouchSensor::PyGetHitObject()
 {
 	ShowDeprecationWarning("getHitObject()", "the objectHit property");
 	/* to do: do Py_IncRef if the object is already known in Python */
 	/* otherwise, this leaks memory */
 	if (m_hitObject)
 	{
-		return m_hitObject->AddRef();
+		return m_hitObject->GetProxy();
 	}
 	Py_RETURN_NONE;
 }
@@ -368,12 +364,12 @@ const char KX_TouchSensor::GetHitObjectList_doc[] =
 "getHitObjectList()\n"
 "\tReturn a list of the objects this object collided with,\n"
 "\tbut only those matching the property/material condition.\n";
-PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self)
+PyObject* KX_TouchSensor::PyGetHitObjectList()
 {
 	ShowDeprecationWarning("getHitObjectList()", "the objectHitList property");
 	/* to do: do Py_IncRef if the object is already known in Python */
 	/* otherwise, this leaks memory */ /* Edit, this seems ok and not to leak memory - Campbell */
-	return m_colliders->AddRef();
+	return m_colliders->GetProxy();
 }
 
 /*getTouchMaterial and setTouchMaterial were never added to the api,
@@ -384,9 +380,9 @@ const char KX_TouchSensor::GetTouchMaterial_doc[] =
 "getTouchMaterial()\n"
 "\tReturns KX_TRUE if this sensor looks for a specific material,\n"
 "\tKX_FALSE if it looks for a specific property.\n" ;
-PyObject* KX_TouchSensor::PyGetTouchMaterial(PyObject* self)
+PyObject* KX_TouchSensor::PyGetTouchMaterial()
 {
-	ShowDeprecationWarning("getTouchMaterial()", "the materialCheck property");
+	ShowDeprecationWarning("getTouchMaterial()", "the useMaterial property");
 	return PyInt_FromLong(m_bFindMaterial);
 }
 
@@ -397,8 +393,9 @@ const char KX_TouchSensor::SetTouchMaterial_doc[] =
 "\t- flag: KX_TRUE or KX_FALSE.\n"
 "\tSet flag to KX_TRUE to switch on positive pulse mode,\n"
 "\tKX_FALSE to switch off positive pulse mode.\n" ;
-PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject *value)
+PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject *value)
 {
+	ShowDeprecationWarning("setTouchMaterial()", "the useMaterial property");
 	int pulseArg = PyInt_AsLong(value);
 
 	if(pulseArg ==-1 && PyErr_Occurred()) {
@@ -412,4 +409,21 @@ PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject *value)
 }
 #endif
 
+PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v);
+	
+	if (self->m_hitObject)
+		return self->m_hitObject->GetProxy();
+	else
+		Py_RETURN_NONE;
+}
+
+PyObject* KX_TouchSensor::pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v);
+	return self->m_colliders->GetProxy();
+}
+
+
 /* eof */
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h
index 93fadef4abd116c0948cb35919e8e03849ca6b6a..9c9c6bf5816ffc9e95453bae1ea7d6c6a734f42d 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.h
+++ b/source/gameengine/Ketsji/KX_TouchSensor.h
@@ -84,8 +84,9 @@ public:
 	virtual ~KX_TouchSensor();
 
 	virtual CValue* GetReplica();
+	virtual void ProcessReplica();
 	virtual void SynchronizeTransform();
-	virtual bool Evaluate(CValue* event);
+	virtual bool Evaluate();
 	virtual void Init();
 	virtual void ReParent(SCA_IObject* parent);
 	
@@ -121,6 +122,7 @@ public:
 	/* --------------------------------------------------------------------- */
 	
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	//Deprecated ----->
@@ -140,6 +142,10 @@ public:
 #endif
 	//<-----
 	
+	static PyObject*	pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static PyObject*	pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	
+	
 };
 
 #endif //__KX_TOUCHSENSOR
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index 58e17785b816c0bffe262fdab5175dd097014112..800da83dc3d149c0b967912273930aceb22c4875 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -83,6 +83,10 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj,
 				// if so, store the initial local rotation
 				// this is needed to revert the effect of the parent inverse node (TBC)
 				m_parentlocalmat = m_parentobj->GetSGNode()->GetLocalOrientation();
+				// use registration mechanism rather than AddRef, it creates zombie objects
+				m_parentobj->RegisterActuator(this);
+				// GetParent did AddRef, undo here
+				m_parentobj->Release();
 			}
 		}
 	}
@@ -189,7 +193,7 @@ KX_TrackToActuator::~KX_TrackToActuator()
 	if (m_object)
 		m_object->UnregisterActuator(this);
 	if (m_parentobj)
-		m_parentobj->Release();
+		m_parentobj->UnregisterActuator(this);
 } /* end of destructor */
 
 void KX_TrackToActuator::ProcessReplica()
@@ -198,7 +202,7 @@ void KX_TrackToActuator::ProcessReplica()
 	if (m_object)
 		m_object->RegisterActuator(this);
 	if (m_parentobj)
-		m_parentobj->AddRef();
+		m_parentobj->RegisterActuator(this);
 	SCA_IActuator::ProcessReplica();
 }
 
@@ -211,6 +215,11 @@ bool KX_TrackToActuator::UnlinkObject(SCA_IObject* clientobj)
 		m_object = NULL;
 		return true;
 	}
+	if (clientobj == m_parentobj)
+	{
+		m_parentobj = NULL;
+		return true;
+	}
 	return false;
 }
 
@@ -227,9 +236,9 @@ void KX_TrackToActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
 	void **h_parobj = (*obj_map)[m_parentobj];
 	if (h_parobj) {
 		if (m_parentobj)
-			m_parentobj->Release();
+			m_parentobj->UnregisterActuator(this);
 		m_parentobj= (KX_GameObject*)(*h_parobj);
-		m_parentobj->AddRef();
+		m_parentobj->RegisterActuator(this);
 	}
 }
 
@@ -425,12 +434,17 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_TrackToActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_TrackToActuator",
-	sizeof(KX_TrackToActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -458,9 +472,9 @@ PyParentObject KX_TrackToActuator::Parents[] = {
 PyMethodDef KX_TrackToActuator::Methods[] = {
 	// ---> deprecated
 	{"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc},
-	{"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_VARARGS, (PY_METHODCHAR)GetTime_doc},
+	{"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_NOARGS, (PY_METHODCHAR)GetTime_doc},
 	{"setUse3D", (PyCFunction) KX_TrackToActuator::sPySetUse3D, METH_VARARGS, (PY_METHODCHAR)SetUse3D_doc},
-	{"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_VARARGS, (PY_METHODCHAR)GetUse3D_doc},
+	{"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_NOARGS, (PY_METHODCHAR)GetUse3D_doc},
 	{"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc},
 	{"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc},
 	
@@ -469,7 +483,7 @@ PyMethodDef KX_TrackToActuator::Methods[] = {
 
 PyAttributeDef KX_TrackToActuator::Attributes[] = {
 	KX_PYATTRIBUTE_INT_RW("time",0,1000,true,KX_TrackToActuator,m_time),
-	KX_PYATTRIBUTE_BOOL_RW("user3D",KX_TrackToActuator,m_allow3D),
+	KX_PYATTRIBUTE_BOOL_RW("use3D",KX_TrackToActuator,m_allow3D),
 	KX_PYATTRIBUTE_RW_FUNCTION("object", KX_TrackToActuator, pyattr_get_object, pyattr_set_object),
 
 	{ NULL }	//Sentinel
@@ -481,7 +495,7 @@ PyObject* KX_TrackToActuator::pyattr_get_object(void *self, const struct KX_PYAT
 	if (!actuator->m_object)	
 		Py_RETURN_NONE;
 	else
-		return actuator->m_object->AddRef();
+		return actuator->m_object->GetProxy();
 }
 
 int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -489,7 +503,7 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT
 	KX_TrackToActuator* actuator = static_cast<KX_TrackToActuator*>(self);
 	KX_GameObject *gameobj;
 		
-	if (!ConvertPythonToGameObject(value, &gameobj, true))
+	if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_TrackToActuator"))
 		return 1; // ConvertPythonToGameObject sets the error
 		
 	if (actuator->m_object != NULL)
@@ -506,18 +520,16 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT
 
 PyObject* KX_TrackToActuator::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_TrackToActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_TrackToActuator::py_setattro(PyObject *attr, PyObject* value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 /* 1. setObject */
@@ -525,13 +537,13 @@ const char KX_TrackToActuator::SetObject_doc[] =
 "setObject(object)\n"
 "\t- object: KX_GameObject, string or None\n"
 "\tSet the object to track with the parent of this actuator.\n";
-PyObject* KX_TrackToActuator::PySetObject(PyObject* self, PyObject* value)
+PyObject* KX_TrackToActuator::PySetObject(PyObject* value)
 {
 	KX_GameObject *gameobj;
 	
 	ShowDeprecationWarning("setObject()", "the object property");
 	
-	if (!ConvertPythonToGameObject(value, &gameobj, true))
+	if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_TrackToActuator"))
 		return NULL; // ConvertPythonToGameObject sets the error
 	
 	if (m_object != NULL)
@@ -551,13 +563,13 @@ const char KX_TrackToActuator::GetObject_doc[] =
 "getObject(name_only = 1)\n"
 "name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
 "\tReturns the object to track with the parent of this actuator\n";
-PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args)
+PyObject* KX_TrackToActuator::PyGetObject(PyObject* args)
 {
 	int ret_name_only = 1;
 	
 	ShowDeprecationWarning("getObject()", "the object property");
 	
-	if (!PyArg_ParseTuple(args, "|i", &ret_name_only))
+	if (!PyArg_ParseTuple(args, "|i:getObject", &ret_name_only))
 		return NULL;
 	
 	if (!m_object)
@@ -566,7 +578,7 @@ PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args)
 	if (ret_name_only)
 		return PyString_FromString(m_object->GetName());
 	else
-		return m_object->AddRef();
+		return m_object->GetProxy();
 }
 
 
@@ -576,12 +588,12 @@ const char KX_TrackToActuator::SetTime_doc[] =
 "setTime(time)\n"
 "\t- time: integer\n"
 "\tSet the time in frames with which to delay the tracking motion.\n";
-PyObject* KX_TrackToActuator::PySetTime(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_TrackToActuator::PySetTime(PyObject* args)
 {
 	ShowDeprecationWarning("setTime()", "the timer property");
 	int timeArg;
 	
-	if (!PyArg_ParseTuple(args, "i", &timeArg))
+	if (!PyArg_ParseTuple(args, "i:setTime", &timeArg))
 	{
 		return NULL;
 	}
@@ -598,7 +610,7 @@ const char KX_TrackToActuator::GetTime_doc[] =
 "getTime()\n"
 "\t- time: integer\n"
 "\tReturn the time in frames with which the tracking motion is delayed.\n";
-PyObject* KX_TrackToActuator::PyGetTime(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_TrackToActuator::PyGetTime()
 {
 	ShowDeprecationWarning("getTime()", "the timer property");
 	return PyInt_FromLong(m_time);
@@ -610,7 +622,7 @@ PyObject* KX_TrackToActuator::PyGetTime(PyObject* self, PyObject* args, PyObject
 const char KX_TrackToActuator::GetUse3D_doc[] = 
 "getUse3D()\n"
 "\tReturns 1 if the motion is allowed to extend in the z-direction.\n";
-PyObject* KX_TrackToActuator::PyGetUse3D(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_TrackToActuator::PyGetUse3D()
 {
 	ShowDeprecationWarning("setTime()", "the use3D property");
 	return PyInt_FromLong(!(m_allow3D == 0));
@@ -624,12 +636,12 @@ const char KX_TrackToActuator::SetUse3D_doc[] =
 "\t- value: 0 or 1\n"
 "\tSet to 1 to allow the tracking motion to extend in the z-direction,\n"
 "\tset to 0 to lock the tracking motion to the x-y plane.\n";
-PyObject* KX_TrackToActuator::PySetUse3D(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_TrackToActuator::PySetUse3D(PyObject* args)
 {
 	ShowDeprecationWarning("setTime()", "the use3D property");
 	int boolArg;
 	
-	if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+	if (!PyArg_ParseTuple(args, "i:setUse3D", &boolArg)) {
 		return NULL;
 	}
 	
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h
index cc4049e19a8b9f71cbf1099417faea7e84ff73b5..c4cc2b1f062e2aad9946e2380b2c0e1aa4f52f41 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.h
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.h
@@ -61,8 +61,6 @@ class KX_TrackToActuator : public SCA_IActuator
 	virtual CValue* GetReplica() {
 		KX_TrackToActuator* replica = new KX_TrackToActuator(*this);
 		replica->ProcessReplica();
-		// this will copy properties and so on...
-		CValue::AddDataToReplica(replica);
 		return replica;
 	};
 
@@ -73,6 +71,7 @@ class KX_TrackToActuator : public SCA_IActuator
 
 	/* Python part */
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject* value);
 
 	/* These are used to get and set m_ob */
@@ -84,13 +83,13 @@ class KX_TrackToActuator : public SCA_IActuator
 	/* 2. getObject */
 	KX_PYMETHOD_DOC_VARARGS(KX_TrackToActuator,GetObject);
 	/* 3. setTime */
-	KX_PYMETHOD_DOC(KX_TrackToActuator,SetTime);
+	KX_PYMETHOD_DOC_VARARGS(KX_TrackToActuator,SetTime);
 	/* 4. getTime */
-	KX_PYMETHOD_DOC(KX_TrackToActuator,GetTime);
+	KX_PYMETHOD_DOC_NOARGS(KX_TrackToActuator,GetTime);
 	/* 5. getUse3D */
-	KX_PYMETHOD_DOC(KX_TrackToActuator,GetUse3D);
+	KX_PYMETHOD_DOC_NOARGS(KX_TrackToActuator,GetUse3D);
 	/* 6. setUse3D */
-	KX_PYMETHOD_DOC(KX_TrackToActuator,SetUse3D);
+	KX_PYMETHOD_DOC_VARARGS(KX_TrackToActuator,SetUse3D);
 	
 }; /* end of class KX_TrackToActuator : public KX_EditObjectActuator */
 
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
index 6afea4d3227bd62f5641c24424ea68163264aa56..8146d04a8788e2c2f22ae6a70746201365c24262 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
@@ -35,9 +35,7 @@ KX_VehicleWrapper::~KX_VehicleWrapper()
 }
 
 
-PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* args)
 {
 	
 	PyObject* pylistPos,*pylistDir,*pylistAxleDir;
@@ -46,14 +44,18 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* self,
 	int hasSteering;
 
 	
-	if (PyArg_ParseTuple(args,"OOOOffi",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering))
+	if (PyArg_ParseTuple(args,"OOOOffi:addWheel",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering))
 	{
-		KX_GameObject* gameOb = (KX_GameObject*) wheelGameObject;
+		KX_GameObject *gameOb;
+		if (!ConvertPythonToGameObject(wheelGameObject, &gameOb, false, "vehicle.addWheel(...): KX_VehicleWrapper (first argument)"))
+			return NULL;
+		
 
 		if (gameOb->GetSGNode())
 		{
 			PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode());
-
+			
+			/* TODO - no error checking here! - bad juju */
 			MT_Vector3 attachPos,attachDir,attachAxle;
 			PyVecTo(pylistPos,attachPos);
 			PyVecTo(pylistDir,attachDir);
@@ -82,14 +84,12 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* self,
 
 
 
-PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* args)
 {
 	
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"i",&wheelIndex))
+	if (PyArg_ParseTuple(args,"i:getWheelPosition",&wheelIndex))
 	{
 		float position[3];
 		m_vehicle->GetWheelPosition(wheelIndex,position[0],position[1],position[2]);
@@ -99,24 +99,20 @@ PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* self,
 	return NULL;
 }
 
-PyObject* KX_VehicleWrapper::PyGetWheelRotation(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyGetWheelRotation(PyObject* args)
 {
 	int wheelIndex;
-	if (PyArg_ParseTuple(args,"i",&wheelIndex))
+	if (PyArg_ParseTuple(args,"i:getWheelRotation",&wheelIndex))
 	{
 		return PyFloat_FromDouble(m_vehicle->GetWheelRotation(wheelIndex));
 	}
 	return NULL;
 }
 
-PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args)
 {
 	int wheelIndex;
-	if (PyArg_ParseTuple(args,"i",&wheelIndex))
+	if (PyArg_ParseTuple(args,"i:getWheelOrientationQuaternion",&wheelIndex))
 	{
 		float orn[4];
 		m_vehicle->GetWheelOrientationQuaternion(wheelIndex,orn[0],orn[1],orn[2],orn[3]);
@@ -129,31 +125,25 @@ PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* self,
 }
 
 
-PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* args)
 {
 	return PyInt_FromLong(m_vehicle->GetNumWheels());
 }
 
 
-PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* args)
 {
 	return PyInt_FromLong(m_vehicle->GetUserConstraintId());
 }
 
 
 
-PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* args)
 {
 	float force;
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"fi",&force,&wheelIndex))
+	if (PyArg_ParseTuple(args,"fi:applyEngineForce",&force,&wheelIndex))
 	{
 		force *= -1.f;//someone reverse some conventions inside Bullet (axle winding)
 		m_vehicle->ApplyEngineForce(force,wheelIndex);
@@ -164,14 +154,12 @@ PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* self,
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* args)
 {
 	float wheelFriction;
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"fi",&wheelFriction,&wheelIndex))
+	if (PyArg_ParseTuple(args,"fi:setTyreFriction",&wheelFriction,&wheelIndex))
 	{
 		m_vehicle->SetWheelFriction(wheelFriction,wheelIndex);
 	}
@@ -181,14 +169,12 @@ PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* self,
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* args)
 {
 	float suspensionStiffness;
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"fi",&suspensionStiffness,&wheelIndex))
+	if (PyArg_ParseTuple(args,"fi:setSuspensionStiffness",&suspensionStiffness,&wheelIndex))
 	{
 		m_vehicle->SetSuspensionStiffness(suspensionStiffness,wheelIndex);
 	}
@@ -198,14 +184,12 @@ PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* self,
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* args)
 {
 	float suspensionDamping;
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"fi",&suspensionDamping,&wheelIndex))
+	if (PyArg_ParseTuple(args,"fi:setSuspensionDamping",&suspensionDamping,&wheelIndex))
 	{
 		m_vehicle->SetSuspensionDamping(suspensionDamping,wheelIndex);
 	} else {
@@ -214,14 +198,12 @@ PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* self,
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* args)
 {
 	float suspensionCompression;
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"fi",&suspensionCompression,&wheelIndex))
+	if (PyArg_ParseTuple(args,"fi:setSuspensionCompression",&suspensionCompression,&wheelIndex))
 	{
 		m_vehicle->SetSuspensionCompression(suspensionCompression,wheelIndex);
 	} else {
@@ -230,14 +212,12 @@ PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* self,
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* args)
 {
 	float rollInfluence;
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"fi",&rollInfluence,&wheelIndex))
+	if (PyArg_ParseTuple(args,"fi:setRollInfluence",&rollInfluence,&wheelIndex))
 	{
 		m_vehicle->SetRollInfluence(rollInfluence,wheelIndex);
 	}
@@ -248,14 +228,12 @@ PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* self,
 }
 
 
-PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* args)
 {
 	float braking;
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"fi",&braking,&wheelIndex))
+	if (PyArg_ParseTuple(args,"fi:applyBraking",&braking,&wheelIndex))
 	{
 		m_vehicle->ApplyBraking(braking,wheelIndex);
 	}
@@ -268,14 +246,12 @@ PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* self,
 
 
 
-PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args)
 {
 	float steeringValue;
 	int wheelIndex;
 
-	if (PyArg_ParseTuple(args,"fi",&steeringValue,&wheelIndex))
+	if (PyArg_ParseTuple(args,"fi:setSteeringValue",&steeringValue,&wheelIndex))
 	{
 		m_vehicle->SetSteeringValue(steeringValue,wheelIndex);
 	}
@@ -286,9 +262,7 @@ PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* self,
 }
 
 
-PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* self, 
-											PyObject* args, 
-											PyObject* kwds)
+PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* args)
 {
 	return PyInt_FromLong(m_vehicle->GetUserConstraintType());
 }
@@ -299,12 +273,17 @@ PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* self,
 
 //python specific stuff
 PyTypeObject KX_VehicleWrapper::Type = {
-	PyObject_HEAD_INIT(NULL)
-		0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 		"KX_VehicleWrapper",
-		sizeof(KX_VehicleWrapper),
+		sizeof(PyObjectPlus_Proxy),
 		0,
-		PyDestructor,
+		py_base_dealloc,
 		0,
 		0,
 		0,
@@ -329,32 +308,13 @@ PyObject*	KX_VehicleWrapper::py_getattro(PyObject *attr)
 	py_getattro_up(PyObjectPlus);
 }
 
-int	KX_VehicleWrapper::py_setattro(PyObject *attr,PyObject* pyobj)
-{
-	
-	PyTypeObject* type = pyobj->ob_type;
-	int result = 1;
-
-	if (type == &PyList_Type)
-	{
-		result = 0;
-	}
-	if (type == &PyFloat_Type)
-	{
-		result = 0;
+PyObject* KX_VehicleWrapper::py_getattro_dict() {
+	py_getattro_dict_up(PyObjectPlus);
+}
 
-	}
-	if (type == &PyInt_Type)
-	{
-		result = 0;
-	}
-	if (type == &PyString_Type)
-	{
-		result = 0;
-	}
-	if (result)
-		result = PyObjectPlus::py_setattro(attr,pyobj);
-	return result;
+int	KX_VehicleWrapper::py_setattro(PyObject *attr,PyObject* value)
+{
+	py_setattro_up(PyObjectPlus);
 };
 
 
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h
index 4e03183bf8517f900d8d35b6a8d479277c1aa618..c2b5e3d92517eb5bb7cb39f62815597d23c4ff98 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.h
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h
@@ -13,6 +13,7 @@ class	KX_VehicleWrapper : public PyObjectPlus
 {
 	Py_Header;
 	virtual PyObject*		py_getattro(PyObject *attr);
+	virtual PyObject*		py_getattro_dict();
 	virtual int 			py_setattro(PyObject *attr, PyObject *value);
 
 	std::vector<PHY_IMotionState*> m_motionStates;
@@ -23,31 +24,31 @@ public:
 	int			getConstraintId();
 	
 	
-	KX_PYMETHOD(KX_VehicleWrapper,AddWheel);
-	KX_PYMETHOD(KX_VehicleWrapper,GetNumWheels);
-	KX_PYMETHOD(KX_VehicleWrapper,GetWheelOrientationQuaternion);
-	KX_PYMETHOD(KX_VehicleWrapper,GetWheelRotation);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,AddWheel);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetNumWheels);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetWheelOrientationQuaternion);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetWheelRotation);
 	
-	KX_PYMETHOD(KX_VehicleWrapper,GetWheelPosition);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetWheelPosition);
 	
-	KX_PYMETHOD(KX_VehicleWrapper,GetConstraintId);
-	KX_PYMETHOD(KX_VehicleWrapper,GetConstraintType);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetConstraintId);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetConstraintType);
 
-	KX_PYMETHOD(KX_VehicleWrapper,SetSteeringValue);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSteeringValue);
 
-	KX_PYMETHOD(KX_VehicleWrapper,ApplyEngineForce);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,ApplyEngineForce);
 
-	KX_PYMETHOD(KX_VehicleWrapper,ApplyBraking);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,ApplyBraking);
 
-	KX_PYMETHOD(KX_VehicleWrapper,SetTyreFriction);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetTyreFriction);
 
-	KX_PYMETHOD(KX_VehicleWrapper,SetSuspensionStiffness);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSuspensionStiffness);
 	
-	KX_PYMETHOD(KX_VehicleWrapper,SetSuspensionDamping);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSuspensionDamping);
 	
-	KX_PYMETHOD(KX_VehicleWrapper,SetSuspensionCompression);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSuspensionCompression);
 	
-	KX_PYMETHOD(KX_VehicleWrapper,SetRollInfluence);
+	KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetRollInfluence);
 	
 
 private:
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp
index 8c8291ef7914af512065cdd013eb02b10df9bf80..4b0ad0834735b40b52c0d0d4b6e6385e26e0eb7e 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.cpp
+++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp
@@ -37,12 +37,17 @@
 #include "KX_PyMath.h"
 
 PyTypeObject KX_VertexProxy::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_VertexProxy",
-	sizeof(KX_VertexProxy),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -57,8 +62,8 @@ PyTypeObject KX_VertexProxy::Type = {
 
 PyParentObject KX_VertexProxy::Parents[] = {
 	&KX_VertexProxy::Type,
-	&SCA_IObject::Type,
 	&CValue::Type,
+	&PyObjectPlus::Type,
 	NULL
 };
 
@@ -79,6 +84,31 @@ PyMethodDef KX_VertexProxy::Methods[] = {
 };
 
 PyAttributeDef KX_VertexProxy::Attributes[] = {
+	//KX_PYATTRIBUTE_TODO("DummyProps"),
+	
+	KX_PYATTRIBUTE_DUMMY("x"),
+	KX_PYATTRIBUTE_DUMMY("y"),
+	KX_PYATTRIBUTE_DUMMY("z"),
+	
+	KX_PYATTRIBUTE_DUMMY("r"),
+	KX_PYATTRIBUTE_DUMMY("g"),
+	KX_PYATTRIBUTE_DUMMY("b"),
+	KX_PYATTRIBUTE_DUMMY("a"),
+	
+	KX_PYATTRIBUTE_DUMMY("u"),
+	KX_PYATTRIBUTE_DUMMY("v"),
+	
+	KX_PYATTRIBUTE_DUMMY("u2"),
+	KX_PYATTRIBUTE_DUMMY("v2"),
+	
+	KX_PYATTRIBUTE_DUMMY("XYZ"),
+	KX_PYATTRIBUTE_DUMMY("UV"),
+	
+	KX_PYATTRIBUTE_DUMMY("color"),
+	KX_PYATTRIBUTE_DUMMY("colour"),
+	
+	KX_PYATTRIBUTE_DUMMY("normal"),
+	
 	{ NULL }	//Sentinel
 };
 
@@ -132,7 +162,11 @@ KX_VertexProxy::py_getattro(PyObject *attr)
 	return PyObjectFrom(MT_Vector3(m_vertex->getNormal()));
   }
   
-  py_getattro_up(SCA_IObject);
+  py_getattro_up(CValue);
+}
+
+PyObject* KX_VertexProxy::py_getattro_dict() {
+	py_getattro_dict_up(CValue);
 }
 
 int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
@@ -147,9 +181,9 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		{
 			m_vertex->SetXYZ(vec);
 			m_mesh->SetMeshModified(true);
-			return 0;
+			return PY_SET_ATTR_SUCCESS;
 		}
-		return 1;
+		return PY_SET_ATTR_FAIL;
 	}
 	
 	if (!strcmp(attr_str, "UV"))
@@ -159,9 +193,9 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		{
 			m_vertex->SetUV(vec);
 			m_mesh->SetMeshModified(true);
-			return 0;
+			return PY_SET_ATTR_SUCCESS;
 		}
-		return 1;
+		return PY_SET_ATTR_FAIL;
 	}
 	
 	if (!strcmp(attr_str, "color") || !strcmp(attr_str, "colour"))
@@ -171,9 +205,9 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		{
 			m_vertex->SetRGBA(vec);
 			m_mesh->SetMeshModified(true);
-			return 0;
+			return PY_SET_ATTR_SUCCESS;
 		}
-		return 1;
+		return PY_SET_ATTR_FAIL;
 	}
 	
 	if (!strcmp(attr_str, "normal"))
@@ -183,9 +217,9 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		{
 			m_vertex->SetNormal(vec);
 			m_mesh->SetMeshModified(true);
-			return 0;
+			return PY_SET_ATTR_SUCCESS;
 		}
-		return 1;
+		return PY_SET_ATTR_FAIL;
 	}
   }
   
@@ -199,7 +233,7 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		pos.x() = val;
 		m_vertex->SetXYZ(pos);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 	
   	if (!strcmp(attr_str, "y"))
@@ -207,7 +241,7 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		pos.y() = val;
 		m_vertex->SetXYZ(pos);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 	
 	if (!strcmp(attr_str, "z"))
@@ -215,7 +249,7 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		pos.z() = val;
 		m_vertex->SetXYZ(pos);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 	
 	// uv
@@ -225,7 +259,7 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		uv[0] = val;
 		m_vertex->SetUV(uv);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 
 	if (!strcmp(attr_str, "v"))
@@ -233,7 +267,7 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		uv[1] = val;
 		m_vertex->SetUV(uv);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 
 	// uv
@@ -251,7 +285,7 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		uv[1] = val;
 		m_vertex->SetUV2(uv);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 	
 	// col
@@ -263,32 +297,32 @@ int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
 		cp[0] = (unsigned char) val;
 		m_vertex->SetRGBA(icol);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 	if (!strcmp(attr_str, "g"))
 	{
 		cp[1] = (unsigned char) val;
 		m_vertex->SetRGBA(icol);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 	if (!strcmp(attr_str, "b"))
 	{
 		cp[2] = (unsigned char) val;
 		m_vertex->SetRGBA(icol);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
 	if (!strcmp(attr_str, "a"))
 	{
 		cp[3] = (unsigned char) val;
 		m_vertex->SetRGBA(icol);
 		m_mesh->SetMeshModified(true);
-		return 0;
+		return PY_SET_ATTR_SUCCESS;
 	}
   }
   
-  return SCA_IObject::py_setattro(attr, pyvalue);
+  return CValue::py_setattro(attr, pyvalue);
 }
 
 KX_VertexProxy::KX_VertexProxy(KX_MeshProxy*mesh, RAS_TexVert* vertex)
@@ -308,21 +342,19 @@ CValue*		KX_VertexProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
 CValue*		KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}	
 STR_String	sVertexName="vertex";
 const STR_String &	KX_VertexProxy::GetText() {return sVertexName;};
-float		KX_VertexProxy::GetNumber() { return -1;}
-STR_String	KX_VertexProxy::GetName() { return sVertexName;}
-void		KX_VertexProxy::SetName(STR_String) { };
+double		KX_VertexProxy::GetNumber() { return -1;}
+STR_String&	KX_VertexProxy::GetName() { return sVertexName;}
+void		KX_VertexProxy::SetName(const char *) { };
 CValue*		KX_VertexProxy::GetReplica() { return NULL;}
-void		KX_VertexProxy::ReplicaSetName(STR_String) {};
-
 
 // stuff for python integration
 	
-PyObject* KX_VertexProxy::PyGetXYZ(PyObject*)
+PyObject* KX_VertexProxy::PyGetXYZ()
 {
 	return PyObjectFrom(MT_Point3(m_vertex->getXYZ()));
 }
 
-PyObject* KX_VertexProxy::PySetXYZ(PyObject*, PyObject* value)
+PyObject* KX_VertexProxy::PySetXYZ(PyObject* value)
 {
 	MT_Point3 vec;
 	if (!PyVecTo(value, vec))
@@ -333,12 +365,12 @@ PyObject* KX_VertexProxy::PySetXYZ(PyObject*, PyObject* value)
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_VertexProxy::PyGetNormal(PyObject*)
+PyObject* KX_VertexProxy::PyGetNormal()
 {
 	return PyObjectFrom(MT_Vector3(m_vertex->getNormal()));
 }
 
-PyObject* KX_VertexProxy::PySetNormal(PyObject*, PyObject* value)
+PyObject* KX_VertexProxy::PySetNormal(PyObject* value)
 {
 	MT_Vector3 vec;
 	if (!PyVecTo(value, vec))
@@ -350,13 +382,13 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject*, PyObject* value)
 }
 
 
-PyObject* KX_VertexProxy::PyGetRGBA(PyObject*)
+PyObject* KX_VertexProxy::PyGetRGBA()
 {
 	int *rgba = (int *) m_vertex->getRGBA();
 	return PyInt_FromLong(*rgba);
 }
 
-PyObject* KX_VertexProxy::PySetRGBA(PyObject*, PyObject* value)
+PyObject* KX_VertexProxy::PySetRGBA(PyObject* value)
 {
 	if PyInt_Check(value) {
 		int rgba = PyInt_AsLong(value);
@@ -374,17 +406,17 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject*, PyObject* value)
 		}
 	}
 	
-	PyErr_SetString(PyExc_TypeError, "expected a 4D vector or an int");
+	PyErr_SetString(PyExc_TypeError, "vert.setRGBA(value): KX_VertexProxy, expected a 4D vector or an int");
 	return NULL;
 }
 
 
-PyObject* KX_VertexProxy::PyGetUV(PyObject*)
+PyObject* KX_VertexProxy::PyGetUV()
 {
 	return PyObjectFrom(MT_Vector2(m_vertex->getUV1()));
 }
 
-PyObject* KX_VertexProxy::PySetUV(PyObject*, PyObject* value)
+PyObject* KX_VertexProxy::PySetUV(PyObject* value)
 {
 	MT_Point2 vec;
 	if (!PyVecTo(value, vec))
@@ -395,17 +427,18 @@ PyObject* KX_VertexProxy::PySetUV(PyObject*, PyObject* value)
 	Py_RETURN_NONE;
 }
 
-PyObject* KX_VertexProxy::PyGetUV2(PyObject*)
+PyObject* KX_VertexProxy::PyGetUV2()
 {
 	return PyObjectFrom(MT_Vector2(m_vertex->getUV2()));
 }
 
-PyObject* KX_VertexProxy::PySetUV2(PyObject*, PyObject* args)
+PyObject* KX_VertexProxy::PySetUV2(PyObject* args)
 {
 	MT_Point2 vec;
-	unsigned int unit=0;
+	unsigned int unit= RAS_TexVert::SECOND_UV;
+	
 	PyObject* list= NULL;
-	if(!PyArg_ParseTuple(args, "Oi:setUV2", &list, &unit))
+	if(!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit))
 		return NULL;
 	
 	if (!PyVecTo(list, vec))
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h
index 26772fc7d60aed75ba2c89397d1cc00f5af02e19..42db5fbc3221a927498efc33d7a304971eb7e931 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.h
+++ b/source/gameengine/Ketsji/KX_VertexProxy.h
@@ -31,7 +31,7 @@
 
 #include "SCA_IObject.h"
 
-class KX_VertexProxy	: public SCA_IObject
+class KX_VertexProxy	: public CValue
 {
 	Py_Header;
 protected:
@@ -46,15 +46,15 @@ public:
 	CValue*		Calc(VALUE_OPERATOR op, CValue *val) ;
 	CValue*		CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
 	const STR_String &	GetText();
-	float		GetNumber();
-	STR_String	GetName();
-	void		SetName(STR_String name);								// Set the name of the value
-	void		ReplicaSetName(STR_String name);
+	double		GetNumber();
+	STR_String&	GetName();
+	void		SetName(const char *name);								// Set the name of the value
 	CValue*		GetReplica();
 
 
 // stuff for python integration
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int    py_setattro(PyObject *attr, PyObject *pyvalue);
 
 	KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ);
diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
index 35edd84f994dfb548e997b8bdb48c30f80f47ae3..46a1db9378a192fe748b6cb1ae38d333b7f12d2c 100644
--- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
+++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
@@ -38,11 +38,13 @@
 KX_VisibilityActuator::KX_VisibilityActuator(
 	SCA_IObject* gameobj,
 	bool visible,
+	bool occlusion,
 	bool recursive,
 	PyTypeObject* T
 	) 
 	: SCA_IActuator(gameobj,T),
 	  m_visible(visible),
+	  m_occlusion(occlusion),
 	  m_recursive(recursive)
 {
 	// intentionally empty
@@ -62,8 +64,6 @@ KX_VisibilityActuator::GetReplica(
 {
 	KX_VisibilityActuator* replica = new KX_VisibilityActuator(*this);
 	replica->ProcessReplica();
-	// this will copy properties and so on...
-	CValue::AddDataToReplica(replica);
 	return replica;
 }
 
@@ -78,6 +78,7 @@ KX_VisibilityActuator::Update()
 	KX_GameObject *obj = (KX_GameObject*) GetParent();
 	
 	obj->SetVisible(m_visible, m_recursive);
+	obj->SetOccluder(m_occlusion, m_recursive);
 	obj->UpdateBuckets(m_recursive);
 
 	return false;
@@ -91,12 +92,17 @@ KX_VisibilityActuator::Update()
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_VisibilityActuator::Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+#endif
 	"KX_VisibilityActuator",
-	sizeof(KX_VisibilityActuator),
+	sizeof(PyObjectPlus_Proxy),
 	0,
-	PyDestructor,
+	py_base_dealloc,
 	0,
 	0,
 	0,
@@ -130,24 +136,23 @@ KX_VisibilityActuator::Methods[] = {
 
 PyAttributeDef KX_VisibilityActuator::Attributes[] = {
 	KX_PYATTRIBUTE_BOOL_RW("visibility", KX_VisibilityActuator, m_visible),
+	KX_PYATTRIBUTE_BOOL_RW("occlusion", KX_VisibilityActuator, m_occlusion),
 	KX_PYATTRIBUTE_BOOL_RW("recursion", KX_VisibilityActuator, m_recursive),
 	{ NULL }	//Sentinel
 };
 
 PyObject* KX_VisibilityActuator::py_getattro(PyObject *attr)
 {
-	PyObject* object = py_getattro_self(Attributes, this, attr);
-	if (object != NULL)
-		return object;
 	py_getattro_up(SCA_IActuator);
 }
 
+PyObject* KX_VisibilityActuator::py_getattro_dict() {
+	py_getattro_dict_up(SCA_IActuator);
+}
+
 int KX_VisibilityActuator::py_setattro(PyObject *attr, PyObject *value)
 {
-	int ret = py_setattro_self(Attributes, this, attr, value);
-	if (ret >= 0)
-		return ret;
-	return SCA_IActuator::py_setattro(attr, value);
+	py_setattro_up(SCA_IActuator);
 }
 
 
@@ -159,13 +164,11 @@ KX_VisibilityActuator::SetVisible_doc[] =
 "\tSet the properties of the actuator.\n";
 PyObject* 
 
-KX_VisibilityActuator::PySetVisible(PyObject* self, 
-				    PyObject* args, 
-				    PyObject* kwds) {
+KX_VisibilityActuator::PySetVisible(PyObject* args) {
 	int vis;
 	ShowDeprecationWarning("SetVisible()", "the visible property");
 
-	if(!PyArg_ParseTuple(args, "i", &vis)) {
+	if(!PyArg_ParseTuple(args, "i:setVisible", &vis)) {
 		return NULL;
 	}
 
diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h
index fca375009157909b22466e7c927b45b2d0b322d1..45aba50f64535cd4c00ad39373a5d2deb959ec60 100644
--- a/source/gameengine/Ketsji/KX_VisibilityActuator.h
+++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h
@@ -39,6 +39,7 @@ class KX_VisibilityActuator : public SCA_IActuator
 
 	/** Make visible? */
 	bool m_visible;
+	bool m_occlusion;
 	bool m_recursive;
 
  public:
@@ -46,6 +47,7 @@ class KX_VisibilityActuator : public SCA_IActuator
 	KX_VisibilityActuator(
 		SCA_IObject* gameobj,
 		bool visible,
+		bool occlusion,
 		bool recursive,
 		PyTypeObject* T=&Type
 		);
@@ -68,10 +70,11 @@ class KX_VisibilityActuator : public SCA_IActuator
 	/* --------------------------------------------------------------------- */
 
 	virtual PyObject* py_getattro(PyObject *attr);
+	virtual PyObject* py_getattro_dict();
 	virtual int py_setattro(PyObject *attr, PyObject *value);
 
 	// Deprecated ----->
-	KX_PYMETHOD_DOC(KX_VisibilityActuator,SetVisible);
+	KX_PYMETHOD_DOC_VARARGS(KX_VisibilityActuator,SetVisible);
 	// <-----
 
 
diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript
index 5989d9d8b52d50d07b2b2eba707d0c3f61473d56..2c87c7dd78a03ddf893ccc898ee0cf08bbb78960 100644
--- a/source/gameengine/Ketsji/SConscript
+++ b/source/gameengine/Ketsji/SConscript
@@ -7,18 +7,28 @@ sources = env.Glob('*.cpp')
 defs = ''
 
 # Mathutils C files.
+if not env['BF_PYTHON_VERSION'].startswith('3'):
+	# TODO - py3 support
+	sources.extend([\
+		'#source/blender/python/api2_2x/Mathutils.c',\
+		'#source/blender/python/api2_2x/Geometry.c',\
+		'#source/blender/python/api2_2x/euler.c',\
+		'#source/blender/python/api2_2x/matrix.c',\
+		'#source/blender/python/api2_2x/quat.c',\
+		'#source/blender/python/api2_2x/vector.c',\
+		'#source/blender/python/api2_2x/constant.c',\
+	])
+	
+	sources.extend([\
+		'#source/blender/python/api2_2x/BGL.c'
+	])
+
 sources.extend([\
-	'#source/blender/python/api2_2x/Mathutils.c',\
-	'#source/blender/python/api2_2x/constant.c',\
-	'#source/blender/python/api2_2x/euler.c',\
-	'#source/blender/python/api2_2x/gen_utils.c',\
-	'#source/blender/python/api2_2x/matrix.c',\
-	'#source/blender/python/api2_2x/point.c',\
-	'#source/blender/python/api2_2x/quat.c',\
-	'#source/blender/python/api2_2x/vector.c',\
+	'#source/blender/python/api2_2x/bpy_internal_import.c'
 ])
 
-incs = '. #source/blender/python/api2_2x' # Only for Mathutils! - no other deps
+
+incs = '. #source/blender/python/api2_2x' # Only for Mathutils! and bpy_internal_import.h, be very careful
 
 incs += ' #source/kernel/gen_system #intern/string #intern/guardedalloc'
 incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #intern/bmfont'
diff --git a/source/gameengine/Network/NG_NetworkScene.cpp b/source/gameengine/Network/NG_NetworkScene.cpp
index 22263a2bdda7a28bfaad4127366d7e4ee1f84308..f8e489a8f48a20a70c0995e6d93186114e7b8596 100644
--- a/source/gameengine/Network/NG_NetworkScene.cpp
+++ b/source/gameengine/Network/NG_NetworkScene.cpp
@@ -119,7 +119,7 @@ void NG_NetworkScene::AddObject(NG_NetworkObject* object)
 {
 	if (! m_networkdevice->IsOnline()) return;
 
-	STR_String name = object->GetName();
+	const STR_String& name = object->GetName();
 	m_networkObjects.insert(name, object);
 }
 
@@ -130,7 +130,7 @@ void NG_NetworkScene::RemoveObject(NG_NetworkObject* object)
 {
 	if (! m_networkdevice->IsOnline()) return;
 
-	STR_String name = object->GetName();
+	const STR_String& name = object->GetName();
 	m_networkObjects.remove(name);
 }
 
diff --git a/source/gameengine/Network/NG_NetworkScene.h b/source/gameengine/Network/NG_NetworkScene.h
index 58de9cf6af2e894f683dd1b65d9bee504e66ea34..fc6367c352631d7ac0a00aae66822077e4e5656c 100644
--- a/source/gameengine/Network/NG_NetworkScene.h
+++ b/source/gameengine/Network/NG_NetworkScene.h
@@ -34,6 +34,11 @@
 #include "STR_HashedString.h"
 #include <vector>
 
+//MSVC defines SendMessage as a win api function, even though we aren't using it
+#ifdef SendMessage
+	#undef SendMessage
+#endif
+
 class NG_NetworkDeviceInterface;
 
 class NG_NetworkScene
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.h b/source/gameengine/Physics/BlOde/OdePhysicsController.h
index 925f5b6686a2d6b409f9a22e80cd80989482db7e..e97afdb68c3c101457508fe2f58b09e61f90849b 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsController.h
+++ b/source/gameengine/Physics/BlOde/OdePhysicsController.h
@@ -124,6 +124,10 @@ public:
 	float	getFriction() { return m_friction;}
 	float	getRestitution() { return m_restitution;}
 
+	float GetLinVelocityMin() const { return 0.f; }
+	void  SetLinVelocityMin(float val) { }
+	float GetLinVelocityMax() const { return 0.f; }
+	void  SetLinVelocityMax(float val) { }
 	
 
 private:
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
index 2e8ee31058f7934d8aae1f3b40dfb16ec0a9fe90..54e97858b7f523c2ef505f91ab01c39c34eb02ce 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
@@ -75,7 +75,7 @@ float		ODEPhysicsEnvironment::getFixedTimeStep()
 
 
 
-bool		ODEPhysicsEnvironment::proceedDeltaTime(double  curTime,float timeStep1)
+bool		ODEPhysicsEnvironment::proceedDeltaTime(double  curTime,float timeStep1,float interval)
 {
 
 	float deltaTime = timeStep1;
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
index dcc87d614c0f1e503fbba9aa411f2edb20c56bb7..82e26e01460ca2938a9adf56644d8cce44f79953 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
+++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
@@ -44,7 +44,7 @@ public:
 
 
 // Perform an integration step of duration 'timeStep'.
-	virtual	bool		proceedDeltaTime(double  curTime,float timeStep);
+	virtual	bool		proceedDeltaTime(double  curTime,float timeStep,float interval);
 	virtual	void		setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep);
 	virtual	float		getFixedTimeStep();
 
@@ -55,6 +55,7 @@ public:
 
 	virtual void		removeConstraint(void * constraintid);
 	virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+	virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes) { return false; }
 
 
 	//gamelogic callbacks
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index 83b77db4efda051fe182840d5c42e0a128b741ab..ec2cdede68327c5d9a7c22bca10714d54dac530b 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -24,17 +24,24 @@
 #
 # ***** END GPL LICENSE BLOCK *****
 
-SET(SRC CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp)
+SET(SRC CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp CcdGraphicController.cpp)
 
 SET(INC
   .
   ../common
   ../../../../extern/bullet2/src
+  ../../../../extern/glew/include
   ../../../../intern/moto/include
   ../../../kernel/gen_system
   ../../../../intern/string
+  ../../../../intern/SoundSystem 
   ../../Rasterizer
+  ../../Ketsji
+  ../../Expressions
+  ../../GameLogic
+  ../../SceneGraph
   ../../../../source/blender/makesdna
+  ${PYTHON_INC}
 )
 
 BLENDERLIB(bf_bullet "${SRC}" "${INC}")
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.cpp b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2dbbb7fa4a02e3f9aa518315d93410f4b02ef755
--- /dev/null
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
@@ -0,0 +1,134 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "CcdPhysicsEnvironment.h"
+#include "CcdGraphicController.h"
+#include "btBulletDynamicsCommon.h"
+#include "MT_Point3.h"
+
+
+CcdGraphicController::CcdGraphicController (CcdPhysicsEnvironment* phyEnv, PHY_IMotionState* motionState) :
+	m_localAabbMin(0.f, 0.f, 0.f),
+	m_localAabbMax(0.f, 0.f, 0.f),
+	m_motionState(motionState),
+	m_phyEnv(phyEnv),
+	m_handle(NULL),
+	m_newClientInfo(NULL)
+{
+}
+
+CcdGraphicController::~CcdGraphicController()
+{
+	if (m_phyEnv)
+		m_phyEnv->removeCcdGraphicController(this);
+
+	if (m_motionState)
+		delete m_motionState;
+}
+
+void CcdGraphicController::setLocalAabb(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	m_localAabbMin = aabbMin;
+	m_localAabbMax = aabbMax;
+	SetGraphicTransform();
+}
+
+void CcdGraphicController::setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax)
+{
+	m_localAabbMin.setValue(aabbMin[0],aabbMin[1],aabbMin[2]);
+	m_localAabbMax.setValue(aabbMax[0],aabbMax[1],aabbMax[2]);
+	SetGraphicTransform();
+}
+
+void CcdGraphicController::setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax)
+{
+	m_localAabbMin.setValue(aabbMin[0],aabbMin[1],aabbMin[2]);
+	m_localAabbMax.setValue(aabbMax[0],aabbMax[1],aabbMax[2]);
+	SetGraphicTransform();
+}
+
+void CcdGraphicController::setLocalAabb(const float* aabbMin,const float* aabbMax)
+{
+	m_localAabbMin.setValue(aabbMin[0],aabbMin[1],aabbMin[2]);
+	m_localAabbMax.setValue(aabbMax[0],aabbMax[1],aabbMax[2]);
+	SetGraphicTransform();
+}
+
+void CcdGraphicController::getAabb(btVector3& aabbMin, btVector3& aabbMax)
+{
+	btVector3 pos;
+	btVector3 scale;
+	float ori[12];
+	m_motionState->getWorldPosition(pos.m_floats[0],pos.m_floats[1],pos.m_floats[2]);
+	m_motionState->getWorldScaling(scale.m_floats[0],scale.m_floats[1],scale.m_floats[2]);
+	m_motionState->getWorldOrientation(ori);
+	btMatrix3x3 rot(ori[0], ori[4], ori[8],
+					ori[1], ori[5], ori[9],
+					ori[2], ori[6], ori[10]);
+
+	btVector3 localAabbMin = m_localAabbMin;
+	btVector3 localAabbMax = m_localAabbMax;
+	btVector3 tmpAabbMin = m_localAabbMin * scale;
+	btVector3 tmpAabbMax = m_localAabbMax * scale;
+
+	localAabbMin[0] = (scale.getX() >= 0.) ? tmpAabbMin[0] : tmpAabbMax[0];
+	localAabbMin[1] = (scale.getY() >= 0.) ? tmpAabbMin[1] : tmpAabbMax[1];
+	localAabbMin[2] = (scale.getZ() >= 0.) ? tmpAabbMin[2] : tmpAabbMax[2];
+	localAabbMax[0] = (scale.getX() <= 0.) ? tmpAabbMin[0] : tmpAabbMax[0];
+	localAabbMax[1] = (scale.getY() <= 0.) ? tmpAabbMin[1] : tmpAabbMax[1];
+	localAabbMax[2] = (scale.getZ() <= 0.) ? tmpAabbMin[2] : tmpAabbMax[2];
+
+	btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+	btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+	
+	btMatrix3x3 abs_b = rot.absolute();  
+	btVector3 center = rot*localCenter + pos;
+	btVector3 extent = abs_b*localHalfExtents;
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+}
+
+bool CcdGraphicController::SetGraphicTransform()
+{
+	if (!m_handle) 
+		return false;
+	btVector3 aabbMin;
+	btVector3 aabbMax;
+	getAabb(aabbMin, aabbMax);
+	// update Aabb in broadphase
+	m_phyEnv->getCullingTree()->setAabb(m_handle,aabbMin,aabbMax,NULL);
+	return true;
+}
+
+PHY_IGraphicController* CcdGraphicController::GetReplica(class PHY_IMotionState* motionState)
+{
+	CcdGraphicController* replica = new CcdGraphicController(*this);
+	replica->m_motionState = motionState;
+	replica->m_newClientInfo = NULL;
+	replica->m_handle = NULL;
+	// don't add the graphic controller now: work around a bug in Bullet with rescaling, 
+	// (the scale of the controller is not yet defined).
+	//m_phyEnv->addCcdGraphicController(replica);
+	return replica;
+}
+
+void CcdGraphicController::Activate(bool active)
+{
+	if (active)
+		m_phyEnv->addCcdGraphicController(this);
+	else
+		m_phyEnv->removeCcdGraphicController(this);
+
+}
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.h b/source/gameengine/Physics/Bullet/CcdGraphicController.h
new file mode 100644
index 0000000000000000000000000000000000000000..b0626f902c2c56815008928dfb3d98c532cc87c1
--- /dev/null
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.h
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BULLET2_GRAPHICCONTROLLER_H
+#define BULLET2_GRAPHICCONTROLLER_H
+
+#include "PHY_IGraphicController.h"
+
+#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btTransform.h"
+
+#include "PHY_IMotionState.h"
+#include "MT_Point3.h"
+
+class CcdPhysicsEnvironment;
+class btCollisionObject;
+
+///CcdGraphicController is a graphic object that supports view frustrum culling and occlusion
+class CcdGraphicController : public PHY_IGraphicController	
+{
+public:
+	CcdGraphicController(CcdPhysicsEnvironment* phyEnv, PHY_IMotionState* motionState);
+
+	virtual ~CcdGraphicController();
+
+	void setLocalAabb(const btVector3& aabbMin,const btVector3& aabbMax);
+	void setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax);
+	virtual void setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax);
+	virtual void setLocalAabb(const float aabbMin[3],const float aabbMax[3]);
+
+	PHY_IMotionState* GetMotionState() { return m_motionState; }
+	void getAabb(btVector3& aabbMin, btVector3& aabbMax);
+
+	virtual void setBroadphaseHandle(btBroadphaseProxy* handle) { m_handle = handle; }
+	virtual btBroadphaseProxy* getBroadphaseHandle() { return m_handle; }
+
+	////////////////////////////////////
+	// PHY_IGraphicController interface
+	////////////////////////////////////
+
+	/**
+	 * Updates the Aabb based on the motion state
+	 */
+	virtual bool SetGraphicTransform();
+	/**
+	 * Add/remove to environment
+	 */
+	virtual void Activate(bool active);
+
+	// client info for culling
+	virtual	void* getNewClientInfo() { return m_newClientInfo; }
+	virtual	void setNewClientInfo(void* clientinfo) { m_newClientInfo = clientinfo; }
+	virtual PHY_IGraphicController*	GetReplica(class PHY_IMotionState* motionstate);
+		
+private:
+	// unscaled aabb corner
+	btVector3 m_localAabbMin;
+	btVector3 m_localAabbMax;
+
+	PHY_IMotionState* m_motionState;
+	CcdPhysicsEnvironment* m_phyEnv;
+	btBroadphaseProxy* m_handle;
+	void* m_newClientInfo;
+
+};
+
+#endif //BULLET2_PHYSICSCONTROLLER_H
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index bb2f53a19883c90d069a160facc2133f1ae397fa..961e9096442df287c4358290ab37fa0be345a7d4 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -572,10 +572,22 @@ bool		CcdPhysicsController::SynchronizeMotionStates(float time)
 	btSoftBody* sb = GetSoftBody();
 	if (sb)
 	{
-		btVector3 aabbMin,aabbMax;
-		sb->getAabb(aabbMin,aabbMax);
-		btVector3 worldPos  = (aabbMax+aabbMin)*0.5f;
-		m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
+		if (sb->m_pose.m_bframe) 
+		{
+			btVector3 worldPos = sb->m_pose.m_com;
+			btQuaternion worldquat;
+			btMatrix3x3	trs = sb->m_pose.m_rot*sb->m_pose.m_scl;
+			trs.getRotation(worldquat);
+			m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
+			m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]);
+		}
+		else 
+		{
+			btVector3 aabbMin,aabbMax;
+			sb->getAabb(aabbMin,aabbMax);
+			btVector3 worldPos  = (aabbMax+aabbMin)*0.5f;
+			m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
+		}
 		m_MotionState->calculateWorldTransformations();
 		return true;
 	}
@@ -584,7 +596,19 @@ bool		CcdPhysicsController::SynchronizeMotionStates(float time)
 
 	if (body && !body->isStaticObject())
 	{
-
+		
+		if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0))
+		{
+			const btVector3& linvel = body->getLinearVelocity();
+			float len= linvel.length();
+			
+			if((m_cci.m_clamp_vel_max>0.0) && (len > m_cci.m_clamp_vel_max))
+					body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len));
+			
+			else if ((m_cci.m_clamp_vel_min>0.0) && btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min))
+				body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len));
+		}
+		
 		const btVector3& worldPos = body->getCenterOfMassPosition();
 		m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
 		
@@ -940,7 +964,14 @@ void		CcdPhysicsController::ApplyTorque(float torqueX,float torqueY,float torque
 			torque	= xform.getBasis()*torque;
 		}
 		if (body)
+		{
+			//workaround for incompatibility between 'DYNAMIC' game object, and angular factor
+			//a DYNAMIC object has some inconsistency: it has no angular effect due to collisions, but still has torque
+			const btVector3& angFac = body->getAngularFactor();
+			body->setAngularFactor(1.f);
 			body->applyTorque(torque);
+			body->setAngularFactor(angFac);
+		}
 	}
 }
 
@@ -1245,6 +1276,22 @@ void	DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,flo
 	quatReal = m_worldTransform.getRotation()[3];
 }
 		
+void	DefaultMotionState::getWorldOrientation(float* ori)
+{
+	*ori++ = m_worldTransform.getBasis()[0].x();
+	*ori++ = m_worldTransform.getBasis()[1].x();
+	*ori++ = m_worldTransform.getBasis()[1].x();
+	*ori++ = 0.f;
+	*ori++ = m_worldTransform.getBasis()[0].y();
+	*ori++ = m_worldTransform.getBasis()[1].y();
+	*ori++ = m_worldTransform.getBasis()[1].y();
+	*ori++ = 0.f;
+	*ori++ = m_worldTransform.getBasis()[0].z();
+	*ori++ = m_worldTransform.getBasis()[1].z();
+	*ori++ = m_worldTransform.getBasis()[1].z();
+	*ori++ = 0.f;
+}
+
 void	DefaultMotionState::setWorldPosition(float posX,float posY,float posZ)
 {
 	btVector3 pos(posX,posY,posZ);
@@ -1328,9 +1375,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo
 			}
 		}
 
-		m_vertexArray.resize(tot_bt_verts);
+		m_vertexArray.resize(tot_bt_verts*3);
 
-		btVector3 *bt= &m_vertexArray[0];
+		btScalar *bt= &m_vertexArray[0];
 
 		for (int p2=0; p2<numpolys; p2++)
 		{
@@ -1348,8 +1395,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo
 						const float* vtx = v->getXYZ();
 						vert_tag_array[orig_index]= false;
 
-						bt->setX(vtx[0]);  bt->setY(vtx[1]);  bt->setZ(vtx[2]);
-						bt++;
+						*bt++ = vtx[0];
+						*bt++ = vtx[1];
+						*bt++ = vtx[2];
 					}
 				}
 			}
@@ -1381,11 +1429,11 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo
 			}
 		}
 
-		m_vertexArray.resize(tot_bt_verts);
+		m_vertexArray.resize(tot_bt_verts*3);
 		m_polygonIndexArray.resize(tot_bt_tris);
 		m_triFaceArray.resize(tot_bt_tris*3);
 
-		btVector3 *bt= &m_vertexArray[0];
+		btScalar *bt= &m_vertexArray[0];
 		int *poly_index_pt= &m_polygonIndexArray[0];
 		int *tri_pt= &m_triFaceArray[0];
 
@@ -1419,20 +1467,23 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo
 				if (vert_tag_array[i1]==true) { /* *** v1 *** */
 					vert_tag_array[i1]= false;
 					vtx = v1->getXYZ();
-					bt->setX(vtx[0]);	bt->setY( vtx[1]);	bt->setZ(vtx[2]);
-					bt++;
+					*bt++ = vtx[0];
+					*bt++ = vtx[1];
+					*bt++ = vtx[2];
 				}
 				if (vert_tag_array[i2]==true) { /* *** v2 *** */
 					vert_tag_array[i2]= false;
 					vtx = v2->getXYZ();
-					bt->setX(vtx[0]);	bt->setY(vtx[1]);	bt->setZ(vtx[2]);
-					bt++;
+					*bt++ = vtx[0];
+					*bt++ = vtx[1];
+					*bt++ = vtx[2];
 				}
 				if (vert_tag_array[i3]==true) { /* *** v3 *** */
 					vert_tag_array[i3]= false;
 					vtx = v3->getXYZ();
-					bt->setX(vtx[0]);	bt->setY(vtx[1]);	bt->setZ(vtx[2]);
-					bt++;
+					*bt++ = vtx[0];	
+					*bt++ = vtx[1];
+					*bt++ = vtx[2];
 				}
 
 				if (poly->VertexCount()==4)
@@ -1453,8 +1504,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo
 					if (vert_tag_array[i4]==true) { /* *** v4 *** */
 						vert_tag_array[i4]= false;
 						vtx = v4->getXYZ();
-						bt->setX(vtx[0]);	bt->setY(vtx[1]);	bt->setZ(vtx[2]);
-						bt++;
+						*bt++ = vtx[0];
+						*bt++ = vtx[1];	
+						*bt++ = vtx[2];
 					}
 				}
 			}
@@ -1537,7 +1589,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
 		break;
 
 	case PHY_SHAPE_POLYTOPE:
-		collisionShape = new btConvexHullShape(&m_vertexArray[0].getX(), m_vertexArray.size());
+		collisionShape = new btConvexHullShape(&m_vertexArray[0], m_vertexArray.size()/3, 3*sizeof(btScalar));
 		break;
 
 	case PHY_SHAPE_MESH:
@@ -1554,9 +1606,9 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
 						m_polygonIndexArray.size(),
 						&m_triFaceArray[0],
 						3*sizeof(int),
-						m_vertexArray.size(),
-						(btScalar*) &m_vertexArray[0].x(),
-						sizeof(btVector3)
+						m_vertexArray.size()/3,
+						&m_vertexArray[0],
+						3*sizeof(btScalar)
 				);
 				
 				btGImpactMeshShape* gimpactShape =  new btGImpactMeshShape(indexVertexArrays);
@@ -1579,12 +1631,13 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
 					bool removeDuplicateVertices=true;
 					// m_vertexArray not in multiple of 3 anymore, use m_triFaceArray
 					for(int i=0; i<m_triFaceArray.size(); i+=3) {
-						collisionMeshData->addTriangle(
-								m_vertexArray[m_triFaceArray[i]],
-								m_vertexArray[m_triFaceArray[i+1]],
-								m_vertexArray[m_triFaceArray[i+2]],
-								removeDuplicateVertices
-						);
+						btScalar *bt = &m_vertexArray[3*m_triFaceArray[i]];
+						btVector3 v1(bt[0], bt[1], bt[2]);
+						bt = &m_vertexArray[3*m_triFaceArray[i+1]];
+						btVector3 v2(bt[0], bt[1], bt[2]);
+						bt = &m_vertexArray[3*m_triFaceArray[i+2]];
+						btVector3 v3(bt[0], bt[1], bt[2]);
+						collisionMeshData->addTriangle(v1, v2, v3, removeDuplicateVertices);
 					}
 					indexVertexArrays = collisionMeshData;
 
@@ -1594,9 +1647,9 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
 							m_polygonIndexArray.size(),
 							&m_triFaceArray[0],
 							3*sizeof(int),
-							m_vertexArray.size(),
-							(btScalar*) &m_vertexArray[0].x(),
-							sizeof(btVector3));
+							m_vertexArray.size()/3,
+							&m_vertexArray[0],
+							3*sizeof(btScalar));
 				}
 				
 				// this shape will be shared and not deleted until shapeInfo is deleted
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 510454a7b630b61c41e0913dd3210fbbb74430fc..4ab478b210646910846fe947a65e7bfbba90a238 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -107,7 +107,7 @@ public:
 	}
 	CcdShapeConstructionInfo* GetChildShape(int i)
 	{
-		if (i < 0 || i >= m_shapeArray.size())
+		if (i < 0 || i >= (int)m_shapeArray.size())
 			return NULL;
 
 		return m_shapeArray.at(i);
@@ -116,7 +116,7 @@ public:
 	{
 		if (shapeInfo == NULL)
 			return -1;
-		for (int i=0; i<m_shapeArray.size(); i++)
+		for (int i=0; i<(int)m_shapeArray.size(); i++)
 		{
 			CcdShapeConstructionInfo* childInfo = m_shapeArray.at(i);
 			if ((userData == NULL || userData == childInfo->m_userData) &&
@@ -130,10 +130,10 @@ public:
 
 	bool RemoveChildShape(int i)
 	{
-		if (i < 0 || i >= m_shapeArray.size())
+		if (i < 0 || i >= (int)m_shapeArray.size())
 			return false;
 		m_shapeArray.at(i)->Release();
-		if (i < m_shapeArray.size()-1)
+		if (i < (int)m_shapeArray.size()-1)
 			m_shapeArray[i] = m_shapeArray.back();
 		m_shapeArray.pop_back();
 		return true;
@@ -161,8 +161,8 @@ public:
 	btTransform				m_childTrans;
 	btVector3				m_childScale;
 	void*					m_userData;	
-	btAlignedObjectArray<btVector3>	m_vertexArray;	// Contains both vertex array for polytope shape and
-											// triangle array for concave mesh shape.
+	btAlignedObjectArray<btScalar>	m_vertexArray;	// Contains both vertex array for polytope shape and
+											// triangle array for concave mesh shape. Each vertex is 3 consecutive values
 											// In this case a triangle is made of 3 consecutive points
 	std::vector<int>		m_polygonIndexArray;	// Contains the array of polygon index in the 
 													// original mesh that correspond to shape triangles.
@@ -173,11 +173,7 @@ public:
 
 	void	setVertexWeldingThreshold1(float threshold)
 	{
-		m_weldingThreshold1  = threshold;
-	}
-	float	getVertexWeldingThreshold1() const
-	{
-		return m_weldingThreshold1;
+		m_weldingThreshold1  = threshold*threshold;
 	}
 protected:
 	static std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> m_meshShapeMap;
@@ -214,6 +210,8 @@ struct CcdConstructionInfo
 		m_gravity(0,0,0),
 		m_scaling(1.f,1.f,1.f),
 		m_mass(0.f),
+		m_clamp_vel_min(-1.f), 
+		m_clamp_vel_max(-1.f), 
 		m_restitution(0.1f),
 		m_friction(0.5f),
 		m_linearDamping(0.1f),
@@ -239,6 +237,8 @@ struct CcdConstructionInfo
 	btVector3	m_gravity;
 	btVector3	m_scaling;
 	btScalar	m_mass;
+	btScalar	m_clamp_vel_min;  
+	btScalar	m_clamp_vel_max;  
 	btScalar	m_restitution;
 	btScalar	m_friction;
 	btScalar	m_linearDamping;
@@ -479,7 +479,24 @@ class CcdPhysicsController : public PHY_IPhysicsController
 			}
 			m_cci.m_radius = margin;
 		}
-
+		
+		// velocity clamping
+		virtual void SetLinVelocityMin(float val) 
+		{
+			m_cci.m_clamp_vel_min= val;
+		}
+		virtual float GetLinVelocityMin() const 
+		{
+			return m_cci.m_clamp_vel_min;
+		}
+		virtual void SetLinVelocityMax(float val) 
+		{
+			m_cci.m_clamp_vel_max= val;
+		}
+		virtual float GetLinVelocityMax() const 
+		{
+			return m_cci.m_clamp_vel_max;
+		}
 
 		bool	wantsSleeping();
 
@@ -544,6 +561,7 @@ class	DefaultMotionState : public PHY_IMotionState
 		
 		virtual void	setWorldPosition(float posX,float posY,float posZ);
 		virtual	void	setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal);
+		virtual void	getWorldOrientation(float* ori);
 		
 		virtual	void	calculateWorldTransformations();
 		
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index dd21e58bd68a6f24c86ccc512afee65796e8b4d6..03c9d13a7dde6425795e2d00863647aaa6fe2d63 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -18,6 +18,7 @@ subject to the following restrictions:
 
 #include "CcdPhysicsEnvironment.h"
 #include "CcdPhysicsController.h"
+#include "CcdGraphicController.h"
 
 #include <algorithm>
 #include "btBulletDynamicsCommon.h"
@@ -32,6 +33,10 @@ subject to the following restrictions:
 
 
 #include "PHY_IMotionState.h"
+#include "KX_GameObject.h"
+#include "RAS_MeshObject.h"
+#include "RAS_Polygon.h"
+#include "RAS_TexVert.h"
 
 #define CCD_CONSTRAINT_DISABLE_LINKED_COLLISION 0x80
 
@@ -46,7 +51,9 @@ btRaycastVehicle::btVehicleTuning	gTuning;
 
 #endif //NEW_BULLET_VEHICLE_SUPPORT
 #include "LinearMath/btAabbUtil2.h"
-
+#include "MT_Matrix4x4.h"
+#include "MT_Vector3.h"
+#include "GL/glew.h"
 
 #ifdef WIN32
 void DrawRasterizerLine(const float* from,const float* to,int color);
@@ -316,8 +323,10 @@ static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVec
 
 
 
-CcdPhysicsEnvironment::CcdPhysicsEnvironment(btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
-:m_numIterations(10),
+CcdPhysicsEnvironment::CcdPhysicsEnvironment(bool useDbvtCulling,btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
+:m_cullingCache(NULL),
+m_cullingTree(NULL),
+m_numIterations(10),
 m_scalingPropagated(false),
 m_numTimeSubSteps(1),
 m_ccdMode(0),
@@ -350,6 +359,11 @@ m_ownDispatcher(NULL)
 	//m_broadphase = new btAxisSweep3(btVector3(-1000,-1000,-1000),btVector3(1000,1000,1000));
 	//m_broadphase = new btSimpleBroadphase();
 	m_broadphase = new btDbvtBroadphase();
+	// avoid any collision in the culling tree
+	if (useDbvtCulling) {
+		m_cullingCache = new btNullPairCache();
+		m_cullingTree = new btDbvtBroadphase(m_cullingCache);
+	}
 
 	m_filterCallback = new CcdOverlapFilterCallBack(this);
 	m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
@@ -364,7 +378,6 @@ m_ownDispatcher(NULL)
 	m_gravity = btVector3(0.f,-10.f,0.f);
 	m_dynamicsWorld->setGravity(m_gravity);
 
-
 }
 
 void	CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
@@ -520,6 +533,12 @@ void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctr
 	{
 		btCollisionObject* obj = ctrl->GetCollisionObject();
 		obj->setUserPointer(ctrl);
+		// update the position of the object from the user
+		if (ctrl->GetMotionState()) 
+		{
+			btTransform xform = CcdPhysicsController::GetTransformFromMotionState(ctrl->GetMotionState());
+			ctrl->SetCenterOfMassTransform(xform);
+		}
 		m_dynamicsWorld->addCollisionObject(obj, 
 			ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
 	}
@@ -558,6 +577,41 @@ void CcdPhysicsEnvironment::refreshCcdPhysicsController(CcdPhysicsController* ct
 	}
 }
 
+void CcdPhysicsEnvironment::addCcdGraphicController(CcdGraphicController* ctrl)
+{
+	if (m_cullingTree && !ctrl->getBroadphaseHandle())
+	{
+		btVector3	minAabb;
+		btVector3	maxAabb;
+		ctrl->getAabb(minAabb, maxAabb);
+
+		ctrl->setBroadphaseHandle(m_cullingTree->createProxy(
+				minAabb,
+				maxAabb,
+				INVALID_SHAPE_PROXYTYPE,	// this parameter is not used
+				ctrl,
+				0,							// this object does not collision with anything
+				0,
+				NULL,						// dispatcher => this parameter is not used
+				0));
+
+		assert(ctrl->getBroadphaseHandle());
+	}
+}
+
+void CcdPhysicsEnvironment::removeCcdGraphicController(CcdGraphicController* ctrl)
+{
+	if (m_cullingTree)
+	{
+		btBroadphaseProxy* bp = ctrl->getBroadphaseHandle();
+		if (bp)
+		{
+			m_cullingTree->destroyProxy(bp,NULL);
+			ctrl->setBroadphaseHandle(0);
+		}
+	}
+}
+
 void	CcdPhysicsEnvironment::beginFrame()
 {
 
@@ -569,7 +623,7 @@ void CcdPhysicsEnvironment::debugDrawWorld()
 			m_dynamicsWorld->debugDrawWorld();
 }
 
-bool	CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
+bool	CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval)
 {
 	std::set<CcdPhysicsController*>::iterator it;
 	int i;
@@ -579,24 +633,19 @@ bool	CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
 		(*it)->SynchronizeMotionStates(timeStep);
 	}
 
-	processFhSprings(curTime,timeStep);
-
 	float subStep = timeStep / float(m_numTimeSubSteps);
-	for (i=0;i<m_numTimeSubSteps;i++)
-	{
-//			m_dynamicsWorld->stepSimulation(subStep,20,1./240.);//perform always a full simulation step
-			m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step
-	}
+	i = m_dynamicsWorld->stepSimulation(interval,25,subStep);//perform always a full simulation step
+	processFhSprings(curTime,i*subStep);
 
 	for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
 	{
 		(*it)->SynchronizeMotionStates(timeStep);
 	}
 
-	for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
-	{
-		(*it)->SynchronizeMotionStates(timeStep);
-	}
+	//for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
+	//{
+	//	(*it)->SynchronizeMotionStates(timeStep);
+	//}
 
 	for (i=0;i<m_wrapperVehicles.size();i++)
 	{
@@ -618,9 +667,10 @@ class ClosestRayResultCallbackNotMe : public btCollisionWorld::ClosestRayResultC
 public:
 	ClosestRayResultCallbackNotMe(const btVector3& rayFromWorld,const btVector3& rayToWorld,btCollisionObject* owner,btCollisionObject* parent)
 		:btCollisionWorld::ClosestRayResultCallback(rayFromWorld,rayToWorld),
-		m_owner(owner)
+		m_owner(owner),
+		m_parent(parent)
 	{
-
+		
 	}
 
 	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
@@ -637,9 +687,11 @@ public:
 
 };
 
-void	CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep)
+void	CcdPhysicsEnvironment::processFhSprings(double curTime,float interval)
 {
 	std::set<CcdPhysicsController*>::iterator it;
+	// dynamic of Fh spring is based on a timestep of 1/60
+	int numIter = (int)(interval*60.0001f);
 	
 	for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
 	{
@@ -651,8 +703,6 @@ void	CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep)
 			//printf("has Fh or RotFh\n");
 			//re-implement SM_FhObject.cpp using btCollisionWorld::rayTest and info from ctrl->getConstructionInfo()
 			//send a ray from {0.0, 0.0, 0.0} towards {0.0, 0.0, -10.0}, in local coordinates
-
-			
 			CcdPhysicsController* parentCtrl = ctrl->getParentCtrl();
 			btRigidBody* parentBody = parentCtrl?parentCtrl->GetRigidBody() : 0;
 			btRigidBody* cl_object = parentBody ? parentBody : body;
@@ -668,7 +718,7 @@ void	CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep)
 			//btVector3	rayToWorld = rayFromWorld + body->getCenterOfMassTransform().getBasis() * rayDirLocal;
 			//ray always points down the z axis in world space...
 			btVector3	rayToWorld = rayFromWorld + rayDirLocal;
-
+			
 			ClosestRayResultCallbackNotMe	resultCallback(rayFromWorld,rayToWorld,body,parentBody);
 
 			m_dynamicsWorld->rayTest(rayFromWorld,rayToWorld,resultCallback);
@@ -699,82 +749,78 @@ void	CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep)
 					btVector3 normal = resultCallback.m_hitNormalWorld;
 					normal.normalize();
 
-					
-					if (ctrl->getConstructionInfo().m_do_fh) 
+					for (int i=0; i<numIter; i++)
 					{
-						btVector3 lspot = cl_object->getCenterOfMassPosition()
-							+ rayDirLocal * resultCallback.m_closestHitFraction;
+						if (ctrl->getConstructionInfo().m_do_fh) 
+						{
+							btVector3 lspot = cl_object->getCenterOfMassPosition()
+								+ rayDirLocal * resultCallback.m_closestHitFraction;
+
 
+								
 
+							lspot -= hit_object->getCenterOfMassPosition();
+							btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot);
+							btScalar rel_vel_ray = ray_dir.dot(rel_vel);
+							btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance; 
 							
+							btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring;
+							btScalar i_damp =   rel_vel_ray * hitObjShapeProps.m_fh_damping;
+							
+							cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir)); 
+							if (hitObjShapeProps.m_fh_normal) 
+							{
+								cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir));
+							}
+							
+							btVector3 lateral = rel_vel - rel_vel_ray * ray_dir;
+							
+							
+							if (ctrl->getConstructionInfo().m_do_anisotropic) {
+								//Bullet basis contains no scaling/shear etc.
+								const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis();
+								btVector3 loc_lateral = lateral * lcs;
+								const btVector3& friction_scaling = cl_object->getAnisotropicFriction();
+								loc_lateral *= friction_scaling;
+								lateral = lcs * loc_lateral;
+							}
 
-						lspot -= hit_object->getCenterOfMassPosition();
-						btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot);
-						btScalar rel_vel_ray = ray_dir.dot(rel_vel);
-						btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance; 
-						
-						btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring;
-						btScalar i_damp =   rel_vel_ray * hitObjShapeProps.m_fh_damping;
-						
-						cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir)); 
-						if (hitObjShapeProps.m_fh_normal) 
-						{
-							cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir));
-						}
-						
-						btVector3 lateral = rel_vel - rel_vel_ray * ray_dir;
-						
-						
-						if (ctrl->getConstructionInfo().m_do_anisotropic) {
-							//Bullet basis contains no scaling/shear etc.
-							const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis();
-							btVector3 loc_lateral = lateral * lcs;
-							const btVector3& friction_scaling = cl_object->getAnisotropicFriction();
-							loc_lateral *= friction_scaling;
-							lateral = lcs * loc_lateral;
+							btScalar rel_vel_lateral = lateral.length();
+							
+							if (rel_vel_lateral > SIMD_EPSILON) {
+								btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction();
+
+								btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring);
+								
+								btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass();
+								
+								btVector3 friction = (rel_mom_lateral > max_friction) ?
+									-lateral * (max_friction / rel_vel_lateral) :
+									-lateral;
+								
+									cl_object->applyCentralImpulse(friction);
+							}
 						}
 
-						btScalar rel_vel_lateral = lateral.length();
 						
-						if (rel_vel_lateral > SIMD_EPSILON) {
-							btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction();
+						if (ctrl->getConstructionInfo().m_do_rot_fh) {
+							btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2);
 
-							btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring);
+							btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring;
+							btVector3 ang_vel = cl_object->getAngularVelocity();
 							
-							btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass();
+							// only rotations that tilt relative to the normal are damped
+							ang_vel -= ang_vel.dot(normal) * normal;
 							
-							btVector3 friction = (rel_mom_lateral > max_friction) ?
-								-lateral * (max_friction / rel_vel_lateral) :
-								-lateral;
+							btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping;  
 							
-								cl_object->applyCentralImpulse(friction);
+							cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp));
 						}
 					}
-
-					
-					if (ctrl->getConstructionInfo().m_do_rot_fh) {
-						btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2);
-
-						btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring;
-						btVector3 ang_vel = cl_object->getAngularVelocity();
-						
-						// only rotations that tilt relative to the normal are damped
-						ang_vel -= ang_vel.dot(normal) * normal;
-						
-						btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping;  
-						
-						cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp));
-					}
-
 				}
-
-
 			}
-
-
 		}
 	}
-	
 }
 
 void		CcdPhysicsEnvironment::setDebugMode(int debugMode)
@@ -1146,7 +1192,578 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
 	return result.m_controller;
 }
 
+// Handles occlusion culling. 
+// The implementation is based on the CDTestFramework
+struct OcclusionBuffer
+{
+	struct WriteOCL
+	{
+		static inline bool Process(btScalar& q,btScalar v) { if(q<v) q=v;return(false); }
+		static inline void Occlusion(bool& flag) { flag = true; }
+	};
+	struct QueryOCL
+	{
+		static inline bool Process(btScalar& q,btScalar v) { return(q<=v); }
+		static inline void Occlusion(bool& flag) { }
+	};
+	btScalar*						m_buffer;
+	size_t							m_bufferSize;
+	bool							m_initialized;
+	bool							m_occlusion;
+	int								m_sizes[2];
+	btScalar						m_scales[2];
+	btScalar						m_offsets[2];
+	btScalar						m_wtc[16];		// world to clip transform
+	btScalar						m_mtc[16];		// model to clip transform
+	// constructor: size=largest dimension of the buffer. 
+	// Buffer size depends on aspect ratio
+	OcclusionBuffer()
+	{
+		m_initialized=false;
+		m_occlusion = false;
+		m_buffer == NULL;
+		m_bufferSize = 0;
+	}
+	// multiplication of column major matrices: m=m1*m2
+	template<typename T1, typename T2>
+	void		CMmat4mul(btScalar* m, const T1* m1, const T2* m2)
+	{
+		m[ 0] = btScalar(m1[ 0]*m2[ 0]+m1[ 4]*m2[ 1]+m1[ 8]*m2[ 2]+m1[12]*m2[ 3]);
+		m[ 1] = btScalar(m1[ 1]*m2[ 0]+m1[ 5]*m2[ 1]+m1[ 9]*m2[ 2]+m1[13]*m2[ 3]);
+		m[ 2] = btScalar(m1[ 2]*m2[ 0]+m1[ 6]*m2[ 1]+m1[10]*m2[ 2]+m1[14]*m2[ 3]);
+		m[ 3] = btScalar(m1[ 3]*m2[ 0]+m1[ 7]*m2[ 1]+m1[11]*m2[ 2]+m1[15]*m2[ 3]);
+
+		m[ 4] = btScalar(m1[ 0]*m2[ 4]+m1[ 4]*m2[ 5]+m1[ 8]*m2[ 6]+m1[12]*m2[ 7]);
+		m[ 5] = btScalar(m1[ 1]*m2[ 4]+m1[ 5]*m2[ 5]+m1[ 9]*m2[ 6]+m1[13]*m2[ 7]);
+		m[ 6] = btScalar(m1[ 2]*m2[ 4]+m1[ 6]*m2[ 5]+m1[10]*m2[ 6]+m1[14]*m2[ 7]);
+		m[ 7] = btScalar(m1[ 3]*m2[ 4]+m1[ 7]*m2[ 5]+m1[11]*m2[ 6]+m1[15]*m2[ 7]);
+
+		m[ 8] = btScalar(m1[ 0]*m2[ 8]+m1[ 4]*m2[ 9]+m1[ 8]*m2[10]+m1[12]*m2[11]);
+		m[ 9] = btScalar(m1[ 1]*m2[ 8]+m1[ 5]*m2[ 9]+m1[ 9]*m2[10]+m1[13]*m2[11]);
+		m[10] = btScalar(m1[ 2]*m2[ 8]+m1[ 6]*m2[ 9]+m1[10]*m2[10]+m1[14]*m2[11]);
+		m[11] = btScalar(m1[ 3]*m2[ 8]+m1[ 7]*m2[ 9]+m1[11]*m2[10]+m1[15]*m2[11]);
+
+		m[12] = btScalar(m1[ 0]*m2[12]+m1[ 4]*m2[13]+m1[ 8]*m2[14]+m1[12]*m2[15]);
+		m[13] = btScalar(m1[ 1]*m2[12]+m1[ 5]*m2[13]+m1[ 9]*m2[14]+m1[13]*m2[15]);
+		m[14] = btScalar(m1[ 2]*m2[12]+m1[ 6]*m2[13]+m1[10]*m2[14]+m1[14]*m2[15]);
+		m[15] = btScalar(m1[ 3]*m2[12]+m1[ 7]*m2[13]+m1[11]*m2[14]+m1[15]*m2[15]);
+	}
+	void		setup(int size)
+	{
+		m_initialized=false;
+		m_occlusion=false;
+		// compute the size of the buffer
+		GLint		v[4];
+		GLdouble	m[16],p[16];
+		int			maxsize;
+		double		ratio;
+		glGetIntegerv(GL_VIEWPORT,v);
+		maxsize = (v[2] > v[3]) ? v[2] : v[3];
+		assert(maxsize > 0);
+		ratio = 1.0/(2*maxsize);
+		// ensure even number
+		m_sizes[0] = 2*((int)(size*v[2]*ratio+0.5));
+		m_sizes[1] = 2*((int)(size*v[3]*ratio+0.5));
+		m_scales[0]=btScalar(m_sizes[0]/2);
+		m_scales[1]=btScalar(m_sizes[1]/2);
+		m_offsets[0]=m_scales[0]+0.5f;
+		m_offsets[1]=m_scales[1]+0.5f;
+		// prepare matrix
+		// at this time of the rendering, the modelview matrix is the 
+		// world to camera transformation and the projection matrix is
+		// camera to clip transformation. combine both so that 
+		glGetDoublev(GL_MODELVIEW_MATRIX,m);
+		glGetDoublev(GL_PROJECTION_MATRIX,p);
+		CMmat4mul(m_wtc,p,m);
+	}
+	void		initialize()
+	{
+		size_t newsize = (m_sizes[0]*m_sizes[1])*sizeof(btScalar);
+		if (m_buffer)
+		{
+			// see if we can reuse
+			if (newsize > m_bufferSize)
+			{
+				free(m_buffer);
+				m_buffer = NULL;
+				m_bufferSize = 0;
+			}
+		}
+		if (!m_buffer)
+		{
+			m_buffer = (btScalar*)calloc(1, newsize);
+			m_bufferSize = newsize;
+		} else
+		{
+			// buffer exists already, just clears it
+			memset(m_buffer, 0, newsize);
+		}
+		// memory allocate must succeed
+		assert(m_buffer != NULL);
+		m_initialized = true;
+		m_occlusion = false;
+	}
+	void		SetModelMatrix(double *fl)
+	{
+		CMmat4mul(m_mtc,m_wtc,fl);
+		if (!m_initialized)
+			initialize();
+	}
 
+	// transform a segment in world coordinate to clip coordinate
+	void		transformW(const btVector3& x, btVector4& t)
+	{
+		t[0]	=	x[0]*m_wtc[0]+x[1]*m_wtc[4]+x[2]*m_wtc[8]+m_wtc[12];
+		t[1]	=	x[0]*m_wtc[1]+x[1]*m_wtc[5]+x[2]*m_wtc[9]+m_wtc[13];
+		t[2]	=	x[0]*m_wtc[2]+x[1]*m_wtc[6]+x[2]*m_wtc[10]+m_wtc[14];
+		t[3]	=	x[0]*m_wtc[3]+x[1]*m_wtc[7]+x[2]*m_wtc[11]+m_wtc[15];
+	}
+	void		transformM(const float* x, btVector4& t)
+	{
+		t[0]	=	x[0]*m_mtc[0]+x[1]*m_mtc[4]+x[2]*m_mtc[8]+m_mtc[12];
+		t[1]	=	x[0]*m_mtc[1]+x[1]*m_mtc[5]+x[2]*m_mtc[9]+m_mtc[13];
+		t[2]	=	x[0]*m_mtc[2]+x[1]*m_mtc[6]+x[2]*m_mtc[10]+m_mtc[14];
+		t[3]	=	x[0]*m_mtc[3]+x[1]*m_mtc[7]+x[2]*m_mtc[11]+m_mtc[15];
+	}
+	// convert polygon to device coordinates
+	static bool	project(btVector4* p,int n)
+	{
+		for(int i=0;i<n;++i)
+		{
+			const btScalar iw=1/p[i][3];
+			p[i][2]=1/p[i][3];
+			p[i][0]*=p[i][2];
+			p[i][1]*=p[i][2];
+		}
+		return(true);
+	}
+	// pi: closed polygon in clip coordinate, NP = number of segments
+	// po: same polygon with clipped segments removed
+	template <const int NP>
+	static int	clip(const btVector4* pi,btVector4* po)
+	{
+		btScalar	s[2*NP];
+		btVector4	pn[2*NP];
+		int			i, j, m, n, ni;
+		// deal with near clipping
+		for(i=0, m=0;i<NP;++i)
+		{
+			s[i]=pi[i][2]+pi[i][3];
+			if(s[i]<0) m+=1<<i;
+		}
+		if(m==((1<<NP)-1)) 
+			return(0);
+		if(m!=0)
+		{
+			for(i=NP-1,j=0,n=0;j<NP;i=j++)
+			{
+				const btVector4&	a=pi[i];
+				const btVector4&	b=pi[j];
+				const btScalar		t=s[i]/(a[3]+a[2]-b[3]-b[2]);
+				if((t>0)&&(t<1))
+				{
+					pn[n][0]	=	a[0]+(b[0]-a[0])*t;
+					pn[n][1]	=	a[1]+(b[1]-a[1])*t;
+					pn[n][2]	=	a[2]+(b[2]-a[2])*t;
+					pn[n][3]	=	a[3]+(b[3]-a[3])*t;
+					++n;
+				}
+				if(s[j]>0) pn[n++]=b;
+			}
+			// ready to test far clipping, start from the modified polygon
+			pi = pn;
+			ni = n;
+		} else
+		{
+			// no clipping on the near plane, keep same vector
+			ni = NP;
+		}
+		// now deal with far clipping
+		for(i=0, m=0;i<ni;++i)
+		{
+			s[i]=pi[i][2]-pi[i][3];
+			if(s[i]>0) m+=1<<i;
+		}
+		if(m==((1<<ni)-1)) 
+			return(0);
+		if(m!=0)
+		{
+			for(i=ni-1,j=0,n=0;j<ni;i=j++)
+			{
+				const btVector4&	a=pi[i];
+				const btVector4&	b=pi[j];
+				const btScalar		t=s[i]/(a[2]-a[3]-b[2]+b[3]);
+				if((t>0)&&(t<1))
+				{
+					po[n][0]	=	a[0]+(b[0]-a[0])*t;
+					po[n][1]	=	a[1]+(b[1]-a[1])*t;
+					po[n][2]	=	a[2]+(b[2]-a[2])*t;
+					po[n][3]	=	a[3]+(b[3]-a[3])*t;
+					++n;
+				}
+				if(s[j]<0) po[n++]=b;
+			}
+			return(n);
+		}
+		for(int i=0;i<ni;++i) po[i]=pi[i];
+		return(ni);
+	}
+	// write or check a triangle to buffer. a,b,c in device coordinates (-1,+1)
+	template <typename POLICY>
+	inline bool	draw(	const btVector4& a,
+						const btVector4& b,
+						const btVector4& c,
+						const float face,
+						const btScalar minarea)
+	{
+		const btScalar		a2=cross(b-a,c-a)[2];
+		if((face*a2)<0.f || btFabs(a2)<minarea)
+			return false;
+		// further down we are normally going to write to the Zbuffer, mark it so
+		POLICY::Occlusion(m_occlusion);
+
+		int x[3], y[3], ib=1, ic=2;
+		btScalar z[3];
+		x[0]=(int)(a.x()*m_scales[0]+m_offsets[0]);
+		y[0]=(int)(a.y()*m_scales[1]+m_offsets[1]);
+		z[0]=a.z();
+		if (a2 < 0.f)
+		{
+			// negative aire is possible with double face => must
+			// change the order of b and c otherwise the algorithm doesn't work
+			ib=2;
+			ic=1;
+		}
+		x[ib]=(int)(b.x()*m_scales[0]+m_offsets[0]);
+		x[ic]=(int)(c.x()*m_scales[0]+m_offsets[0]);
+		y[ib]=(int)(b.y()*m_scales[1]+m_offsets[1]);
+		y[ic]=(int)(c.y()*m_scales[1]+m_offsets[1]);
+		z[ib]=b.z();
+		z[ic]=c.z();
+		const int		mix=btMax(0,btMin(x[0],btMin(x[1],x[2])));
+		const int		mxx=btMin(m_sizes[0],1+btMax(x[0],btMax(x[1],x[2])));
+		const int		miy=btMax(0,btMin(y[0],btMin(y[1],y[2])));
+		const int		mxy=btMin(m_sizes[1],1+btMax(y[0],btMax(y[1],y[2])));
+		const int		width=mxx-mix;
+		const int		height=mxy-miy;
+		if ((width*height) <= 1)
+		{
+			// degenerated in at most one single pixel
+			btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
+			// use for loop to detect the case where width or height == 0
+			for(int iy=miy;iy<mxy;++iy)
+			{
+				for(int ix=mix;ix<mxx;++ix)
+				{
+					if(POLICY::Process(*scan,z[0])) 
+						return(true);
+					if(POLICY::Process(*scan,z[1])) 
+						return(true);
+					if(POLICY::Process(*scan,z[2])) 
+						return(true);
+				}
+			}
+		} else if (width == 1) 
+		{
+			// Degenerated in at least 2 vertical lines
+			// The algorithm below doesn't work when face has a single pixel width
+			// We cannot use general formulas because the plane is degenerated. 
+			// We have to interpolate along the 3 edges that overlaps and process each pixel.
+			// sort the y coord to make formula simpler
+			int ytmp;
+			btScalar ztmp;
+			if (y[0] > y[1]) { ytmp=y[1];y[1]=y[0];y[0]=ytmp;ztmp=z[1];z[1]=z[0];z[0]=ztmp; }
+			if (y[0] > y[2]) { ytmp=y[2];y[2]=y[0];y[0]=ytmp;ztmp=z[2];z[2]=z[0];z[0]=ztmp; }
+			if (y[1] > y[2]) { ytmp=y[2];y[2]=y[1];y[1]=ytmp;ztmp=z[2];z[2]=z[1];z[1]=ztmp; }
+			int	dy[]={	y[0]-y[1],
+						y[1]-y[2],
+						y[2]-y[0]};
+			btScalar dzy[3];
+			dzy[0] = (dy[0]) ? (z[0]-z[1])/dy[0] : btScalar(0.f);
+			dzy[1] = (dy[1]) ? (z[1]-z[2])/dy[1] : btScalar(0.f);
+			dzy[2] = (dy[2]) ? (z[2]-z[0])/dy[2] : btScalar(0.f);
+			btScalar v[3] = {	dzy[0]*(miy-y[0])+z[0],
+								dzy[1]*(miy-y[1])+z[1],
+								dzy[2]*(miy-y[2])+z[2] };
+			dy[0] = y[1]-y[0];
+			dy[1] = y[0]-y[1];
+			dy[2] = y[2]-y[0];
+			btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
+			for(int iy=miy;iy<mxy;++iy)
+			{
+				if(dy[0] >= 0 && POLICY::Process(*scan,v[0])) 
+					return(true);
+				if(dy[1] >= 0 && POLICY::Process(*scan,v[1])) 
+					return(true);
+				if(dy[2] >= 0 && POLICY::Process(*scan,v[2])) 
+					return(true);
+				scan+=m_sizes[0];
+				v[0] += dzy[0]; v[1] += dzy[1]; v[2] += dzy[2];
+				dy[0]--; dy[1]++, dy[2]--;
+			}
+		} else if (height == 1)
+		{
+			// Degenerated in at least 2 horizontal lines
+			// The algorithm below doesn't work when face has a single pixel width
+			// We cannot use general formulas because the plane is degenerated. 
+			// We have to interpolate along the 3 edges that overlaps and process each pixel.
+			int xtmp;
+			btScalar ztmp;
+			if (x[0] > x[1]) { xtmp=x[1];x[1]=x[0];x[0]=xtmp;ztmp=z[1];z[1]=z[0];z[0]=ztmp; }
+			if (x[0] > x[2]) { xtmp=x[2];x[2]=x[0];x[0]=xtmp;ztmp=z[2];z[2]=z[0];z[0]=ztmp; }
+			if (x[1] > x[2]) { xtmp=x[2];x[2]=x[1];x[1]=xtmp;ztmp=z[2];z[2]=z[1];z[1]=ztmp; }
+			int	dx[]={	x[0]-x[1],
+						x[1]-x[2],
+						x[2]-x[0]};
+			btScalar dzx[3];
+			dzx[0] = (dx[0]) ? (z[0]-z[1])/dx[0] : btScalar(0.f);
+			dzx[1] = (dx[1]) ? (z[1]-z[2])/dx[1] : btScalar(0.f);
+			dzx[2] = (dx[2]) ? (z[2]-z[0])/dx[2] : btScalar(0.f);
+			btScalar v[3] = { dzx[0]*(mix-x[0])+z[0],
+							  dzx[1]*(mix-x[1])+z[1],
+							  dzx[2]*(mix-x[2])+z[2] };
+			dx[0] = x[1]-x[0];
+			dx[1] = x[0]-x[1];
+			dx[2] = x[2]-x[0];
+			btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
+			for(int ix=mix;ix<mxx;++ix)
+			{
+				if(dx[0] >= 0 && POLICY::Process(*scan,v[0])) 
+					return(true);
+				if(dx[1] >= 0 && POLICY::Process(*scan,v[1])) 
+					return(true);
+				if(dx[2] >= 0 && POLICY::Process(*scan,v[2])) 
+					return(true);
+				scan++;
+				v[0] += dzx[0]; v[1] += dzx[1]; v[2] += dzx[2];
+				dx[0]--; dx[1]++, dx[2]--;
+			}
+		} else
+		{
+			// general case
+			const int		dx[]={	y[0]-y[1],
+									y[1]-y[2],
+									y[2]-y[0]};
+			const int		dy[]={	x[1]-x[0]-dx[0]*width,
+									x[2]-x[1]-dx[1]*width,
+									x[0]-x[2]-dx[2]*width};
+			const int		a=x[2]*y[0]+x[0]*y[1]-x[2]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0];
+			const btScalar	ia=1/(btScalar)a;
+			const btScalar	dzx=ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1]));
+			const btScalar	dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width);		
+			int				c[]={	miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0],
+									miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1],
+									miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]};
+			btScalar		v=ia*((z[2]*c[0])+(z[0]*c[1])+(z[1]*c[2]));
+			btScalar*		scan=&m_buffer[miy*m_sizes[0]];
+			for(int iy=miy;iy<mxy;++iy)
+			{
+				for(int ix=mix;ix<mxx;++ix)
+				{
+					if((c[0]>=0)&&(c[1]>=0)&&(c[2]>=0))
+					{
+						if(POLICY::Process(scan[ix],v)) 
+							return(true);
+					}
+					c[0]+=dx[0];c[1]+=dx[1];c[2]+=dx[2];v+=dzx;
+				}
+				c[0]+=dy[0];c[1]+=dy[1];c[2]+=dy[2];v+=dzy;
+				scan+=m_sizes[0];
+			}
+		}
+		return(false);
+	}
+	// clip than write or check a polygon 
+	template <const int NP,typename POLICY>
+	inline bool	clipDraw(	const btVector4* p,
+							const float face,
+							btScalar minarea)
+	{
+		btVector4	o[NP*2];
+		int			n=clip<NP>(p,o);
+		bool		earlyexit=false;
+		if (n)
+		{
+			project(o,n);
+			for(int i=2;i<n && !earlyexit;++i)
+			{
+				earlyexit|=draw<POLICY>(o[0],o[i-1],o[i],face,minarea);
+			}
+		}
+		return(earlyexit);
+	}
+	// add a triangle (in model coordinate)
+	// face =  0.f if face is double side, 
+	//      =  1.f if face is single sided and scale is positive
+	//      = -1.f if face is single sided and scale is negative
+	void		appendOccluderM(const float* a,
+								const float* b,
+								const float* c,
+								const float face)
+	{
+		btVector4	p[3];
+		transformM(a,p[0]);
+		transformM(b,p[1]);
+		transformM(c,p[2]);
+		clipDraw<3,WriteOCL>(p,face,btScalar(0.f));
+	}
+	// add a quad (in model coordinate)
+	void		appendOccluderM(const float* a,
+								const float* b,
+								const float* c,
+								const float* d,
+								const float face)
+	{	
+		btVector4	p[4];
+		transformM(a,p[0]);
+		transformM(b,p[1]);
+		transformM(c,p[2]);
+		transformM(d,p[3]);
+		clipDraw<4,WriteOCL>(p,face,btScalar(0.f));
+	}
+	// query occluder for a box (c=center, e=extend) in world coordinate
+	inline bool	queryOccluderW(	const btVector3& c,
+								const btVector3& e)
+	{
+		if (!m_occlusion)
+			// no occlusion yet, no need to check
+			return true;
+		btVector4	x[8];
+		transformW(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2]),x[0]);
+		transformW(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2]),x[1]);
+		transformW(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2]),x[2]);
+		transformW(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2]),x[3]);
+		transformW(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2]),x[4]);
+		transformW(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2]),x[5]);
+		transformW(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2]),x[6]);
+		transformW(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]),x[7]);
+		for(int i=0;i<8;++i)
+		{
+			// the box is clipped, it's probably a large box, don't waste our time to check
+			if((x[i][2]+x[i][3])<=0) return(true);
+		}
+		static const int	d[]={	1,0,3,2,
+									4,5,6,7,
+									4,7,3,0,
+									6,5,1,2,
+									7,6,2,3,
+									5,4,0,1};
+		for(int i=0;i<(sizeof(d)/sizeof(d[0]));)
+		{
+			const btVector4	p[]={	x[d[i++]],
+									x[d[i++]],
+									x[d[i++]],
+									x[d[i++]]};
+			if(clipDraw<4,QueryOCL>(p,1.f,0.f)) 
+				return(true);
+		}
+		return(false);
+	}
+};
+
+
+struct	DbvtCullingCallback : btDbvt::ICollide
+{
+	PHY_CullingCallback m_clientCallback;
+	void* m_userData;
+	OcclusionBuffer *m_ocb;
+
+	DbvtCullingCallback(PHY_CullingCallback clientCallback, void* userData)
+	{
+		m_clientCallback = clientCallback;
+		m_userData = userData;
+		m_ocb = NULL;
+	}
+	bool Descent(const btDbvtNode* node)
+	{
+		return(m_ocb->queryOccluderW(node->volume.Center(),node->volume.Extents()));
+	}
+	void Process(const btDbvtNode* node,btScalar depth)
+	{
+		Process(node);
+	}
+	void Process(const btDbvtNode* leaf)
+	{	
+		btBroadphaseProxy*	proxy=(btBroadphaseProxy*)leaf->data;
+		// the client object is a graphic controller
+		CcdGraphicController* ctrl = static_cast<CcdGraphicController*>(proxy->m_clientObject);
+		KX_ClientObjectInfo* info = (KX_ClientObjectInfo*)ctrl->getNewClientInfo();
+		if (m_ocb)
+		{
+			// means we are doing occlusion culling. Check if this object is an occluders
+			KX_GameObject* gameobj = KX_GameObject::GetClientObject(info);
+			if (gameobj && gameobj->GetOccluder())
+			{
+				double* fl = gameobj->GetOpenGLMatrixPtr()->getPointer();
+				// this will create the occlusion buffer if not already done
+				// and compute the transformation from model local space to clip space
+				m_ocb->SetModelMatrix(fl);
+				float face = (gameobj->IsNegativeScaling()) ? -1.0f : 1.0f;
+				// walk through the meshes and for each add to buffer
+				for (int i=0; i<gameobj->GetMeshCount(); i++)
+				{
+					RAS_MeshObject* meshobj = gameobj->GetMesh(i);
+					const float *v1, *v2, *v3, *v4;
+
+					int polycount = meshobj->NumPolygons();
+					for (int j=0; j<polycount; j++)
+					{
+						RAS_Polygon* poly = meshobj->GetPolygon(j);
+						switch (poly->VertexCount())
+						{
+						case 3:
+							v1 = poly->GetVertex(0)->getXYZ();
+							v2 = poly->GetVertex(1)->getXYZ();
+							v3 = poly->GetVertex(2)->getXYZ();
+							m_ocb->appendOccluderM(v1,v2,v3,((poly->IsTwoside())?0.f:face));
+							break;
+						case 4:
+							v1 = poly->GetVertex(0)->getXYZ();
+							v2 = poly->GetVertex(1)->getXYZ();
+							v3 = poly->GetVertex(2)->getXYZ();
+							v4 = poly->GetVertex(3)->getXYZ();
+							m_ocb->appendOccluderM(v1,v2,v3,v4,((poly->IsTwoside())?0.f:face));
+							break;
+						}
+					}
+				}
+			}
+		}
+		if (info)
+			(*m_clientCallback)(info, m_userData);
+	}
+};
+
+static OcclusionBuffer gOcb;
+bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes)
+{
+	if (!m_cullingTree)
+		return false;
+	DbvtCullingCallback dispatcher(callback, userData);
+	btVector3 planes_n[6];
+	btScalar planes_o[6];
+	if (nplanes > 6)
+		nplanes = 6;
+	for (int i=0; i<nplanes; i++)
+	{
+		planes_n[i].setValue(planes[i][0], planes[i][1], planes[i][2]);
+		planes_o[i] = planes[i][3];
+	}
+	// if occlusionRes != 0 => occlusion culling
+	if (occlusionRes)
+	{
+		gOcb.setup(occlusionRes);
+		dispatcher.m_ocb = &gOcb;
+		// occlusion culling, the direction of the view is taken from the first plan which MUST be the near plane
+		btDbvt::collideOCL(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);
+		btDbvt::collideOCL(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);		
+	}else 
+	{
+		btDbvt::collideKDOP(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,nplanes,dispatcher);
+		btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher);		
+	}
+	return true;
+}
 
 int	CcdPhysicsEnvironment::getNumContactPoints()
 {
@@ -1211,6 +1828,13 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
 
 	if (NULL != m_broadphase)
 		delete m_broadphase;
+
+	if (NULL != m_cullingTree)
+		delete m_cullingTree;
+
+	if (NULL != m_cullingCache)
+		delete m_cullingCache;
+
 }
 
 
@@ -1465,8 +2089,8 @@ PHY_IPhysicsController*	CcdPhysicsEnvironment::CreateSphereController(float radi
 {
 	
 	CcdConstructionInfo	cinfo;
-	// memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list
-	cinfo.m_collisionShape = new btSphereShape(radius);
+	memset(&cinfo, 0, sizeof(cinfo)); /* avoid uninitialized values */
+	cinfo.m_collisionShape = new btSphereShape(radius); // memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list
 	cinfo.m_MotionState = 0;
 	cinfo.m_physicsEnv = this;
 	// declare this object as Dyamic rather then static!!
@@ -1925,7 +2549,7 @@ int			CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
 {
 	CcdConstructionInfo	cinfo;
-
+	memset(&cinfo, 0, sizeof(cinfo)); /* avoid uninitialized values */
 	// we don't need a CcdShapeConstructionInfo for this shape:
 	// it is simple enough for the standard copy constructor (see CcdPhysicsController::GetReplica)
 	cinfo.m_collisionShape = new btConeShape(coneradius,coneheight);
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index 2f1f0bb254b7f8e8c16242871a271b09b581ed57..5f9fb9511d625fb7ef118b08c4ef3b1c74284a6b 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -20,6 +20,7 @@ subject to the following restrictions:
 #include <vector>
 #include <set>
 class CcdPhysicsController;
+class CcdGraphicController;
 #include "LinearMath/btVector3.h"
 #include "LinearMath/btTransform.h"
 
@@ -40,6 +41,7 @@ class btDispatcher;
 class WrapperVehicle;
 class btPersistentManifold;
 class btBroadphaseInterface;
+struct btDbvtBroadphase;
 class btOverlappingPairCache;
 class btIDebugDraw;
 class PHY_IVehicle;
@@ -58,7 +60,10 @@ protected:
 	btIDebugDraw*	m_debugDrawer;
 	
 	class btDefaultCollisionConfiguration* m_collisionConfiguration;
-	class btBroadphaseInterface*			m_broadphase;
+    class btBroadphaseInterface*		m_broadphase;	// broadphase for dynamic world
+	// for culling only
+	btOverlappingPairCache*				m_cullingCache;
+	struct btDbvtBroadphase*			m_cullingTree;	// broadphase for culling
 
 	//solver iterations
 	int	m_numIterations;
@@ -77,7 +82,7 @@ protected:
 	void	processFhSprings(double curTime,float timeStep);
 
 	public:
-		CcdPhysicsEnvironment(btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0);
+		CcdPhysicsEnvironment(bool useDbvtCulling, btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0);
 
 		virtual		~CcdPhysicsEnvironment();
 
@@ -109,7 +114,7 @@ protected:
 		virtual	void		beginFrame();
 		virtual void		endFrame() {};
 		/// Perform an integration step of duration 'timeStep'.
-		virtual	bool		proceedDeltaTime(double curTime,float timeStep);
+		virtual	bool		proceedDeltaTime(double curTime,float timeStep,float interval);
 		
 		virtual void		debugDrawWorld();
 //		virtual bool		proceedDeltaTimeOneStep(float timeStep);
@@ -167,6 +172,7 @@ protected:
 		btTypedConstraint*	getConstraintById(int constraintId);
 
 		virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+		virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes);
 
 
 		//Methods for gamelogic collision/physics callbacks
@@ -200,7 +206,12 @@ protected:
 
 		void	refreshCcdPhysicsController(CcdPhysicsController* ctrl);
 
+		void	addCcdGraphicController(CcdGraphicController* ctrl);
+
+		void	removeCcdGraphicController(CcdGraphicController* ctrl);
+
 		btBroadphaseInterface*	getBroadphase();
+		btDbvtBroadphase*	getCullingTree() { return m_cullingTree; }
 
 		btDispatcher*	getDispatcher();
 		
diff --git a/source/gameengine/Physics/Bullet/Makefile b/source/gameengine/Physics/Bullet/Makefile
index bf3573138f74f837dfdcc9265d69086d78f2b5fc..48e537bb6a35681c3cf3402ac919c409d71ae340 100644
--- a/source/gameengine/Physics/Bullet/Makefile
+++ b/source/gameengine/Physics/Bullet/Makefile
@@ -39,9 +39,16 @@ CPPFLAGS += -I$(NAN_BULLET2)/include
 CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
 CPPFLAGS += -I$(NAN_STRING)/include
 CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) 
+CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include    
 CPPFLAGS += -I../../../kernel/gen_system
 CPPFLAGS += -I../../Physics/common
 CPPFLAGS += -I../../Physics/Dummy
 CPPFLAGS += -I../../Rasterizer
+CPPFLAGS += -I../../Ketsji
+CPPFLAGS += -I../../Expressions
+CPPFLAGS += -I../../GameLogic
+CPPFLAGS += -I../../SceneGraph
 CPPFLAGS += -I../../../../source/blender/makesdna
 
diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript
index 868a4d66af0b137698679c9aca14691adb28b128..115ab8bf7303dc26a5a9b19f6f498fbe0f41a3e7 100644
--- a/source/gameengine/Physics/Bullet/SConscript
+++ b/source/gameengine/Physics/Bullet/SConscript
@@ -1,11 +1,23 @@
 #!/usr/bin/python
 Import ('env')
 
-sources = 'CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp'
+sources = 'CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp CcdGraphicController.cpp'
 
-incs = '. ../common #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/blender/makesdna'
+incs = '. ../common'
+incs += ' #source/kernel/gen_system'
+incs += ' #intern/string'
+incs += ' #intern/moto/include'
+incs += ' #extern/glew/include'
+incs += ' #source/gameengine/Rasterizer'
+incs += ' #source/gameengine/Ketsji'
+incs += ' #source/gameengine/Expressions'
+incs += ' #source/gameengine/GameLogic'
+incs += ' #source/gameengine/SceneGraph'
+incs += ' #source/blender/makesdna'
+incs += ' #intern/SoundSystem'
 
 incs += ' ' + env['BF_BULLET_INC']
+incs += ' ' + env['BF_PYTHON_INC']
 
 cxxflags = []
 if env['OURPLATFORM']=='win32-vc':
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
index ba196b5cf5506f59a6055357990b18cfa180e501..e41574ff181b3021749be1b511dcf65b90dcc2eb 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -57,7 +57,7 @@ void DummyPhysicsEnvironment::endFrame()
 
 
 
-bool		DummyPhysicsEnvironment::proceedDeltaTime(double  curTime,float timeStep)
+bool		DummyPhysicsEnvironment::proceedDeltaTime(double  curTime,float timeStep,float interval)
 {
 	//step physics simulation, typically perform
 	
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index a92b1e7f4a6d5734d14c40cabb13cab3f534d089..397a1ba4218346d50a869db4f8206aec8ba7ee12 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -48,7 +48,7 @@ public:
 	virtual void		beginFrame();
 	virtual void		endFrame();
 // Perform an integration step of duration 'timeStep'.
-	virtual	bool		proceedDeltaTime(double  curTime,float timeStep);
+	virtual	bool		proceedDeltaTime(double  curTime,float timeStep,float interval);
 	virtual	void		setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep);
 	virtual	float		getFixedTimeStep();
 
@@ -70,6 +70,7 @@ public:
 	}
 
 	virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+	virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes) { return false; }
 
 
 	//gamelogic callbacks
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.h b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
index d8ee54935d7d18e1ad1b8fd0122023a4c9cb87ad..415bc1e3982e55f2190d719eeac14c2209c467e5 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsController.h
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
@@ -144,6 +144,11 @@ public:
 	void GetWorldPosition(MT_Point3& pos);
 	void GetWorldScaling(MT_Vector3& scale);
 
+	float GetLinVelocityMin() const { return 0.f; }
+	void  SetLinVelocityMin(float val) { }
+	float GetLinVelocityMax() const { return 0.f; }
+	void  SetLinVelocityMax(float val) { }
+
 
 //	void	SetSumoObject(class SM_Object* sumoObj)	{
 //		m_sumoObj = sumoObj;
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
index 3be5e027345db5383ed42a4f664b105f865312a7..cc6d5654ec9d1c9132c3980056ffa002772603aa 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
@@ -81,7 +81,7 @@ float		SumoPhysicsEnvironment::getFixedTimeStep()
 }
 
 
-bool		SumoPhysicsEnvironment::proceedDeltaTime(double  curTime,float timeStep)
+bool		SumoPhysicsEnvironment::proceedDeltaTime(double  curTime,float timeStep,float interval)
 {
 	
 	bool result = false;
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
index 65b07a7a0bee5a68f437590f27cb6e184c795c41..c2b443a2b382a5498b07103895d9bdbf98b69a05 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
@@ -54,7 +54,7 @@ public:
 	virtual	void		beginFrame();
 	virtual void		endFrame();
 // Perform an integration step of duration 'timeStep'.
-	virtual	bool		proceedDeltaTime(double  curTime,float timeStep);
+	virtual	bool		proceedDeltaTime(double  curTime,float timeStep,float interval);
 	virtual	void		setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep);
 	virtual	float		getFixedTimeStep();
 
@@ -76,6 +76,7 @@ public:
 	}
 
 	virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+	virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes) { return false; }
 
 	
 	//gamelogic callbacks
diff --git a/source/gameengine/Physics/common/CMakeLists.txt b/source/gameengine/Physics/common/CMakeLists.txt
index a28fabe0c3a572b42a242a89f2f1ef4176afc766..41b2687fe381dc36d499b86f10b89009906c1233 100644
--- a/source/gameengine/Physics/common/CMakeLists.txt
+++ b/source/gameengine/Physics/common/CMakeLists.txt
@@ -24,7 +24,7 @@
 #
 # ***** END GPL LICENSE BLOCK *****
 
-SET(SRC PHY_IMotionState.cpp PHY_IPhysicsController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp)
+SET(SRC PHY_IMotionState.cpp PHY_IController.cpp PHY_IPhysicsController.cpp PHY_IGraphicController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp)
 
 SET(INC
   .
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
index c5cf92b553ae171c78058349ccb70f77563179f6..7ce40001af75dca5c756982e375581cafecb1d89 100644
--- a/source/gameengine/Physics/common/PHY_DynamicTypes.h
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -19,12 +19,42 @@ subject to the following restrictions:
 
 
 
-
+struct KX_ClientObjectInfo;
 class PHY_Shape;
 
 struct	PHY__Vector3
 {
 	float	m_vec[4];
+
+	operator const float* () const 
+	{ 
+		return &m_vec[0];
+	}	
+	operator float* () 
+	{ 
+		return &m_vec[0];
+	}	
+};
+
+struct	PHY__Vector4
+{
+	float	m_vec[4];
+	PHY__Vector4() {}
+	void setValue(const float *value)
+	{
+		m_vec[0] = *value++;
+		m_vec[1] = *value++;
+		m_vec[2] = *value++;
+		m_vec[3] = *value++;
+	}
+	void setValue(const double *value)
+	{
+		m_vec[0] = (float)(*value++);
+		m_vec[1] = (float)(*value++);
+		m_vec[2] = (float)(*value++);
+		m_vec[3] = (float)(*value++);
+	}
+
 	operator const float* () const 
 	{ 
 		return &m_vec[0];
@@ -34,6 +64,7 @@ struct	PHY__Vector3
 		return &m_vec[0];
 	}	
 };
+
 //typedef 	float	PHY__Vector3[4];
 
 enum
@@ -59,7 +90,7 @@ enum
 										   void *client_object1,
 										   void *client_object2,
 										   const PHY_CollData *coll_data);
-		
+	typedef void (*PHY_CullingCallback)(KX_ClientObjectInfo* info, void* param);
 
 
 /// PHY_PhysicsType enumerates all possible Physics Entities.
diff --git a/source/gameengine/Physics/common/PHY_IController.cpp b/source/gameengine/Physics/common/PHY_IController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..47fe9a9eea824e0086a99a537d9046d2647c7e86
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IController.cpp
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "PHY_IController.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+PHY_IController::~PHY_IController()
+{
+
+}
+
diff --git a/source/gameengine/Physics/common/PHY_IController.h b/source/gameengine/Physics/common/PHY_IController.h
new file mode 100644
index 0000000000000000000000000000000000000000..45e93f9d24e2cac9952fc190df2b838ffa07bd30
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IController.h
@@ -0,0 +1,53 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef PHY_ICONTROLLER_H
+#define PHY_ICONTROLLER_H
+
+#include "PHY_DynamicTypes.h"
+
+
+
+/**
+	PHY_IController is the abstract simplified Interface to objects 
+	controlled by the physics engine. This includes the physics objects
+	and the graphics object for view frustrum and occlusion culling.
+*/
+class PHY_IController	
+{
+	public:
+		
+		virtual ~PHY_IController();
+		// clientinfo for raycasts for example
+		virtual	void*				getNewClientInfo()=0;
+		virtual	void				setNewClientInfo(void* clientinfo)=0;
+
+};
+
+#endif //PHY_ICONTROLLER_H
+
diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.cpp b/source/gameengine/Physics/common/PHY_IGraphicController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4dccecd3d290dcb6dac0ce60d0bb00b37f2a2f69
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IGraphicController.cpp
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "PHY_IGraphicController.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+PHY_IGraphicController::~PHY_IGraphicController()
+{
+
+}
+
diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.h b/source/gameengine/Physics/common/PHY_IGraphicController.h
new file mode 100644
index 0000000000000000000000000000000000000000..470d42cb84a31f94d88e30924a36c7771b8e3bb1
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IGraphicController.h
@@ -0,0 +1,59 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef PHY_IGRAPHICCONTROLLER_H
+#define PHY_IGRAPHICCONTROLLER_H
+
+#include "PHY_IController.h"
+
+
+
+/**
+	PHY_IPhysicsController is the abstract simplified Interface to a physical object.
+	It contains the IMotionState and IDeformableMesh Interfaces.
+*/
+class PHY_IGraphicController : public PHY_IController
+{
+
+	public:
+		
+		virtual ~PHY_IGraphicController();
+		/**
+			SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+		*/
+		virtual bool SetGraphicTransform()=0;
+		virtual void Activate(bool active=true)=0;
+		virtual void setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax)=0;
+		virtual void setLocalAabb(const float* aabbMin,const float* aabbMax)=0;
+
+		virtual PHY_IGraphicController*	GetReplica(class PHY_IMotionState* motionstate) {return 0;}
+
+};
+
+#endif //PHY_IGRAPHICCONTROLLER_H
+
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h
index d759b0aeff4a1e775698da2c1639289142537ba5..64bb810ee7c6420f678047f29c3dded94de62d61 100644
--- a/source/gameengine/Physics/common/PHY_IMotionState.h
+++ b/source/gameengine/Physics/common/PHY_IMotionState.h
@@ -43,6 +43,8 @@ class	PHY_IMotionState
 		virtual void	getWorldPosition(float& posX,float& posY,float& posZ)=0;
 		virtual void	getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)=0;
 		virtual void	getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)=0;
+		// ori = array 12 floats, [0..3] = first column + 0, [4..7] = second colum, [8..11] = third column
+		virtual void	getWorldOrientation(float* ori)=0;
 		
 		virtual void	setWorldPosition(float posX,float posY,float posZ)=0;
 		virtual	void	setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)=0;
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index 884e14cfb5af124482a068ca0fae4311cb87f547..770426b48db613558c3238348eb5b7608cb510f8 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -29,7 +29,7 @@
 #ifndef PHY_IPHYSICSCONTROLLER_H
 #define PHY_IPHYSICSCONTROLLER_H
 
-#include "PHY_DynamicTypes.h"
+#include "PHY_IController.h"
 
 
 
@@ -37,7 +37,7 @@
 	PHY_IPhysicsController is the abstract simplified Interface to a physical object.
 	It contains the IMotionState and IDeformableMesh Interfaces.
 */
-class PHY_IPhysicsController	
+class PHY_IPhysicsController : public PHY_IController
 {
 
 	public:
@@ -82,9 +82,7 @@ class PHY_IPhysicsController
 
 		// dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted 
 		virtual	void		setRigidBody(bool rigid)=0;
-		// clientinfo for raycasts for example
-		virtual	void*				getNewClientInfo()=0;
-		virtual	void				setNewClientInfo(void* clientinfo)=0;
+
 		virtual PHY_IPhysicsController*	GetReplica() {return 0;}
 
 		virtual void	calcXform() =0;
@@ -92,6 +90,12 @@ class PHY_IPhysicsController
 		virtual float GetMargin() const=0;
 		virtual float GetRadius() const=0;
 		virtual void  SetRadius(float margin) = 0;
+
+		virtual float GetLinVelocityMin() const=0;
+		virtual void  SetLinVelocityMin(float val) = 0;
+		virtual float GetLinVelocityMax() const=0;
+		virtual void  SetLinVelocityMax(float val) = 0;
+		
 		PHY__Vector3	GetWorldPosition(PHY__Vector3& localpos);
 
 };
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index 226ba3a7e744e2c3f9d1eb0c14d0e62347d202fc..a3605669f70b1aeeecc2ead635775378258d1eab 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -89,7 +89,7 @@ class PHY_IPhysicsEnvironment
 		virtual	void		beginFrame() = 0;
 		virtual void		endFrame() = 0;
 		/// Perform an integration step of duration 'timeStep'.
-		virtual	bool		proceedDeltaTime(double curTime,float timeStep)=0;
+		virtual	bool		proceedDeltaTime(double curTime,float timeStep,float interval)=0;
 		///draw debug lines (make sure to call this during the render phase, otherwise lines are not drawn properly)
 		virtual void		debugDrawWorld(){}
 		virtual	void		setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)=0;
@@ -142,6 +142,10 @@ class PHY_IPhysicsEnvironment
 
 		virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0;
 
+		//culling based on physical broad phase
+		// the plane number must be set as follow: near, far, left, right, top, botton
+		// the near plane must be the first one and must always be present, it is used to get the direction of the view
+		virtual bool cullingTest(PHY_CullingCallback callback, void *userData, PHY__Vector4* planeNormals, int planeNumber, int occlusionRes) = 0;
 
 		//Methods for gamelogic collision/physics callbacks
 		//todo:
diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h
index 32e63ac2f6d2d8406d60e108a01d2d016eff6679..0249fc3118aa6f9a0a248ae2857d9d7f471a928b 100644
--- a/source/gameengine/Physics/common/PHY_Pro.h
+++ b/source/gameengine/Physics/common/PHY_Pro.h
@@ -35,9 +35,11 @@
 struct PHY_ShapeProps {
 	MT_Scalar  m_mass;                  // Total mass
 	MT_Scalar  m_inertia;               // Inertia, should be a tensor some time 
-	MT_Scalar  m_lin_drag;              // Linear drag (air, water) 0 = concrete, 1 = vacuum 
-	MT_Scalar  m_ang_drag;              // Angular drag
+	MT_Scalar  m_lin_drag;              // Linear drag (air, water) 0 = concrete, 1 = vacuum, inverted and called dampening in blenders UI
+	MT_Scalar  m_ang_drag;              // Angular drag, inverted and called dampening in blenders UI
 	MT_Scalar  m_friction_scaling[3];   // Scaling for anisotropic friction. Component in range [0, 1]   
+	MT_Scalar  m_clamp_vel_min;			// Clamp the minimum velocity, this ensures an object moves at a minimum speed unless its stationary
+	MT_Scalar  m_clamp_vel_max;			// Clamp max velocity
 	bool       m_do_anisotropic;        // Should I do anisotropic friction? 
 	bool       m_do_fh;                 // Should the object have a linear Fh spring?
 	bool       m_do_rot_fh;             // Should the object have an angular Fh spring?
diff --git a/source/gameengine/Physics/common/SConscript b/source/gameengine/Physics/common/SConscript
index 474536e1f76fc01169ce0af8e12484e394039714..05c6f17a4a074127c7a7e35560cfd55c80a4471d 100644
--- a/source/gameengine/Physics/common/SConscript
+++ b/source/gameengine/Physics/common/SConscript
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 Import ('env')
 
-sources = 'PHY_IMotionState.cpp PHY_IPhysicsController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp'
+sources = 'PHY_IMotionState.cpp PHY_IController.cpp PHY_IPhysicsController.cpp PHY_IGraphicController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp'
 
 incs = '. ../Dummy #intern/moto/include'
 
diff --git a/source/gameengine/PyDoc/BL_ActionActuator.py b/source/gameengine/PyDoc/BL_ActionActuator.py
index 3e95befe16b8fc7849e1c6ee2b929b895dc9cde8..455f83d5ce7eabee8ef701d87db0098222e4771a 100644
--- a/source/gameengine/PyDoc/BL_ActionActuator.py
+++ b/source/gameengine/PyDoc/BL_ActionActuator.py
@@ -1,7 +1,9 @@
 # $Id$
 # Documentation for BL_ActionActuator
+import SCA_ILogicBrick
 from SCA_IActuator import *
 
+
 class BL_ActionActuator(SCA_IActuator):
 	"""
 	Action Actuators apply an action to an actor.
@@ -10,7 +12,7 @@ class BL_ActionActuator(SCA_IActuator):
 	@type action: string
 	@ivar start: Specifies the starting frame of the animation.
 	@type start: float
-	@type end: Specifies the ending frame of the animation.
+	@ivar end: Specifies the ending frame of the animation.
 	@type end: float
 	@ivar blendin: Specifies the number of frames of animation to generate when making transitions between actions.
 	@type blendin: float
@@ -25,11 +27,9 @@ class BL_ActionActuator(SCA_IActuator):
 	@ivar blendTime: Sets the internal frame timer. This property must be in
 						the range from 0.0 to blendin.
 	@type blendTime: float
-	@ivar type: The operation mode of the actuator.
-					KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER,
-					KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND
+	@ivar type: The operation mode of the actuator. KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND
 	@type type: integer
-	@ivar continue: The actions continue option, True or False.
+	@ivar useContinue: The actions continue option, True or False.
 					When True, the action will always play from where last left off,
 					otherwise negative events to this actuator will reset it to its start frame.
 	@type: boolean
diff --git a/source/gameengine/PyDoc/BL_Shader.py b/source/gameengine/PyDoc/BL_Shader.py
new file mode 100644
index 0000000000000000000000000000000000000000..10e8b7c94efd948bf47a5ea8fc37a4bc1d846207
--- /dev/null
+++ b/source/gameengine/PyDoc/BL_Shader.py
@@ -0,0 +1,231 @@
+
+from PyObjectPlus import *
+
+class BL_Shader(PyObjectPlus):
+	"""
+	BL_Shader GLSL shaders.
+	
+	All placeholders have a __ prefix
+	"""
+	
+	def __setUniformfv(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+
+	def __delSource(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getFragmentProg(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getVertexProg(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __isValid(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setAttrib(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setNumberOfPasses(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setSampler(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setSource(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniform1f(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniform1i(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniform2f(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniform2i(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniform3f(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniform3i(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniform4f(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniform4i(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniformDef(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniformMatrix3(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniformMatrix4(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setUniformiv(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __validate(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
diff --git a/source/gameengine/PyDoc/BL_ShapeActionActuator.py b/source/gameengine/PyDoc/BL_ShapeActionActuator.py
index 209ff4e5580ba2c927e4ee997db71b3e1e6d2c15..e1e8b0397497034df96867d55dc153d2fc6ec526 100644
--- a/source/gameengine/PyDoc/BL_ShapeActionActuator.py
+++ b/source/gameengine/PyDoc/BL_ShapeActionActuator.py
@@ -1,6 +1,7 @@
 # $Id$
 # Documentation for BL_ShapeActionActuator
 from SCA_IActuator import *
+from SCA_ILogicBrick import *
 
 class BL_ShapeActionActuator(SCA_IActuator):
 	"""
@@ -10,7 +11,7 @@ class BL_ShapeActionActuator(SCA_IActuator):
 	@type action: string
 	@ivar start: Specifies the starting frame of the shape animation.
 	@type start: float
-	@type end: Specifies the ending frame of the shape animation.
+	@ivar end: Specifies the ending frame of the shape animation.
 	@type end: float
 	@ivar blendin: Specifies the number of frames of animation to generate when making transitions between actions.
 	@type blendin: float
diff --git a/source/gameengine/PyDoc/CListValue.py b/source/gameengine/PyDoc/CListValue.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f60e8a7bc2264b37661653d2996e1e34771986b
--- /dev/null
+++ b/source/gameengine/PyDoc/CListValue.py
@@ -0,0 +1,61 @@
+from CPropValue import *
+
+class CListValue(CPropValue):
+	"""
+	CListValue
+	
+	This is a list like object used in the game engine internally that behaves similar to a python list in most ways.
+	
+	As well as the normal index lookup.
+	C{val= clist[i]}
+	
+	CListValue supports string lookups.
+	C{val= scene.objects["OBCube"]}
+	
+	Other operations such as C{len(clist), list(clist), clist[0:10]} are also supported.
+	"""
+	def append(val):
+		"""
+		Add an item to the list (like pythons append)
+		
+		Warning: Appending values to the list can cause crashes when the list is used internally by the game engine.
+		"""
+
+	def count(val):
+		"""
+		Count the number of instances of a value in the list.
+		
+		@rtype: integer
+		@return: number of instances
+		"""
+	def index(val):
+		"""
+		Return the index of a value in the list.
+		
+		@rtype: integer
+		@return: The index of the value in the list.
+		"""
+	def reverse():
+		"""
+		Reverse the order of the list.
+		"""
+	def from_id(id):
+		"""
+		This is a funtion especially for the game engine to return a value with a spesific id.
+		
+		Since object names are not always unique, the id of an object can be used to get an object from the CValueList.
+		
+		Example.
+			
+		C{myObID = id(gameObject)}
+		
+		C{...}
+		
+		C{ob= scene.objects.from_id(myObID)}
+		
+		Where myObID is an int or long from the id function.
+		
+		This has the advantage that you can store the id in places you could not store a gameObject.
+		
+		Warning: the id is derived from a memory location and will be different each time the game engine starts.
+		"""
\ No newline at end of file
diff --git a/source/gameengine/PyDoc/CPropValue.py b/source/gameengine/PyDoc/CPropValue.py
new file mode 100644
index 0000000000000000000000000000000000000000..498b47ab0133fcbf0c19f4e618de5184e65910ee
--- /dev/null
+++ b/source/gameengine/PyDoc/CPropValue.py
@@ -0,0 +1,8 @@
+# 
+# Documentation for CValue class
+from CValue import *
+class CPropValue(CValue):
+	"""
+	This class has no python functions
+	"""
+	pass
diff --git a/source/gameengine/PyDoc/CValue.py b/source/gameengine/PyDoc/CValue.py
new file mode 100644
index 0000000000000000000000000000000000000000..e9b0563955b4834281586e456016bac4e35c0767
--- /dev/null
+++ b/source/gameengine/PyDoc/CValue.py
@@ -0,0 +1,8 @@
+# 
+# Documentation for CValue class
+from PyObjectPlus import *
+class CValue(PyObjectPlus):
+	"""
+	This class has no python functions
+	"""
+	pass
diff --git a/source/gameengine/PyDoc/GameKeys.py b/source/gameengine/PyDoc/GameKeys.py
index 1a0a737718eb5028170cfe2e2944583ec305c0f1..e798f6c901b7a595a6e4b482973c3bffc01610fa 100644
--- a/source/gameengine/PyDoc/GameKeys.py
+++ b/source/gameengine/PyDoc/GameKeys.py
@@ -5,126 +5,6 @@ Documentation for the GameKeys module.
 
 This module holds key constants for the SCA_KeyboardSensor.
 
-Alphabet keys
--------------
-	- AKEY
-	- BKEY
-	- CKEY
-	- DKEY
-	- EKEY
-	- FKEY
-	- GKEY
-	- HKEY
-	- IKEY
-	- JKEY
-	- KKEY
-	- LKEY
-	- MKEY
-	- NKEY
-	- OKEY
-	- PKEY
-	- QKEY
-	- RKEY
-	- SKEY
-	- TKEY
-	- UKEY
-	- VKEY
-	- WKEY
-	- XKEY
-	- YKEY
-	- ZKEY
-
-Number keys
------------
-	- ZEROKEY
-	- ONEKEY
-	- TWOKEY
-	- THREEKEY
-	- FOURKEY
-	- FIVEKEY
-	- SIXKEY
-	- SEVENKEY
-	- EIGHTKEY
-	- NINEKEY
-
-Shift Modifiers
----------------
-	- CAPSLOCKKEY
-
-	- LEFTCTRLKEY
-	- LEFTALTKEY
-	- RIGHTALTKEY
-	- RIGHTCTRLKEY
-	- RIGHTSHIFTKEY
-	- LEFTSHIFTKEY
-
-Arrow Keys
-----------
-	- LEFTARROWKEY
-	- DOWNARROWKEY
-	- RIGHTARROWKEY
-	- UPARROWKEY
-
-Numberpad Keys
---------------
-	- PAD0
-	- PAD1
-	- PAD2
-	- PAD3
-	- PAD4
-	- PAD5
-	- PAD6
-	- PAD7
-	- PAD8
-	- PAD9
-	- PADPERIOD
-	- PADSLASHKEY
-	- PADASTERKEY
-	- PADMINUS
-	- PADENTER
-	- PADPLUSKEY
-
-Function Keys
--------------
-	- F1KEY
-	- F2KEY
-	- F3KEY
-	- F4KEY
-	- F5KEY
-	- F6KEY
-	- F7KEY
-	- F8KEY
-	- F9KEY
-	- F10KEY
-	- F11KEY
-	- F12KEY
-
-Other Keys
-----------
-	- ACCENTGRAVEKEY
-	- BACKSLASHKEY
-	- BACKSPACEKEY
-	- COMMAKEY
-	- DELKEY
-	- ENDKEY
-	- EQUALKEY
-	- ESCKEY
-	- HOMEKEY
-	- INSERTKEY
-	- LEFTBRACKETKEY
-	- LINEFEEDKEY
-	- MINUSKEY
-	- PAGEDOWNKEY
-	- PAGEUPKEY
-	- PAUSEKEY
-	- PERIODKEY
-	- QUOTEKEY
-	- RIGHTBRACKETKEY
-	- RETKEY
-	- SEMICOLONKEY
-	- SLASHKEY
-	- SPACEKEY
-	- TABKEY
 
 Example::
 	# Set a connected keyboard sensor to accept F1
@@ -134,26 +14,20 @@ Example::
 	co = GameLogic.getCurrentController()
 	# 'Keyboard' is a keyboard sensor
 	sensor = co.getSensor('Keyboard')
-	sensor.setKey(GameKeys.F1KEY)
+	sensor.key = GameKeys.F1KEY
 
 Example::
 	# Do the all keys thing
 	import GameLogic
 	import GameKeys
-
-	# status: these should be added to a module somewhere
-	KX_NO_INPUTSTATUS = 0
-	KX_JUSTACTIVATED = 1
-	KX_ACTIVE = 2
-	KX_JUSTRELEASED = 3
-		
+	
 	co = GameLogic.getCurrentController()
 	# 'Keyboard' is a keyboard sensor
 	sensor = co.getSensor('Keyboard')
-	keylist = sensor.getPressedKeys()
+	keylist = sensor.events
 	for key in keylist:
 		# key[0] == GameKeys.keycode, key[1] = status
-		if key[1] == KX_JUSTACTIVATED:
+		if key[1] == GameLogic.KX_INPUT_JUST_ACTIVATED:
 			if key[0] == GameKeys.WKEY:
 				# Activate Forward!
 			if key[0] == GameKeys.SKEY:
@@ -162,7 +36,120 @@ Example::
 				# Activate Left!
 			if key[0] == GameKeys.DKEY:
 				# Activate Right!
-		
+
+@group Alphabet keys: AKEY, BKEY, CKEY, DKEY, EKEY, FKEY, GKEY, HKEY, IKEY, JKEY, KKEY, LKEY, MKEY, NKEY, OKEY, PKEY, QKEY, RKEY, SKEY, TKEY, UKEY, VKEY, WKEY, XKEY, YKEY, ZKEY
+@var AKEY:
+@var BKEY:
+@var CKEY:
+@var DKEY:
+@var EKEY:
+@var FKEY:
+@var GKEY:
+@var HKEY:
+@var IKEY:
+@var JKEY:
+@var KKEY:
+@var LKEY:
+@var MKEY:
+@var NKEY:
+@var OKEY:
+@var PKEY:
+@var QKEY:
+@var RKEY:
+@var SKEY:
+@var TKEY:
+@var UKEY:
+@var VKEY:
+@var WKEY:
+@var XKEY:
+@var YKEY:
+@var ZKEY:
+
+@group Number keys: ZEROKEY, ONEKEY, TWOKEY, THREEKEY, FOURKEY, FIVEKEY, SIXKEY, SEVENKEY, EIGHTKEY, NINEKEY
+@var ZEROKEY:
+@var ONEKEY:
+@var TWOKEY:
+@var THREEKEY:
+@var FOURKEY:
+@var FIVEKEY:
+@var SIXKEY:
+@var SEVENKEY:
+@var EIGHTKEY:
+@var NINEKEY:
+
+@group Modifiers: CAPSLOCKKEY, LEFTCTRLKEY, LEFTALTKEY, RIGHTALTKEY, RIGHTCTRLKEY, RIGHTSHIFTKEY, LEFTSHIFTKEY
+@var CAPSLOCKKEY:
+@var LEFTCTRLKEY:
+@var LEFTALTKEY:
+@var RIGHTALTKEY:
+@var RIGHTCTRLKEY:
+@var RIGHTSHIFTKEY:
+@var LEFTSHIFTKEY:
+
+@group Arrow Keys: LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY
+@var LEFTARROWKEY:
+@var DOWNARROWKEY:
+@var RIGHTARROWKEY:
+@var UPARROWKEY:
+
+@group Numberpad Keys: PAD0, PAD1, PAD2, PAD3, PAD4, PAD5, PAD6, PAD7, PAD8, PAD9, PADPERIOD, PADSLASHKEY, PADASTERKEY, PADMINUS, PADENTER, PADPLUSKEY
+@var PAD0:
+@var PAD1:
+@var PAD2:
+@var PAD3:
+@var PAD4:
+@var PAD5:
+@var PAD6:
+@var PAD7:
+@var PAD8:
+@var PAD9:
+@var PADPERIOD:
+@var PADSLASHKEY:
+@var PADASTERKEY:
+@var PADMINUS:
+@var PADENTER:
+@var PADPLUSKEY:
+
+@group Function Keys: F1KEY, F2KEY, F3KEY, F4KEY, F5KEY, F6KEY, F7KEY, F8KEY, F9KEY, F10KEY, F11KEY, F12KEY
+@var F1KEY:
+@var F2KEY:
+@var F3KEY:
+@var F4KEY:
+@var F5KEY:
+@var F6KEY:
+@var F7KEY:
+@var F8KEY:
+@var F9KEY:
+@var F10KEY:
+@var F11KEY:
+@var F12KEY:
+
+@group Other Keys: ACCENTGRAVEKEY, BACKSLASHKEY, BACKSPACEKEY, COMMAKEY, DELKEY, ENDKEY, EQUALKEY, ESCKEY, HOMEKEY, INSERTKEY, LEFTBRACKETKEY, LINEFEEDKEY, MINUSKEY, PAGEDOWNKEY, PAGEUPKEY, PAUSEKEY, PERIODKEY, QUOTEKEY, RIGHTBRACKETKEY, RETKEY, SEMICOLONKEY, SLASHKEY, SPACEKEY, TABKEY
+@var ACCENTGRAVEKEY:
+@var BACKSLASHKEY:
+@var BACKSPACEKEY:
+@var COMMAKEY:
+@var DELKEY:
+@var ENDKEY:
+@var EQUALKEY:
+@var ESCKEY:
+@var HOMEKEY:
+@var INSERTKEY:
+@var LEFTBRACKETKEY:
+@var LINEFEEDKEY:
+@var MINUSKEY:
+@var PAGEDOWNKEY:
+@var PAGEUPKEY:
+@var PAUSEKEY:
+@var PERIODKEY:
+@var QUOTEKEY:
+@var RIGHTBRACKETKEY:
+@var RETKEY:
+@var SEMICOLONKEY:
+@var SLASHKEY:
+@var SPACEKEY:
+@var TABKEY:
+
 """
 
 def EventToString(event):
@@ -173,3 +160,15 @@ def EventToString(event):
 	@param event: key event from GameKeys or the keyboard sensor.
 	@rtype: string
 	"""
+	
+def EventToCharacter(event, shift):
+	"""
+	Return the string name of a key event. Returns an empty string if the event cant be represented as a character.
+	
+	@type event: int
+	@param event: key event from GameKeys or the keyboard sensor.
+	@type shift: bool
+	@param shift: set to true if shift is held.
+	@rtype: string
+	"""
+
diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py
index f158b41097534d9829eecc7c86ced84318ea87eb..d16c00ca27217690beecd80eef3542451dd99e45 100644
--- a/source/gameengine/PyDoc/GameLogic.py
+++ b/source/gameengine/PyDoc/GameLogic.py
@@ -3,10 +3,17 @@
 Documentation for the GameLogic Module.
 =======================================
 
-	There are only three importable modules in the game engine:
+	Modules available in the game engine:
 		- GameLogic
 		- L{GameKeys}
 		- L{Rasterizer}
+		- L{GameTypes}
+	
+	Undocumented modules:
+		- VideoTexture
+		- CValue
+		- Expression
+		- PhysicsConstraints
 	
 	All the other modules are accessible through the methods in GameLogic.
 	
@@ -18,7 +25,7 @@ Documentation for the GameLogic Module.
 		
 		# To get the game object this controller is on:
 		obj = co.getOwner()
-	L{KX_GameObject} and L{KX_Camera} or L{KX_Light} methods are
+	L{KX_GameObject} and L{KX_Camera} or L{KX_LightObject} methods are
 	available depending on the type of object::
 		# To get a sensor linked to this controller.
 		# "sensorname" is the name of the sensor as defined in the Blender interface.
@@ -52,28 +59,32 @@ Documentation for the GameLogic Module.
 		actuator = co.getActuator("actuatorname")
 		
 		# Activate an actuator
-		GameLogic.addActiveActuator(actuator, True)
+		controller.activate(actuator)
 		
 	See the actuator's reference for available methods:
+		- L{2DFilterActuator<SCA_2DFilterActuator.SCA_2DFilterActuator>}
 		- L{ActionActuator<BL_ActionActuator.BL_ActionActuator>}
 		- L{AddObjectActuator<KX_SCA_AddObjectActuator.KX_SCA_AddObjectActuator>}
 		- L{CameraActuator<KX_CameraActuator.KX_CameraActuator>}
 		- L{CDActuator<KX_CDActuator.KX_CDActuator>}
 		- L{ConstraintActuator<KX_ConstraintActuator.KX_ConstraintActuator>}
+		- L{DynamicActuator<KX_SCA_DynamicActuator.KX_SCA_DynamicActuator>}
 		- L{EndObjectActuator<KX_SCA_EndObjectActuator.KX_SCA_EndObjectActuator>}
 		- L{GameActuator<KX_GameActuator.KX_GameActuator>}
 		- L{IpoActuator<KX_IpoActuator.KX_IpoActuator>}
 		- L{NetworkMessageActuator<KX_NetworkMessageActuator.KX_NetworkMessageActuator>}
 		- L{ObjectActuator<KX_ObjectActuator.KX_ObjectActuator>}
+		- L{ParentActuator<KX_ParentActuator.KX_ParentActuator>}
 		- L{PropertyActuator<SCA_PropertyActuator.SCA_PropertyActuator>}
 		- L{RandomActuator<SCA_RandomActuator.SCA_RandomActuator>}
 		- L{ReplaceMeshActuator<KX_SCA_ReplaceMeshActuator.KX_SCA_ReplaceMeshActuator>}
 		- L{SceneActuator<KX_SceneActuator.KX_SceneActuator>}
+		- L{ShapeActionActuator<BL_ShapeActionActuator.BL_ShapeActionActuator>}
 		- L{SoundActuator<KX_SoundActuator.KX_SoundActuator>}
+		- L{StateActuator<KX_StateActuator.KX_StateActuator>}
 		- L{TrackToActuator<KX_TrackToActuator.KX_TrackToActuator>}
 		- L{VisibilityActuator<KX_VisibilityActuator.KX_VisibilityActuator>}
-		- L{DynamicActuator<KX_SCA_DynamicActuator.KX_SCA_DynamicActuator>}
-	
+
 	Most logic brick's methods are accessors for the properties available in the logic buttons.
 	Consult the logic bricks documentation for more information on how each logic brick works.
 	
@@ -100,20 +111,31 @@ Documentation for the GameLogic Module.
 @var KX_PROPSENSOR_CHANGED:	Activate when the property changes
 @var KX_PROPSENSOR_EXPRESSION:	Activate when the expression matches
 
-@group Constraint Actuator: KX_CONSTRAINTACT_LOCX, KX_CONSTRAINTACT_LOCY, KX_CONSTRAINTACT_LOCZ, KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY, KX_CONSTRAINTACT_ROTZ
+
+
+
+@group Constraint Actuator: KX_CONSTRAINTACT_LOCX, KX_CONSTRAINTACT_LOCY, KX_CONSTRAINTACT_LOCZ, KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY, KX_CONSTRAINTACT_ROTZ, KX_CONSTRAINTACT_DIRNX, KX_CONSTRAINTACT_DIRNY, KX_CONSTRAINTACT_DIRPX, KX_CONSTRAINTACT_DIRPY, KX_CONSTRAINTACT_ORIX, KX_CONSTRAINTACT_ORIY, KX_CONSTRAINTACT_ORIZ
 @var KX_CONSTRAINTACT_LOCX: See L{KX_ConstraintActuator}
 @var KX_CONSTRAINTACT_LOCY: See L{KX_ConstraintActuator}
 @var KX_CONSTRAINTACT_LOCZ: See L{KX_ConstraintActuator}
 @var KX_CONSTRAINTACT_ROTX: See L{KX_ConstraintActuator}
 @var KX_CONSTRAINTACT_ROTY: See L{KX_ConstraintActuator}
 @var KX_CONSTRAINTACT_ROTZ: See L{KX_ConstraintActuator}
+@var KX_CONSTRAINTACT_DIRNX: See L{KX_ConstraintActuator}
+@var KX_CONSTRAINTACT_DIRNY: See L{KX_ConstraintActuator}
+@var KX_CONSTRAINTACT_DIRPX: See L{KX_ConstraintActuator}
+@var KX_CONSTRAINTACT_DIRPY: See L{KX_ConstraintActuator}
+@var KX_CONSTRAINTACT_ORIX: See L{KX_ConstraintActuator}
+@var KX_CONSTRAINTACT_ORIY: See L{KX_ConstraintActuator}
+@var KX_CONSTRAINTACT_ORIZ: See L{KX_ConstraintActuator}
 
-@group IPO Actuator: KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND
+@group IPO Actuator: KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND, KX_IPOACT_FROM_PROP
 @var KX_IPOACT_PLAY:	 See L{KX_IpoActuator}
 @var KX_IPOACT_PINGPONG:	 See L{KX_IpoActuator}
 @var KX_IPOACT_FLIPPER:	 See L{KX_IpoActuator}
 @var KX_IPOACT_LOOPSTOP:	 See L{KX_IpoActuator}
 @var KX_IPOACT_LOOPEND:	 See L{KX_IpoActuator}
+@var KX_IPOACT_FROM_PROP:	 See L{KX_IpoActuator}
 
 @group Random Distributions: KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, KX_RANDOMACT_BOOL_BERNOUILLI, KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, KX_RANDOMACT_INT_POISSON, KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL
 @var KX_RANDOMACT_BOOL_CONST:		See L{SCA_RandomActuator}
@@ -165,8 +187,133 @@ Documentation for the GameLogic Module.
 @var KX_DYN_DISABLE_RIGID_BODY:	See L{KX_SCA_DynamicActuator}
 @var KX_DYN_SET_MASS:			See L{KX_SCA_DynamicActuator}
 
+@group Game Actuator: KX_GAME_LOAD, KX_GAME_START, KX_GAME_RESTART, KX_GAME_QUIT, KX_GAME_SAVECFG, KX_GAME_LOADCFG
+@var KX_Game_LOAD:		See L{KX_GameActuator}
+@var KX_Game_START:		See L{KX_GameActuator}
+@var KX_Game_RESTART:	See L{KX_GameActuator}
+@var KX_Game_QUIT:		See L{KX_GameActuator}
+@var KX_Game_SAVECFG:	See L{KX_GameActuator}
+@var KX_Game_LOADCFG:	See L{KX_GameActuator}
+
+@group Scene Actuator: KX_SCENE_RESTART, KX_SCENE_SET_SCENE, KX_SCENE_SET_CAMERA, KX_SCENE_ADD_FRONT_SCENE, KX_SCENE_ADD_BACK_SCENE, KX_SCENE_REMOVE_SCENE, KX_SCENE_SUSPEND, KX_SCENE_RESUME
+KX_SCENE_RESTART:			See L{KX_SceneActuator}
+KX_SCENE_SET_SCENE:			See L{KX_SceneActuator}
+KX_SCENE_SET_CAMERA:		See L{KX_SceneActuator}
+KX_SCENE_ADD_FRONT_SCENE:	See L{KX_SceneActuator}
+KX_SCENE_ADD_BACK_SCENE:	See L{KX_SceneActuator}
+KX_SCENE_REMOVE_SCENE:		See L{KX_SceneActuator}
+KX_SCENE_SUSPEND:			See L{KX_SceneActuator}
+KX_SCENE_RESUME:			See L{KX_SceneActuator}
+
+@group Input Status: KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED
+@var KX_INPUT_NONE:				See L{SCA_MouseSensor}
+@var KX_INPUT_JUST_ACTIVATED:	See L{SCA_MouseSensor}
+@var KX_INPUT_ACTIVE:			See L{SCA_MouseSensor}
+@var KX_INPUT_JUST_RELEASED:	See L{SCA_MouseSensor}
+
+
+@group Mouse Buttons: KX_MOUSE_BUT_LEFT, KX_MOUSE_BUT_MIDDLE, KX_MOUSE_BUT_RIGHT
+@var KX_MOUSE_BUT_LEFT:		See L{SCA_MouseSensor}
+@var KX_MOUSE_BUT_MIDDLE:	See L{SCA_MouseSensor}
+@var KX_MOUSE_BUT_RIGHT:	See L{SCA_MouseSensor}
+
+@group States: KX_STATE1, KX_STATE10, KX_STATE11, KX_STATE12, KX_STATE13, KX_STATE14, KX_STATE15, KX_STATE16, KX_STATE17, KX_STATE18, KX_STATE19, KX_STATE2, KX_STATE20, KX_STATE21, KX_STATE22, KX_STATE23, KX_STATE24, KX_STATE25, KX_STATE26, KX_STATE27, KX_STATE28, KX_STATE29, KX_STATE3, KX_STATE30, KX_STATE4, KX_STATE5, KX_STATE6, KX_STATE7, KX_STATE8, KX_STATE9, KX_STATE_OP_CLR, KX_STATE_OP_CPY, KX_STATE_OP_NEG, KX_STATE_OP_SET
+@var KX_STATE1:
+@var KX_STATE10:
+@var KX_STATE11:
+@var KX_STATE12:
+@var KX_STATE13:
+@var KX_STATE14:
+@var KX_STATE15:
+@var KX_STATE16:
+@var KX_STATE17:
+@var KX_STATE18:
+@var KX_STATE19:
+@var KX_STATE2:
+@var KX_STATE20:
+@var KX_STATE21:
+@var KX_STATE22:
+@var KX_STATE23:
+@var KX_STATE24:
+@var KX_STATE25:
+@var KX_STATE26:
+@var KX_STATE27:
+@var KX_STATE28:
+@var KX_STATE29:
+@var KX_STATE3:
+@var KX_STATE30:
+@var KX_STATE4:
+@var KX_STATE5:
+@var KX_STATE6:
+@var KX_STATE7:
+@var KX_STATE8:
+@var KX_STATE9:
+@var KX_STATE_OP_CLR:
+@var KX_STATE_OP_CPY:
+@var KX_STATE_OP_NEG:
+@var KX_STATE_OP_SET:
+
+@group UNSORTED: BL_DST_ALPHA, BL_DST_COLOR, BL_ONE, BL_ONE_MINUS_DST_ALPHA, BL_ONE_MINUS_DST_COLOR, BL_ONE_MINUS_SRC_ALPHA, BL_ONE_MINUS_SRC_COLOR, BL_SRC_ALPHA, BL_SRC_ALPHA_SATURATE, BL_SRC_COLOR, BL_ZERO, CAM_POS, CONSTANT_TIMER, KX_ACT_CONSTRAINT_DISTANCE, KX_ACT_CONSTRAINT_DOROTFH, KX_ACT_CONSTRAINT_FHNX, KX_ACT_CONSTRAINT_FHNY, KX_ACT_CONSTRAINT_FHNZ, KX_ACT_CONSTRAINT_FHPX, KX_ACT_CONSTRAINT_FHPY, KX_ACT_CONSTRAINT_FHPZ, KX_ACT_CONSTRAINT_LOCAL, KX_ACT_CONSTRAINT_MATERIAL, KX_ACT_CONSTRAINT_NORMAL, KX_ACT_CONSTRAINT_PERMANENT, MODELMATRIX, MODELMATRIX_INVERSE, MODELMATRIX_INVERSETRANSPOSE, MODELMATRIX_TRANSPOSE, MODELVIEWMATRIX, MODELVIEWMATRIX_INVERSE, MODELVIEWMATRIX_INVERSETRANSPOSE, MODELVIEWMATRIX_TRANSPOSE, RAS_2DFILTER_BLUR, RAS_2DFILTER_CUSTOMFILTER, RAS_2DFILTER_DILATION, RAS_2DFILTER_DISABLED, RAS_2DFILTER_ENABLED, RAS_2DFILTER_EROSION, RAS_2DFILTER_GRAYSCALE, RAS_2DFILTER_INVERT, RAS_2DFILTER_LAPLACIAN, RAS_2DFILTER_MOTIONBLUR, RAS_2DFILTER_NOFILTER, RAS_2DFILTER_PREWITT, RAS_2DFILTER_SEPIA, RAS_2DFILTER_SHARPEN, RAS_2DFILTER_SOBEL, SHD_TANGENT, VIEWMATRIX, VIEWMATRIX_INVERSE, VIEWMATRIX_INVERSETRANSPOSE, VIEWMATRIX_TRANSPOSE
+@var BL_DST_ALPHA:
+@var BL_DST_COLOR:
+@var BL_ONE:
+@var BL_ONE_MINUS_DST_ALPHA:
+@var BL_ONE_MINUS_DST_COLOR:
+@var BL_ONE_MINUS_SRC_ALPHA:
+@var BL_ONE_MINUS_SRC_COLOR:
+@var BL_SRC_ALPHA:
+@var BL_SRC_ALPHA_SATURATE:
+@var BL_SRC_COLOR:
+@var BL_ZERO:
+@var CAM_POS:
+@var CONSTANT_TIMER:
+@var KX_ACT_CONSTRAINT_DISTANCE:
+@var KX_ACT_CONSTRAINT_DOROTFH:
+@var KX_ACT_CONSTRAINT_FHNX:
+@var KX_ACT_CONSTRAINT_FHNY:
+@var KX_ACT_CONSTRAINT_FHNZ:
+@var KX_ACT_CONSTRAINT_FHPX:
+@var KX_ACT_CONSTRAINT_FHPY:
+@var KX_ACT_CONSTRAINT_FHPZ:
+@var KX_ACT_CONSTRAINT_LOCAL:
+@var KX_ACT_CONSTRAINT_MATERIAL:
+@var KX_ACT_CONSTRAINT_NORMAL:
+@var KX_ACT_CONSTRAINT_PERMANENT:
+@var MODELMATRIX:
+@var MODELMATRIX_INVERSE:
+@var MODELMATRIX_INVERSETRANSPOSE:
+@var MODELMATRIX_TRANSPOSE:
+@var MODELVIEWMATRIX:
+@var MODELVIEWMATRIX_INVERSE:
+@var MODELVIEWMATRIX_INVERSETRANSPOSE:
+@var MODELVIEWMATRIX_TRANSPOSE:
+@var RAS_2DFILTER_BLUR:
+@var RAS_2DFILTER_CUSTOMFILTER:
+@var RAS_2DFILTER_DILATION:
+@var RAS_2DFILTER_DISABLED:
+@var RAS_2DFILTER_ENABLED:
+@var RAS_2DFILTER_EROSION:
+@var RAS_2DFILTER_GRAYSCALE:
+@var RAS_2DFILTER_INVERT:
+@var RAS_2DFILTER_LAPLACIAN:
+@var RAS_2DFILTER_MOTIONBLUR:
+@var RAS_2DFILTER_NOFILTER:
+@var RAS_2DFILTER_PREWITT:
+@var RAS_2DFILTER_SEPIA:
+@var RAS_2DFILTER_SHARPEN:
+@var RAS_2DFILTER_SOBEL:
+@var SHD_TANGENT:
+@var VIEWMATRIX:
+@var VIEWMATRIX_INVERSE:
+@var VIEWMATRIX_INVERSETRANSPOSE:
+@var VIEWMATRIX_TRANSPOSE:
+
+@group Deprecated: addActiveActuator
 """
 
+# TODO
+# globalDict
+# error
 
 def getCurrentController():
 	"""
@@ -180,14 +327,35 @@ def getCurrentScene():
 	
 	@rtype: L{KX_Scene}
 	"""
+def getSceneList():
+	"""
+	Gets a list of the current scenes loaded in the game engine.
+	
+	@note: Scenes in your blend file that have not been converted wont be in this list. This list will only contain scenes such as overlays scenes.
+	
+	@rtype: list of L{KX_Scene}
+	"""
 def addActiveActuator(actuator, activate):
 	"""
-	Activates the given actuator.
+	Activates the given actuator. (B{deprecated})
 	
 	@type actuator: L{SCA_IActuator} or the actuator name as a string.
 	@type activate: boolean
 	@param activate: whether to activate or deactivate the given actuator.
 	"""
+def sendMessage(subject, body="", to="", message_from=""):
+	"""
+	Sends a message to sensors in any active scene.
+	
+	@param subject: The subject of the message
+	@type subject: string
+	@param body: The body of the message (optional)
+	@type body: string
+	@param to: The name of the object to send the message to (optional)
+	@type to: string
+	@param message_from: The name of the object that the message is coming from (optional)
+	@type message_from: string
+	"""
 def getRandomFloat():
 	"""
 	Returns a random floating point value in the range [0...1)
@@ -212,6 +380,21 @@ def stopDSP():
 	Only the fmod sound driver supports this.
 	DSP can be computationally expensive.
 	"""
+def getMaxLogicFrame():
+	"""
+	Gets the maximum number of logic frame per render frame.
+	
+	@return: The maximum number of logic frame per render frame
+	@rtype: interger
+	"""
+def setMaxLogicFrame(maxlogic):
+	"""
+	Sets the maximum number of logic frame that are executed per render frame.
+	This does not affect the physic system that still runs at full frame rate.	
+	 
+	@param maxlogic: The new maximum number of logic frame per render frame. Valid values: 1..5
+	@type maxlogic: integer
+	"""
 def getLogicTicRate():
 	"""
 	Gets the logic update frequency.
@@ -224,7 +407,7 @@ def setLogicTicRate(ticrate):
 	Sets the logic update frequency.
 	
 	The logic update frequency is the number of times logic bricks are executed every second.
-	The default is 30 Hz.
+	The default is 60 Hz.
 	
 	@param ticrate: The new logic update frequency (in Hz).
 	@type ticrate: float
@@ -279,3 +462,7 @@ def getBlendFileList(path = "//"):
 	@return: A list of filenames, with no directory prefix
 	@rtype: list
 	"""
+def PrintGLInfo():
+	"""
+	Prints GL Extension Info into the console
+	"""
\ No newline at end of file
diff --git a/source/gameengine/PyDoc/GameTypes.py b/source/gameengine/PyDoc/GameTypes.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b07a18247c05252ff98d7ebe79b107f4d414495
--- /dev/null
+++ b/source/gameengine/PyDoc/GameTypes.py
@@ -0,0 +1,75 @@
+# $Id$
+"""
+GameEngine Types
+================
+@var BL_ActionActuator: L{BL_ActionActuator<BL_ActionActuator.BL_ActionActuator>}
+@var BL_Shader: L{BL_Shader<BL_Shader.BL_Shader>}
+@var BL_ShapeActionActuator: L{BL_ShapeActionActuator<BL_ShapeActionActuator.BL_ShapeActionActuator>}
+@var CListValue: L{CListValue<CListValue.CListValue>}
+@var CValue: L{CValue<CValue.CValue>}
+@var KX_BlenderMaterial: L{KX_BlenderMaterial<KX_BlenderMaterial.KX_BlenderMaterial>}
+@var KX_CDActuator: L{KX_CDActuator<KX_CDActuator.KX_CDActuator>}
+@var KX_Camera: L{KX_Camera<KX_Camera.KX_Camera>}
+@var KX_CameraActuator: L{KX_CameraActuator<KX_CameraActuator.KX_CameraActuator>}
+@var KX_ConstraintActuator: L{KX_ConstraintActuator<KX_ConstraintActuator.KX_ConstraintActuator>}
+@var KX_ConstraintWrapper: L{KX_ConstraintWrapper<KX_ConstraintWrapper.KX_ConstraintWrapper>}
+@var KX_GameActuator: L{KX_GameActuator<KX_GameActuator.KX_GameActuator>}
+@var KX_GameObject: L{KX_GameObject<KX_GameObject.KX_GameObject>}
+@var KX_IpoActuator: L{KX_IpoActuator<KX_IpoActuator.KX_IpoActuator>}
+@var KX_LightObject: L{KX_LightObject<KX_LightObject.KX_LightObject>}
+@var KX_MeshProxy: L{KX_MeshProxy<KX_MeshProxy.KX_MeshProxy>}
+@var KX_MouseFocusSensor: L{KX_MouseFocusSensor<KX_MouseFocusSensor.KX_MouseFocusSensor>}
+@var KX_NearSensor: L{KX_NearSensor<KX_NearSensor.KX_NearSensor>}
+@var KX_NetworkMessageActuator: L{KX_NetworkMessageActuator<KX_NetworkMessageActuator.KX_NetworkMessageActuator>}
+@var KX_NetworkMessageSensor: L{KX_NetworkMessageSensor<KX_NetworkMessageSensor.KX_NetworkMessageSensor>}
+@var KX_ObjectActuator: L{KX_ObjectActuator<KX_ObjectActuator.KX_ObjectActuator>}
+@var KX_ParentActuator: L{KX_ParentActuator<KX_ParentActuator.KX_ParentActuator>}
+@var KX_PhysicsObjectWrapper: L{KX_PhysicsObjectWrapper<KX_PhysicsObjectWrapper.KX_PhysicsObjectWrapper>}
+@var KX_PolyProxy: L{KX_PolyProxy<KX_PolyProxy.KX_PolyProxy>}
+@var KX_PolygonMaterial: L{KX_PolygonMaterial<KX_PolygonMaterial.KX_PolygonMaterial>}
+@var KX_RadarSensor: L{KX_RadarSensor<KX_RadarSensor.KX_RadarSensor>}
+@var KX_RaySensor: L{KX_RaySensor<KX_RaySensor.KX_RaySensor>}
+@var KX_SCA_AddObjectActuator: L{KX_SCA_AddObjectActuator<KX_SCA_AddObjectActuator.KX_SCA_AddObjectActuator>}
+@var KX_SCA_DynamicActuator: L{KX_SCA_DynamicActuator<KX_SCA_DynamicActuator.KX_SCA_DynamicActuator>}
+@var KX_SCA_EndObjectActuator: L{KX_SCA_EndObjectActuator<KX_SCA_EndObjectActuator.KX_SCA_EndObjectActuator>}
+@var KX_SCA_ReplaceMeshActuator: L{KX_SCA_ReplaceMeshActuator<KX_SCA_ReplaceMeshActuator.KX_SCA_ReplaceMeshActuator>}
+@var KX_Scene: L{KX_Scene<KX_Scene.KX_Scene>}
+@var KX_SceneActuator: L{KX_SceneActuator<KX_SceneActuator.KX_SceneActuator>}
+@var KX_SoundActuator: L{KX_SoundActuator<KX_SoundActuator.KX_SoundActuator>}
+@var KX_StateActuator: L{KX_StateActuator<KX_StateActuator.KX_StateActuator>}
+@var KX_TouchSensor: L{KX_TouchSensor<KX_TouchSensor.KX_TouchSensor>}
+@var KX_TrackToActuator: L{KX_TrackToActuator<KX_TrackToActuator.KX_TrackToActuator>}
+@var KX_VehicleWrapper: L{KX_VehicleWrapper<KX_VehicleWrapper.KX_VehicleWrapper>}
+@var KX_VertexProxy: L{KX_VertexProxy<KX_VertexProxy.KX_VertexProxy>}
+@var KX_VisibilityActuator: L{KX_VisibilityActuator<KX_VisibilityActuator.KX_VisibilityActuator>}
+@var PyObjectPlus: L{PyObjectPlus<PyObjectPlus.PyObjectPlus>}
+@var SCA_2DFilterActuator: L{SCA_2DFilterActuator<SCA_2DFilterActuator.SCA_2DFilterActuator>}
+@var SCA_ANDController: L{SCA_ANDController<SCA_ANDController.SCA_ANDController>}
+@var SCA_ActuatorSensor: L{SCA_ActuatorSensor<SCA_ActuatorSensor.SCA_ActuatorSensor>}
+@var SCA_AlwaysSensor: L{SCA_AlwaysSensor<SCA_AlwaysSensor.SCA_AlwaysSensor>}
+@var SCA_DelaySensor: L{SCA_DelaySensor<SCA_DelaySensor.SCA_DelaySensor>}
+@var SCA_ILogicBrick: L{SCA_ILogicBrick<SCA_ILogicBrick.SCA_ILogicBrick>}
+@var SCA_IObject: L{SCA_IObject<SCA_IObject.SCA_IObject>}
+@var SCA_ISensor: L{SCA_ISensor<SCA_ISensor.SCA_ISensor>}
+@var SCA_JoystickSensor: L{SCA_JoystickSensor<SCA_JoystickSensor.SCA_JoystickSensor>}
+@var SCA_KeyboardSensor: L{SCA_KeyboardSensor<SCA_KeyboardSensor.SCA_KeyboardSensor>}
+@var SCA_MouseSensor: L{SCA_MouseSensor<SCA_MouseSensor.SCA_MouseSensor>}
+@var SCA_NANDController: L{SCA_NANDController<SCA_NANDController.SCA_NANDController>}
+@var SCA_NORController: L{SCA_NORController<SCA_NORController.SCA_NORController>}
+@var SCA_ORController: L{SCA_ORController<SCA_ORController.SCA_ORController>}
+@var SCA_PropertyActuator: L{SCA_PropertyActuator<SCA_PropertyActuator.SCA_PropertyActuator>}
+@var SCA_PropertySensor: L{SCA_PropertySensor<SCA_PropertySensor.SCA_PropertySensor>}
+@var SCA_PythonController: L{SCA_PythonController<SCA_PythonController.SCA_PythonController>}
+@var SCA_RandomActuator: L{SCA_RandomActuator<SCA_RandomActuator.SCA_RandomActuator>}
+@var SCA_RandomSensor: L{SCA_RandomSensor<SCA_RandomSensor.SCA_RandomSensor>}
+@var SCA_XNORController: L{SCA_XNORController<SCA_XNORController.SCA_XNORController>}
+@var SCA_XORController: L{SCA_XORController<SCA_XORController.SCA_XORController>}
+"""
+
+if 0:
+	# Use to print out all the links
+	for i in a.split('\n'):
+		if i.startswith('@var'):
+			var = i.split(' ')[1].split(':')[0]
+			print '@var %s: L{%s<%s.%s>}' % (var, var, var, var)
+
diff --git a/source/gameengine/PyDoc/KX_BlenderMaterial.py b/source/gameengine/PyDoc/KX_BlenderMaterial.py
new file mode 100644
index 0000000000000000000000000000000000000000..c70a7dddcca6e04fbf785b6f5dbfe93d59f09ae2
--- /dev/null
+++ b/source/gameengine/PyDoc/KX_BlenderMaterial.py
@@ -0,0 +1,41 @@
+
+from PyObjectPlus import *
+
+class KX_BlenderMaterial(PyObjectPlus): # , RAS_IPolyMaterial)
+	"""
+	KX_BlenderMaterial
+	
+	All placeholders have a __ prefix
+	"""
+	
+	def __getShader(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+
+	def __setBlending(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getMaterialIndex(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
diff --git a/source/gameengine/PyDoc/KX_CDActuator.py b/source/gameengine/PyDoc/KX_CDActuator.py
index ffc8ddefa43344acc15cd697a7f76c9c55f816b6..e1067674e7eed992a42e1d69c593da0a44452cf1 100644
--- a/source/gameengine/PyDoc/KX_CDActuator.py
+++ b/source/gameengine/PyDoc/KX_CDActuator.py
@@ -3,13 +3,15 @@
 from SCA_IActuator import *
 
 class KX_CDActuator(SCA_IActuator):
-    """
-    CD Controller actuator.
-    @ivar volume: controls the volume to set the CD to. 0.0 = silent, 1.0 = max volume.
-    @type volume: float
-    @ivar track: the track selected to be played
-    @type track: integer
-    """
+	"""
+	CD Controller actuator.
+	@ivar volume: controls the volume to set the CD to. 0.0 = silent, 1.0 = max volume.
+	@type volume: float
+	@ivar track: the track selected to be played
+	@type track: integer
+	@ivar gain: the gain (volume) of the CD between 0.0 and 1.0.
+	@type gain: float
+	"""
 	def startCD():
 		"""
 		Starts the CD playing.
@@ -26,17 +28,17 @@ class KX_CDActuator(SCA_IActuator):
 		"""
 		Resumes the CD after a pause.
 		"""
-    def playAll():
-        """
-        Plays the CD from the beginning.
-        """
-    def playTrack(trackNumber):
-        """
-        Plays the track selected.
-        """
+	def playAll():
+		"""
+		Plays the CD from the beginning.
+		"""
+	def playTrack(trackNumber):
+		"""
+		Plays the track selected.
+		"""
 	def setGain(gain):
 		"""
-        DEPRECATED: Use the volume property.
+		DEPRECATED: Use the volume property.
 		Sets the gain (volume) of the CD.
 		
 		@type gain: float
@@ -44,7 +46,7 @@ class KX_CDActuator(SCA_IActuator):
 		"""
 	def getGain():
 		"""
-        DEPRECATED: Use the volume property.
+		DEPRECATED: Use the volume property.
 		Gets the current gain (volume) of the CD.
 		
 		@rtype: float
diff --git a/source/gameengine/PyDoc/KX_Camera.py b/source/gameengine/PyDoc/KX_Camera.py
index 4cadf1c0ed007f8b07a8184fe930afd8fde1019e..5c54935192a63477b291273912a14c062e623384 100644
--- a/source/gameengine/PyDoc/KX_Camera.py
+++ b/source/gameengine/PyDoc/KX_Camera.py
@@ -40,6 +40,8 @@ class KX_Camera(KX_GameObject):
 	                       Regenerated every frame from the camera's position and orientation.
 	                       This is camera_to_world inverted.
 	@type world_to_camera: 4x4 Matrix [[float]]
+	
+	@group Deprecated: enableViewport
 	"""
 	
 	def sphereInsideFrustum(centre, radius):
@@ -185,3 +187,26 @@ class KX_Camera(KX_GameObject):
 		@param matrix: The new projection matrix for this camera.
 		"""
 
+	def enableViewport(viewport):
+		"""
+		DEPRECATED: use the isViewport property
+		Use this camera to draw a viewport on the screen (for split screen games or overlay scenes). The viewport region is defined with L{setViewport}.
+		
+		@type viewport: bool
+		@param viewport: the new viewport status
+		"""
+	def setOnTop():
+		"""
+		Set this cameras viewport ontop of all other viewport.
+		"""
+	def setViewport(left, bottom, right, top):
+		"""
+		Sets the region of this viewport on the screen in pixels.
+		
+		Use L{Rasterizer.getWindowHeight} L{Rasterizer.getWindowWidth} to calculate values relative to the entire display.
+		
+		@type left: int
+		@type bottom: int
+		@type right: int
+		@type top: int
+		"""
diff --git a/source/gameengine/PyDoc/KX_ConstraintActuator.py b/source/gameengine/PyDoc/KX_ConstraintActuator.py
index 7c7ad5aa0fac30ca5c854228f57d4c71cbeac386..89ca4d80c731b765544e0bb745e1bd435e3fd0d5 100644
--- a/source/gameengine/PyDoc/KX_ConstraintActuator.py
+++ b/source/gameengine/PyDoc/KX_ConstraintActuator.py
@@ -5,6 +5,75 @@ from SCA_IActuator import *
 class KX_ConstraintActuator(SCA_IActuator):
 	"""
 	A constraint actuator limits the position, rotation, distance or orientation of an object.
+	
+	Properties:
+	
+	@ivar damp: time constant of the constraint expressed in frame (not use by Force field constraint)
+	@type damp: integer
+	
+	@ivar rotDamp: time constant for the rotation expressed in frame (only for the distance constraint)
+	               0 = use damp for rotation as well
+	@type rotDamp: integer
+	
+	@ivar direction: the reference direction in world coordinate for the orientation constraint
+	@type direction: 3-tuple of float: [x,y,z]
+	
+	@ivar option: Binary combination of the following values:
+				Applicable to Distance constraint:
+					- KX_ACT_CONSTRAINT_NORMAL    (  64) : Activate alignment to surface
+					- KX_ACT_CONSTRAINT_DISTANCE  ( 512) : Activate distance control
+					- KX_ACT_CONSTRAINT_LOCAL		(1024) : direction of the ray is along the local axis
+				Applicable to Force field constraint:					
+					- KX_ACT_CONSTRAINT_DOROTFH   (2048) : Force field act on rotation as well
+				Applicable to both:
+					- KX_ACT_CONSTRAINT_MATERIAL  ( 128) : Detect material rather than property
+					- KX_ACT_CONSTRAINT_PERMANENT ( 256) : No deactivation if ray does not hit target
+	@type option: integer
+	
+	@ivar time: activation time of the actuator. The actuator disables itself after this many frame.
+		        If set to 0, the actuator is not limited in time.
+	@type time: integer
+	
+	@ivar property: the name of the property or material for the ray detection of the distance constraint.
+	@type property: string
+	
+	@ivar min: The lower bound of the constraint
+	           For the rotation and orientation constraint, it represents radiant
+	@type min: float
+	
+	@ivar distance: the target distance of the distance constraint
+	@type distance: float
+	
+	@ivar max: the upper bound of the constraint.
+	           For rotation and orientation constraints, it represents radiant.
+	@type max: float
+	
+	@ivar rayLength: the length of the ray of the distance constraint.
+	@type rayLength: float
+	
+	@ivar limit: type of constraint, use one of the following constant:
+	              KX_ACT_CONSTRAINT_LOCX  ( 1) : limit X coord
+	              KX_ACT_CONSTRAINT_LOCY  ( 2) : limit Y coord
+	              KX_ACT_CONSTRAINT_LOCZ  ( 3) : limit Z coord
+	              KX_ACT_CONSTRAINT_ROTX  ( 4) : limit X rotation
+	              KX_ACT_CONSTRAINT_ROTY  ( 5) : limit Y rotation
+	              KX_ACT_CONSTRAINT_ROTZ  ( 6) : limit Z rotation
+	              KX_ACT_CONSTRAINT_DIRPX ( 7) : set distance along positive X axis
+	              KX_ACT_CONSTRAINT_DIRPY ( 8) : set distance along positive Y axis
+	              KX_ACT_CONSTRAINT_DIRPZ ( 9) : set distance along positive Z axis
+	              KX_ACT_CONSTRAINT_DIRNX (10) : set distance along negative X axis
+	              KX_ACT_CONSTRAINT_DIRNY (11) : set distance along negative Y axis
+	              KX_ACT_CONSTRAINT_DIRNZ (12) : set distance along negative Z axis
+	              KX_ACT_CONSTRAINT_ORIX  (13) : set orientation of X axis
+	              KX_ACT_CONSTRAINT_ORIY  (14) : set orientation of Y axis
+	              KX_ACT_CONSTRAINT_ORIZ  (15) : set orientation of Z axis
+	              KX_ACT_CONSTRAINT_FHPX  (16) : set force field along positive X axis
+	              KX_ACT_CONSTRAINT_FHPY  (17) : set force field along positive Y axis
+	              KX_ACT_CONSTRAINT_FHPZ  (18) : set force field along positive Z axis
+	              KX_ACT_CONSTRAINT_FHNX  (19) : set force field along negative X axis
+	              KX_ACT_CONSTRAINT_FHNY  (20) : set force field along negative Y axis
+	              KX_ACT_CONSTRAINT_FHNZ  (21) : set force field along negative Z axis
+	@type limit: integer
 	"""
 	def setDamp(time):
 		"""
diff --git a/source/gameengine/PyDoc/KX_ConstraintWrapper.py b/source/gameengine/PyDoc/KX_ConstraintWrapper.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b34e1609e811683b0aabadda0a8d32cbe6f7523
--- /dev/null
+++ b/source/gameengine/PyDoc/KX_ConstraintWrapper.py
@@ -0,0 +1,28 @@
+class KX_ConstraintWrapper: # (PyObjectPlus)
+	"""
+	KX_ConstraintWrapper
+	
+	All placeholders have a __ prefix
+	"""
+	def __getConstraintId(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+
+	def __testMethod(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+
diff --git a/source/gameengine/PyDoc/KX_GameActuator.py b/source/gameengine/PyDoc/KX_GameActuator.py
index fc5bd6005fcbf4df9ca14ae38fcf14890893c639..0b329419ad7e1590a0db4f1aa26d9d7b7a4a6f76 100644
--- a/source/gameengine/PyDoc/KX_GameActuator.py
+++ b/source/gameengine/PyDoc/KX_GameActuator.py
@@ -10,6 +10,8 @@ class KX_GameActuator(SCA_IActuator):
 	
 	@ivar file: the new .blend file to load
 	@type file: string.
+	@ivar mode: The mode of this actuator
+	@type mode: int from 0 to 5 L{GameLogic.Game Actuator}
 	"""
 	def getFile():
 		"""
diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py
index 694fe02a7ccac4d2b0bda57716ec1d41b2784b88..257a25e8ad9a8bc5813eec4ddf1c7fc52ce0ccb6 100644
--- a/source/gameengine/PyDoc/KX_GameObject.py
+++ b/source/gameengine/PyDoc/KX_GameObject.py
@@ -1,41 +1,97 @@
 # $Id$
 # Documentation for game objects
 
-class KX_GameObject:
+from SCA_IObject import *
+# from SCA_ISensor import *
+# from SCA_IController import *
+# from SCA_IActuator import *
+
+
+class KX_GameObject(SCA_IObject):
 	"""
 	All game objects are derived from this class.
 	
 	Properties assigned to game objects are accessible as attributes of this class.
-	
+		- note: Calling ANY method or attribute on an object that has been removed from a scene will raise a SystemError, if an object may have been removed since last accessing it use the L{invalid} attribute to check.
+
 	@ivar name: The object's name. (Read only)
+		- note: Currently (Blender 2.49) the prefix "OB" is added to all objects name. This may change in blender 2.5.
 	@type name: string.
-	@ivar mass: The object's mass (provided the object has a physics controller). Read only.
+	@ivar mass: The object's mass
+		- note: The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0
 	@type mass: float
+	@ivar linVelocityMin: Enforces the object keeps moving at a minimum velocity.
+		- note: Applies to dynamic and rigid body objects only.
+		- note: A value of 0.0 disables this option.
+		- note: While objects are stationary the minimum velocity will not be applied.
+	@type linVelocityMin: float
+	@ivar linVelocityMax: Clamp the maximum linear velocity to prevent objects moving beyond a set speed.
+		- note: Applies to dynamic and rigid body objects only.
+		- note: A value of 0.0 disables this option (rather then setting it stationary).
+	@type linVelocityMax: float
+	@ivar localInertia: the object's inertia vector in local coordinates. Read only.
+	@type localInertia: list [ix, iy, iz]
 	@ivar parent: The object's parent object. (Read only)
-	@type parent: L{KX_GameObject}
+	@type parent: L{KX_GameObject} or None
 	@ivar visible: visibility flag.
+		- note: Game logic will still run for invisible objects.
 	@type visible: boolean
+	@ivar occlusion: occlusion capability flag.
+	@type occlusion: boolean
 	@ivar position: The object's position. 
-	@type position: list [x, y, z]
-	@ivar orientation: The object's orientation. 3x3 Matrix.  
-	                   You can also write a Quaternion or Euler vector.
-	@type orientation: 3x3 Matrix [[float]]
+	                DEPRECATED: use localPosition and worldPosition
+	@type position: list [x, y, z] On write: local position, on read: world position
+	@ivar orientation: The object's orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector.
+	                   DEPRECATED: use localOrientation and worldOrientation
+	@type orientation: 3x3 Matrix [[float]] On write: local orientation, on read: world orientation
 	@ivar scaling: The object's scaling factor. list [sx, sy, sz]
-	@type scaling: list [sx, sy, sz]
+	               DEPRECATED: use localScaling and worldScaling
+	@type scaling: list [sx, sy, sz] On write: local scaling, on read: world scaling
+	@ivar localOrientation: The object's local orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector.
+	@type localOrientation: 3x3 Matrix [[float]]
+	@ivar worldOrientation: The object's world orientation.
+	@type worldOrientation: 3x3 Matrix [[float]]
+	@ivar localScaling: The object's local scaling factor.
+	@type localScaling: list [sx, sy, sz]
+	@ivar worldScaling: The object's world scaling factor. Read-only
+	@type worldScaling: list [sx, sy, sz]
+	@ivar localPosition: The object's local position.
+	@type localPosition: list [x, y, z]
+	@ivar worldPosition: The object's world position. 
+	@type worldPosition: list [x, y, z]
 	@ivar timeOffset: adjust the slowparent delay at runtime.
 	@type timeOffset: float
-	@ivar state: the game object's state bitmask.
+	@ivar state: the game object's state bitmask, using the first 30 bits, one bit must always be set.
 	@type state: int
+	@ivar meshes: a list meshes for this object.
+		- note: Most objects use only 1 mesh.
+		- note: Changes to this list will not update the KX_GameObject.
+	@type meshes: list of L{KX_MeshProxy}
+	@ivar sensors: a sequence of L{SCA_ISensor} objects with string/index lookups and iterator support.
+		- note: This attribute is experemental and may be removed (but probably wont be).
+		- note: Changes to this list will not update the KX_GameObject.
+	@type sensors: list
+	@ivar controllers: a sequence of L{SCA_IController} objects with string/index lookups and iterator support.
+		- note: This attribute is experemental and may be removed (but probably wont be).
+		- note: Changes to this list will not update the KX_GameObject.
+	@type controllers: list of L{SCA_ISensor}.
+	@ivar actuators: a list of L{SCA_IActuator} with string/index lookups and iterator support.
+		- note: This attribute is experemental and may be removed (but probably wont be).
+		- note: Changes to this list will not update the KX_GameObject.
+	@type actuators: list
+	@ivar attrDict: get the objects internal python attribute dictionary for direct (faster) access.
+	@type attrDict: dict
+	@group Deprecated: getPosition, setPosition, setWorldPosition, getOrientation, setOrientation, getState, setState, getParent, getVisible, getMass, getMesh
 	"""
-	def endObject(visible):
+	def endObject():
 		"""
 		Delete this object, can be used inpace of the EndObject Actuator.
 		The actual removal of the object from the scene is delayed.
 		"""	
-	def replaceMesh(mesh_name):
+	def replaceMesh(mesh):
 		"""
 		Replace the mesh of this object with a new mesh. This works the same was as the actuator.
-		@type mesh_name: string
+		@type mesh: L{KX_MeshProxy<KX_MeshProxy.KX_MeshProxy>} or mesh name
 		"""	
 	def getVisible():
 		"""
@@ -51,6 +107,14 @@ class KX_GameObject:
 		@type recursive: boolean
 		@param recursive: optional argument to set all childrens visibility flag too.
 		"""
+	def setOcclusion(occlusion, recursive):
+		"""
+		Sets the game object's occlusion capability.
+		
+		@type occlusion: boolean
+		@type recursive: boolean
+		@param recursive: optional argument to set all childrens occlusion flag too.
+		"""
 	def getState():
 		"""
 		Gets the game object's state bitmask. (B{deprecated})
@@ -96,7 +160,7 @@ class KX_GameObject:
 		@param orn: a rotation matrix specifying the new rotation.
 		@note: When using this matrix with Blender.Mathutils.Matrix() types, it will need to be transposed.
 		"""
-	def alignAxisToVect(vect, axis):
+	def alignAxisToVect(vect, axis, factor):
 		"""
 		Aligns any of the game object's axis along the given vector.
 		
@@ -107,6 +171,8 @@ class KX_GameObject:
 					- 0: X axis
 					- 1: Y axis
 					- 2: Z axis (default) 
+		@type factor: float
+		@param factor: Only rotate a feaction of the distance to the target vector (0.0 - 1.0)
 		"""
 	def getAxisVect(vect):
 		"""
@@ -137,7 +203,7 @@ class KX_GameObject:
 		@param local: - False: you get the "global" movement ie: relative to world orientation (default).
 		              - True: you get the "local" movement ie: relative to object orientation.
 		"""	
-	def applyRotation(movement, local = 0):
+	def applyRotation(rotation, local = 0):
 		"""
 		Sets the game object's rotation.
 		
@@ -247,6 +313,8 @@ class KX_GameObject:
 		The reaction force is the force applied to this object over the last simulation timestep.
 		This also includes impulses, eg from collisions.
 		
+		(B{This is not implimented for bullet physics at the moment})
+		
 		@rtype: list [fx, fy, fz]
 		@return: the reaction force of this object.
 		"""
@@ -303,13 +371,13 @@ class KX_GameObject:
 	def getChildren():
 		"""
 		Return a list of immediate children of this object.
-		@rtype: list
+		@rtype: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>}
 		@return: a list of all this objects children.
 		"""
 	def getChildrenRecursive():
 		"""
 		Return a list of children of this object, including all their childrens children.
-		@rtype: list
+		@rtype: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>}
 		@return: a list of all this objects children recursivly.
 		"""
 	def getMesh(mesh):
@@ -403,7 +471,7 @@ class KX_GameObject:
 		@type objfrom: L{KX_GameObject} or 3-tuple or None
 		@param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to
 		@type dist: float
-		@param prop: property name that object must have; can be omitted => detect any object
+		@param prop: property name that object must have; can be omitted or "" => detect any object
 		@type prop: string
 		@param face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin
 		@type face: int
@@ -417,5 +485,23 @@ class KX_GameObject:
 		         If no hit, returns (None,None,None) or (None,None,None,None)
 		         If the object hit is not a static mesh, polygon is None
 		"""
-
-
+	def setCollisionMargin(margin):
+		"""
+		Set the objects collision margin.
+		
+		note: If this object has no physics controller (a physics ID of zero), this function will raise RuntimeError.
+		
+		@type margin: float
+		@param margin: the collision margin distance in blender units.
+		"""
+	def sendMessage(subject, body="", to=""):
+		"""
+		Sends a message.
+	
+		@param subject: The subject of the message
+		@type subject: string
+		@param body: The body of the message (optional)
+		@type body: string
+		@param to: The name of the object to send the message to (optional)
+		@type to: string
+		"""
diff --git a/source/gameengine/PyDoc/KX_Light.py b/source/gameengine/PyDoc/KX_LightObject.py
similarity index 97%
rename from source/gameengine/PyDoc/KX_Light.py
rename to source/gameengine/PyDoc/KX_LightObject.py
index ff0cf071d2d3d99107bcbb5dd1b66d5481e47b83..8cc1787887b21b6b64a4160572b3c3c3370fa131 100644
--- a/source/gameengine/PyDoc/KX_Light.py
+++ b/source/gameengine/PyDoc/KX_LightObject.py
@@ -2,7 +2,7 @@
 # Documentation for Light game objects.
 from KX_GameObject import *
 
-class KX_Light(KX_GameObject):
+class KX_LightObject(KX_GameObject):
 	"""
 	A Light object.
 
diff --git a/source/gameengine/PyDoc/KX_MeshProxy.py b/source/gameengine/PyDoc/KX_MeshProxy.py
index 03bc36b6ac1f5c5e248bdae8b2d323c676b27013..c864523cde87610463e6d0f9eec0e6f30b5332a6 100644
--- a/source/gameengine/PyDoc/KX_MeshProxy.py
+++ b/source/gameengine/PyDoc/KX_MeshProxy.py
@@ -1,7 +1,9 @@
 # $Id$
 # Documentation for KX_MeshProxy
 
-class KX_MeshProxy:
+from SCA_IObject import *
+
+class KX_MeshProxy(SCA_IObject):
 	"""
 	A mesh object.
 	
@@ -45,7 +47,14 @@ class KX_MeshProxy:
 			m_i += 1
 			mesh = obj.getMesh(m_i)
 	
-			
+	@ivar materials: 
+	@type materials: list of L{KX_BlenderMaterial} or L{KX_PolygonMaterial} types
+
+	@ivar numPolygons:
+	@type numPolygons: integer
+
+	@ivar numMaterials:
+	@type numMaterials: integer
 	"""
 	
 	def getNumMaterials():
diff --git a/source/gameengine/PyDoc/KX_MouseFocusSensor.py b/source/gameengine/PyDoc/KX_MouseFocusSensor.py
index 28d584037f837b03aae268e3db68688339980865..24f7716218ba181d2578bc170a2b6feec9a1bff6 100644
--- a/source/gameengine/PyDoc/KX_MouseFocusSensor.py
+++ b/source/gameengine/PyDoc/KX_MouseFocusSensor.py
@@ -8,19 +8,60 @@ class KX_MouseFocusSensor(SCA_MouseSensor):
 	
 	The mouse focus sensor works by transforming the mouse coordinates from 2d device
 	space to 3d space then raycasting away from the camera.
+	
+	@ivar raySource: The worldspace source of the ray (the view position)
+	@type raySource: list (vector of 3 floats)
+	@ivar rayTarget: The worldspace target of the ray.
+	@type rayTarget: list (vector of 3 floats)
+	@ivar rayDirection: The L{rayTarget} - L{raySource} normalized.
+	@type rayDirection: list (normalized vector of 3 floats)
+	@ivar hitObject: the last object the mouse was over.
+	@type hitObject: L{KX_GameObject<KX_GameObject.KX_GameObject>} or None
+	@ivar hitPosition: The worldspace position of the ray intersecton.
+	@type hitPosition: list (vector of 3 floats)
+	@ivar hitNormal: the worldspace normal from the face at point of intersection.
+	@type hitNormal: list (normalized vector of 3 floats)
 	"""
 	
-	def GetRayTarget():
+	def getHitNormal():
+		"""
+		Returns the normal (in worldcoordinates) at the point of collision where the object was hit by this ray. (B{deprecated})
+		 
+		@rtype: list [x, y, z]
+		@return: the ray collision normal.
+		"""
+	def getHitObject():
+		"""
+		Returns the object that was hit by this ray or None. (B{deprecated})
+		
+		@rtype: L{KX_GameObject} or None
+		@return: the collision object.
+		"""
+	def getHitPosition():
 		"""
-		Returns the end point of the sensor ray.
+		Returns the position (in worldcoordinates) at the point of collision where the object was hit by this ray. (B{deprecated})
 		
 		@rtype: list [x, y, z]
-		@return: the end point of the sensor ray, in world coordinates.
+		@return: the ray collision position.
 		"""
-	def GetRaySource():
+	def getRayDirection():
 		"""
-		Returns the start point of the sensor ray.
+		Returns the normalized direction (in worldcoordinates) of the ray cast by the mouse. (B{deprecated})
 		
 		@rtype: list [x, y, z]
-		@return: the start point of the sensor ray, in world coordinates.
+		@return: the ray direction.
 		"""
+	def getRaySource():
+		"""
+		Returns the position (in worldcoordinates) the ray was cast from by the mouse. (B{deprecated})
+		
+		@rtype: list [x, y, z]
+		@return: the ray source.
+		"""
+	def getRayTarget():
+		"""
+		Returns the target of the ray (in worldcoordinates) that seeks the focus object. (B{deprecated})
+		
+		@rtype: list [x, y, z]
+		@return: the ray target.
+		"""
\ No newline at end of file
diff --git a/source/gameengine/PyDoc/KX_ParentActuator.py b/source/gameengine/PyDoc/KX_ParentActuator.py
index 4a5f72e7cc289960f671735c5f4cbc4a6bbfd0a7..1e2bfe60a4fd1622cd9c38f77de810f3b492cf8b 100644
--- a/source/gameengine/PyDoc/KX_ParentActuator.py
+++ b/source/gameengine/PyDoc/KX_ParentActuator.py
@@ -7,10 +7,12 @@ class KX_ParentActuator(SCA_IActuator):
 	The parent actuator can set or remove an objects parent object.	
 	@ivar object: the object this actuator sets the parent too.
 	@type object: KX_GameObject or None
+	@ivar mode: The mode of this actuator
+	@type mode: int from 0 to 1 L{GameLogic.Parent Actuator}
 	"""
 	def setObject(object):
 		"""
-        DEPRECATED: Use the object property.
+		DEPRECATED: Use the object property.
 		Sets the object to set as parent.
 		
 		Object can be either a L{KX_GameObject} or the name of the object.
@@ -19,7 +21,7 @@ class KX_ParentActuator(SCA_IActuator):
 		"""
 	def getObject(name_only = 1):
 		"""
-        DEPRECATED: Use the object property.
+		DEPRECATED: Use the object property.
 		Returns the name of the object to change to.
 		@type name_only: bool
 		@param name_only: optional argument, when 0 return a KX_GameObject
diff --git a/source/gameengine/PyDoc/KX_PhysicsObjectWrapper.py b/source/gameengine/PyDoc/KX_PhysicsObjectWrapper.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea9a2a3a4118b373f104ca2a46c2b1957044c27b
--- /dev/null
+++ b/source/gameengine/PyDoc/KX_PhysicsObjectWrapper.py
@@ -0,0 +1,49 @@
+from PyObjectPlus import *
+
+class KX_PhysicsObjectWrapper(PyObjectPlus):
+	"""
+	KX_PhysicsObjectWrapper
+	
+	All placeholders have a __ prefix
+	"""
+	def __setActive(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+
+	def __setAngularVelocity(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setLinearVelocity(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setPosition(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
diff --git a/source/gameengine/PyDoc/KX_PolyProxy.py b/source/gameengine/PyDoc/KX_PolyProxy.py
index bcd42c2ac2e5a7616e531787d5b98725ae91f473..2d1c1f9b21835cce1f344ff8af2241c9e8954b3e 100644
--- a/source/gameengine/PyDoc/KX_PolyProxy.py
+++ b/source/gameengine/PyDoc/KX_PolyProxy.py
@@ -1,7 +1,8 @@
 # $Id$
 # Documentation for the polygon proxy class
+from SCA_IObject import *
 
-class KX_PolyProxy:
+class KX_PolyProxy(SCA_IObject):
 	"""
 	A polygon holds the index of the vertex forming the poylgon.
 
diff --git a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py
index 974ef718ccf0d6956111bfd4d4a997df6da100c8..572b864ff0a950a25b7cdcb7f60906aac6934a16 100644
--- a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py
+++ b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py
@@ -109,3 +109,10 @@ class KX_SCA_AddObjectActuator(SCA_IActuator):
 		@rtype: L{KX_GameObject}
 		@return: A L{KX_GameObject} or None if no object has been created.
 		"""
+	def instantAddObject():
+		"""
+		Returns the last object created by this actuator. The object can then be accessed from L{objectLastCreated}.
+		
+		@rtype: None
+		"""
+	
diff --git a/source/gameengine/PyDoc/KX_SCA_DynamicActuator.py b/source/gameengine/PyDoc/KX_SCA_DynamicActuator.py
index a6a3bce1f31323163041611a3a94fd50e664a184..22da159ce711bc01446eeb73eeda35b742e6237b 100644
--- a/source/gameengine/PyDoc/KX_SCA_DynamicActuator.py
+++ b/source/gameengine/PyDoc/KX_SCA_DynamicActuator.py
@@ -5,26 +5,26 @@ from SCA_IActuator import *
 class KX_SCA_DynamicActuator(SCA_IActuator):
 	"""
 	Dynamic Actuator.
-    @ivar operation: the type of operation of the actuator, 0-4
-                     KX_DYN_RESTORE_DYNAMICS, KX_DYN_DISABLE_DYNAMICS, 
-                     KX_DYN_ENABLE_RIGID_BODY, KX_DYN_DISABLE_RIGID_BODY, KX_DYN_SET_MASS
-    @type operation: integer
-    @ivar mass: the mass value for the KX_DYN_SET_MASS operation
-    @type mass: float
+	@ivar operation: the type of operation of the actuator, 0-4
+						KX_DYN_RESTORE_DYNAMICS, KX_DYN_DISABLE_DYNAMICS, 
+						KX_DYN_ENABLE_RIGID_BODY, KX_DYN_DISABLE_RIGID_BODY, KX_DYN_SET_MASS
+	@type operation: integer
+	@ivar mass: the mass value for the KX_DYN_SET_MASS operation
+	@type mass: float
 	"""
 	def setOperation(operation):
 		"""
-        DEPRECATED: Use the operation property instead.
+		DEPRECATED: Use the operation property instead.
 		Set the type of operation when the actuator is activated:
-                0 = restore dynamics
-                1 = disable dynamics
-                2 = enable rigid body
-                3 = disable rigid body
-                4 = set mass
-        """
-	def getOperatoin()
+				- 0 = restore dynamics
+				- 1 = disable dynamics
+				- 2 = enable rigid body
+				- 3 = disable rigid body
+				- 4 = set mass
 		"""
-        DEPRECATED: Use the operation property instead.
+	def getOperation():
+		"""
+		DEPRECATED: Use the operation property instead.
 		return the type of operation
 		"""
 	
diff --git a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py
index 1013dd53cb966aa52680d5c1a9eabedeca8d0f86..951c118a99ac587f370766526944d87226db22f4 100644
--- a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py
+++ b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py
@@ -18,13 +18,13 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator):
 		# Mesh (name, near, far)
 		# Meshes overlap so that they don't 'pop' when on the edge of the distance.
 		meshes = ((".Hi", 0.0, -20.0),
-		          (".Med", -15.0, -50.0),
-			  (".Lo", -40.0, -100.0)
-			  )
+				  (".Med", -15.0, -50.0),
+				  (".Lo", -40.0, -100.0)
+				)
 		
 		co = GameLogic.getCurrentController()
 		obj = co.getOwner()
-		act = co.getActuator("LOD." + obj.getName())
+		act = co.getActuator("LOD." + obj.name)
 		cam = GameLogic.getCurrentScene().active_camera
 		
 		def Depth(pos, plane):
@@ -39,10 +39,10 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator):
 		for mesh in meshes:
 			if depth < mesh[1] and depth > mesh[2]:
 				newmesh = mesh
-			if "ME" + obj.getName() + mesh[0] == act.getMesh():
+			if "ME" + obj.name + mesh[0] == act.getMesh():
 				curmesh = mesh
 		
-		if newmesh != None and "ME" + obj.getName() + newmesh[0] != act.getMesh():
+		if newmesh != None and "ME" + obj.name + newmesh[0] != act.getMesh():
 			# The mesh is a different mesh - switch it.
 			# Check the current mesh is not a better fit.
 			if curmesh == None or curmesh[1] < depth or curmesh[2] > depth:
@@ -55,15 +55,14 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator):
 		This will generate a warning in the console:
 		
 		C{ERROR: GameObject I{OBName} ReplaceMeshActuator I{ActuatorName} without object}
-		
-	Properties:
+	
 	@ivar mesh: L{KX_MeshProxy} or the name of the mesh that will replace the current one
 	            Set to None to disable actuator
 	@type mesh: L{KX_MeshProxy} or None if no mesh is set
 	"""
 	def setMesh(name):
 		"""
-        DEPRECATED: Use the mesh property instead.
+		DEPRECATED: Use the mesh property instead.
 		Sets the name of the mesh that will replace the current one.
 		When the name is None it will unset the mesh value so no action is taken.
 		
@@ -71,11 +70,15 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator):
 		"""
 	def getMesh():
 		"""
-        DEPRECATED: Use the mesh property instead.
+		DEPRECATED: Use the mesh property instead.
 		Returns the name of the mesh that will replace the current one.
 		
 		Returns None if no mesh has been scheduled to be added.
 		
 		@rtype: string or None
 		"""
-
+	def instantReplaceMesh():
+		"""
+		Immediately replace mesh without delay.
+		@rtype: None
+		"""
\ No newline at end of file
diff --git a/source/gameengine/PyDoc/KX_Scene.py b/source/gameengine/PyDoc/KX_Scene.py
index 5e357e6eefca554e4ab0851bfd5846092f617278..4fe150be8987f6b79bcc34d8da3d8313e2bcd60d 100644
--- a/source/gameengine/PyDoc/KX_Scene.py
+++ b/source/gameengine/PyDoc/KX_Scene.py
@@ -1,7 +1,9 @@
 # $Id$
 # Documentation for KX_Scene.py
 
-class KX_Scene:
+from PyObjectPlus import *
+
+class KX_Scene(PyObjectPlus):
 	"""
 	Scene.
 	
@@ -16,14 +18,14 @@ class KX_Scene:
 		scene = GameLogic.getCurrentScene()
 		
 		# print all the objects in the scene
-		for obj in scene.getObjectList():
-			print obj.getName()
+		for obj in scene.objects:
+			print obj.name
 		
 		# get an object named 'Cube'
-		obj = scene.getObjectList()["OBCube"]
+		obj = scene.objects["OBCube"]
 		
 		# get the first object in the scene.
-		obj = scene.getObjectList()[0]
+		obj = scene.objects[0]
 	
 	Example::
 		# Get the depth of an object in the camera view.
@@ -39,8 +41,14 @@ class KX_Scene:
 		
 	@ivar name: The scene's name
 	@type name: string
-	@type objects: A list of objects in the scene.
-	@type objects: list [L{KX_GameObject}]
+	@ivar objects: A list of objects in the scene.
+	@type objects: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>}
+	@ivar objects_inactive: A list of objects on background layers (used for the addObject actuator).
+	@type objects_inactive: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>}
+	@ivar lights: A list of lights in the scene.
+	@type lights: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_LightObject.KX_LightObject>}
+	@ivar cameras: A list of cameras in the scene.
+	@type cameras: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_Camera.KX_Camera>}
 	@ivar active_camera: The current active camera
 	@type active_camera: L{KX_Camera}
 	@ivar suspended: True if the scene is suspended.
@@ -49,28 +57,32 @@ class KX_Scene:
 	@type activity_culling: boolean
 	@ivar activity_culling_radius: The distance outside which to do activity culling.  Measured in manhattan distance.
 	@type activity_culling_radius: float
+	@group Deprecated: getLightList, getObjectList, getName
 	"""
 	
 	def getLightList():
 		"""
+		DEPRECATED: use the 'lights' property.
 		Returns the list of lights in the scene.
 		
-		@rtype: list [L{KX_Light}]
+		@rtype: list [L{KX_LightObject}]
 		"""
 	def getObjectList():
 		"""
+		DEPRECATED: use the 'objects' property.
 		Returns the list of objects in the scene.
 		
 		@rtype: list [L{KX_GameObject}]
 		"""
 	def getName():
 		"""
+		DEPRECATED: use the 'name' property.
 		Returns the name of the scene.
 		
 		@rtype: string
 		"""
 
-	def addObject(object, other, time=0)
+	def addObject(object, other, time=0):
 		"""
 		Adds an object to the scene like the Add Object Actuator would, and returns the created object.
 		
diff --git a/source/gameengine/PyDoc/KX_SceneActuator.py b/source/gameengine/PyDoc/KX_SceneActuator.py
index c8912783ab7915824356ce69a6c3c1bd1f491e3f..937c94c91e65d7f9ace5b326507d31d1a014af11 100644
--- a/source/gameengine/PyDoc/KX_SceneActuator.py
+++ b/source/gameengine/PyDoc/KX_SceneActuator.py
@@ -8,22 +8,24 @@ class KX_SceneActuator(SCA_IActuator):
 	
 	@warning: Scene actuators that use a scene name will be ignored if at game start, the
 	          named scene doesn't exist or is empty
-		  
+
 		  This will generate a warning in the console:
 		  
 		  C{ERROR: GameObject I{OBName} has a SceneActuator I{ActuatorName} (SetScene) without scene}
-
-	Properties:
 	
 	@ivar scene: the name of the scene to change to/overlay/underlay/remove/suspend/resume
 	@type scene: string.
 	@ivar camera: the camera to change to.
 	              When setting the attribute, you can use either a L{KX_Camera} or the name of the camera.
 	@type camera: L{KX_Camera} on read, string or L{KX_Camera} on write
+	@ivar useRestart: Set flag to True to restart the sene
+	@type useRestart: bool
+	@ivar mode: The mode of the actuator
+	@type mode: int from 0 to 5 L{GameLogic.Scene Actuator}
 	"""
 	def setUseRestart(flag):
 		"""
-		DEPRECATED
+		DEPRECATED: use the useRestart property instead
 		Set flag to True to restart the scene.
 		
 		@type flag: boolean
@@ -46,7 +48,7 @@ class KX_SceneActuator(SCA_IActuator):
 		"""
 	def getUseRestart():
 		"""
-		DEPRECATED
+		DEPRECATED: use the useRestart property instead
 		Returns True if the scene will be restarted.
 		
 		@rtype: boolean
diff --git a/source/gameengine/PyDoc/KX_SoundActuator.py b/source/gameengine/PyDoc/KX_SoundActuator.py
index 072af5b816cdef13d0017793c61832a700a78ab8..0aec57c851c651ef2235355ebb22397eb4410712 100644
--- a/source/gameengine/PyDoc/KX_SoundActuator.py
+++ b/source/gameengine/PyDoc/KX_SoundActuator.py
@@ -7,18 +7,55 @@ class KX_SoundActuator(SCA_IActuator):
 	Sound Actuator.
 	
 	The L{startSound()}, L{pauseSound()} and L{stopSound()} do not require
-	the actuator to be activated - they act instantly.
+	the actuator to be activated - they act instantly provided that the actuator has
+	been activated once at least.
+
+	@ivar filename: Sets the filename of the sound this actuator plays.
+	@type filename: string
+
+	@ivar volume: Sets the volume (gain) of the sound.
+	@type volume: float
+
+	@ivar pitch: Sets the pitch of the sound.
+	@type pitch: float
+	
+	@ivar rollOffFactor: Sets the roll off factor. Rolloff defines the rate of attenuation as the sound gets further away.
+	@type rollOffFactor: float
+	
+	@ivar looping: Sets the loop mode of the actuator.
+	@type looping: integer
+	
+	@ivar position: Sets the position of the sound.
+	@type position: float array
+	
+	@ivar velocity: Sets the speed of the sound; The speed of the sound alter the pitch.
+	@type velocity: float array
+	
+	@ivar orientation: Sets the orientation of the sound. When setting the orientation you can 
+	                   also use quaternion [float,float,float,float] or euler angles [float,float,float]
+	@type orientation: 3x3 matrix [[float]]
+	
+	@ivar type: Sets the operation mode of the actuator. You can use one of the following constant:
+				- KX_SOUNDACT_PLAYSTOP               (1)
+				- KX_SOUNDACT_PLAYEND                (2)
+				- KX_SOUNDACT_LOOPSTOP               (3)
+				- KX_SOUNDACT_LOOPEND                (4)
+				- KX_SOUNDACT_LOOPBIDIRECTIONAL      (5)
+				- KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP (6)
+	@type type:	integer
 	
 	@group Play Methods: startSound, pauseSound, stopSound
 	"""
 	def setFilename(filename):
 		"""
+		DEPRECATED: Use the filename property instead.
 		Sets the filename of the sound this actuator plays.
 		
 		@type filename: string
 		"""
 	def getFilename():
 		"""
+		DEPRECATED: Use the filename property instead.
 		Returns the filename of the sound this actuator plays.
 		
 		@rtype: string
@@ -37,6 +74,7 @@ class KX_SoundActuator(SCA_IActuator):
 		"""
 	def setGain(gain):
 		"""
+		DEPRECATED: Use the volume property instead
 		Sets the gain (volume) of the sound
 		
 		@type gain: float
@@ -44,24 +82,28 @@ class KX_SoundActuator(SCA_IActuator):
 		"""
 	def getGain():
 		"""
+		DEPRECATED: Use the volume property instead.
 		Gets the gain (volume) of the sound.
 		
 		@rtype: float
 		"""
 	def setPitch(pitch):
 		"""
+		DEPRECATED: Use the pitch property instead.
 		Sets the pitch of the sound.
 		
 		@type pitch: float
 		"""
 	def getPitch():
 		"""
+		DEPRECATED: Use the pitch property instead.
 		Returns the pitch of the sound.
 		
 		@rtype: float
 		"""
 	def setRollOffFactor(rolloff):
 		"""
+		DEPRECATED: Use the rollOffFactor property instead.
 		Sets the rolloff factor for the sounds.
 		
 		Rolloff defines the rate of attenuation as the sound gets further away.
@@ -71,12 +113,14 @@ class KX_SoundActuator(SCA_IActuator):
 		"""
 	def getRollOffFactor():
 		"""
+		DEPRECATED: Use the rollOffFactor property instead.
 		Returns the rolloff factor for the sound.
 		
 		@rtype: float
 		"""
 	def setLooping(loop):
 		"""
+		DEPRECATED: Use the looping property instead.
 		Sets the loop mode of the actuator.
 		
 		@bug: There are no constants defined for this method!
@@ -90,12 +134,14 @@ class KX_SoundActuator(SCA_IActuator):
 		"""
 	def getLooping():
 		"""
+		DEPRECATED: Use the looping property instead.
 		Returns the current loop mode of the actuator.
 		
 		@rtype: integer
 		"""
 	def setPosition(x, y, z):
 		"""
+		DEPRECATED: Use the position property instead.
 		Sets the position this sound will come from.
 		
 		@type x: float
@@ -107,6 +153,7 @@ class KX_SoundActuator(SCA_IActuator):
 		"""
 	def setVelocity(vx, vy, vz):
 		"""
+		DEPRECATED: Use the velocity property instead.
 		Sets the velocity this sound is moving at.  
 		
 		The sound's pitch is determined from the velocity.
@@ -120,6 +167,7 @@ class KX_SoundActuator(SCA_IActuator):
 		"""
 	def setOrientation(o11, o12, o13, o21, o22, o23, o31, o32, o33):
 		"""
+		DEPRECATED: Use the orientation property instead.
 		Sets the orientation of the sound.
 		
 		The nine parameters specify a rotation matrix::
@@ -130,6 +178,7 @@ class KX_SoundActuator(SCA_IActuator):
 	
 	def setType(mode):
 		"""
+		DEPRECATED: Use the type property instead.
 		Sets the operation mode of the actuator.
 		
 		@param mode: KX_SOUNDACT_PLAYSTOP, KX_SOUNDACT_PLAYEND, KX_SOUNDACT_LOOPSTOP, KX_SOUNDACT_LOOPEND, KX_SOUNDACT_LOOPBIDIRECTIONAL, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP
@@ -138,6 +187,7 @@ class KX_SoundActuator(SCA_IActuator):
 
 	def getType():
 		"""
+		DEPRECATED: Use the type property instead.
 		Returns the operation mode of the actuator.
 		
 		@rtype: integer
diff --git a/source/gameengine/PyDoc/KX_StateActuator.py b/source/gameengine/PyDoc/KX_StateActuator.py
index fb6ae5a3621a8ce09514fc1f57d5ec66cc6b63df..d9785ad13fac6348257d4b060f75644fe59ed2af 100644
--- a/source/gameengine/PyDoc/KX_StateActuator.py
+++ b/source/gameengine/PyDoc/KX_StateActuator.py
@@ -5,9 +5,26 @@ from SCA_IActuator import *
 class KX_StateActuator(SCA_IActuator):
 	"""
 	State actuator changes the state mask of parent object.
+	
+	Property:
+	
+	@ivar operation: type of bit operation to be applied on object state mask.
+					You can use one of the following constant:
+						- KX_STATE_OP_CPY (0) : Copy state mask
+						- KX_STATE_OP_SET (1) : Add bits to state mask
+						- KX_STATE_OP_CLR (2) : Substract bits to state mask
+						- KX_STATE_OP_NEG (3) : Invert bits to state mask
+	@type operation: integer
+	
+	@ivar mask: value that defines the bits that will be modified by the operation.
+				The bits that are 1 in the mask will be updated in the object state,
+				the bits that are 0 are will be left unmodified expect for the Copy operation
+				which copies the mask to the object state
+	@type mask: integer
 	"""
 	def setOperation(op):
 		"""
+		DEPRECATED: Use the operation property instead.
 		Set the type of bit operation to be applied on object state mask.
 		Use setMask() to specify the bits that will be modified.
 		
@@ -16,6 +33,7 @@ class KX_StateActuator(SCA_IActuator):
 		"""
 	def setMask(mask):
 		"""
+		DEPRECATED: Use the mask property instead.
 		Set the value that defines the bits that will be modified by the operation.
 		The bits that are 1 in the value will be updated in the object state,
 		the bits that are 0 are will be left unmodified expect for the Copy operation
diff --git a/source/gameengine/PyDoc/KX_TouchSensor.py b/source/gameengine/PyDoc/KX_TouchSensor.py
index d7277be4c2ae2aa7d47003d1d2c54d51f061ad7a..f4fcbeefc6218717c6c0ba338a5c0e20cd2a59b4 100644
--- a/source/gameengine/PyDoc/KX_TouchSensor.py
+++ b/source/gameengine/PyDoc/KX_TouchSensor.py
@@ -17,7 +17,7 @@ class KX_TouchSensor(SCA_ISensor):
 	@ivar objectHit: The last collided object. (Read Only)
 	@type objectHit: L{KX_GameObject} or None
 	@ivar objectHitList: A list of colliding objects. (Read Only)
-	@type objectHitList: list
+	@type objectHitList: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>}
 	"""
 		
 	#--The following methods are deprecated, please use properties instead.
@@ -53,7 +53,7 @@ class KX_TouchSensor(SCA_ISensor):
 		
 		Only objects that have the requisite material/property are listed.
 		
-		@rtype: list [L{KX_GameObject}]
+		@rtype: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>}
 		"""
 	def getTouchMaterial():
 		"""
diff --git a/source/gameengine/PyDoc/KX_TrackToActuator.py b/source/gameengine/PyDoc/KX_TrackToActuator.py
index ff533e22ac0fea6192608f5c07bbffe9ba2c3929..ee2dc5d614452bab30b03bafd0a0da2fe4094f33 100644
--- a/source/gameengine/PyDoc/KX_TrackToActuator.py
+++ b/source/gameengine/PyDoc/KX_TrackToActuator.py
@@ -23,7 +23,7 @@ class KX_TrackToActuator(SCA_IActuator):
 	"""
 	def setObject(object):
 		"""
-        DEPRECATED: Use the object property.
+		DEPRECATED: Use the object property.
 		Sets the object to track.
 		
 		@type object: L{KX_GameObject}, string or None
@@ -31,7 +31,7 @@ class KX_TrackToActuator(SCA_IActuator):
 		"""
 	def getObject(name_only):
 		"""
-        DEPRECATED: Use the object property.
+		DEPRECATED: Use the object property.
 		Returns the name of the object to track.
 		
 		@type name_only: bool
@@ -40,21 +40,21 @@ class KX_TrackToActuator(SCA_IActuator):
 		"""
 	def setTime(time):
 		"""
-        DEPRECATED: Use the time property.
+		DEPRECATED: Use the time property.
 		Sets the time in frames with which to delay the tracking motion.
 		
 		@type time: integer
 		"""
 	def getTime():
 		"""
-        DEPRECATED: Use the time property.
+		DEPRECATED: Use the time property.
 		Returns the time in frames with which the tracking motion is delayed.
 		
 		@rtype: integer
 		"""
 	def setUse3D(use3d):
 		"""
-        DEPRECATED: Use the use3D property.
+		DEPRECATED: Use the use3D property.
 		Sets the tracking motion to use 3D.
 		
 		@type use3d: boolean
@@ -63,7 +63,7 @@ class KX_TrackToActuator(SCA_IActuator):
 		"""
 	def getUse3D():
 		"""
-        DEPRECATED: Use the use3D property.
+		DEPRECATED: Use the use3D property.
 		Returns True if the tracking motion will track in the z direction.
 		
 		@rtype: boolean
diff --git a/source/gameengine/PyDoc/KX_VehicleWrapper.py b/source/gameengine/PyDoc/KX_VehicleWrapper.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d91b7db676dbaf5a2dfbbd098108bdeaa732fd8
--- /dev/null
+++ b/source/gameengine/PyDoc/KX_VehicleWrapper.py
@@ -0,0 +1,168 @@
+from PyObjectPlus import *
+
+class KX_VehicleWrapper(PyObjectPlus):
+	"""
+	KX_VehicleWrapper
+	
+	All placeholders have a __ prefix
+	"""
+	
+	def addWheel(wheel, attachPos, attachDir, axleDir, suspensionRestLength, wheelRadius, hasSteering):
+		
+		"""
+		TODO - Description
+		
+		@param wheel: The object to use as a wheel.
+		@type wheel: L{KX_GameObject<KX_GameObject.KX_GameObject>} or a KX_GameObject name
+		@param attachPos: The position that this wheel will attach to.
+		@type attachPos: vector of 3 floats
+		@param attachDir: The direction this wheel points.
+		@type attachDir: vector of 3 floats
+		@param axleDir: The direction of this wheels axle.
+		@type axleDir: vector of 3 floats
+		@param suspensionRestLength: TODO - Description
+		@type suspensionRestLength: float
+		@param wheelRadius: The size of the wheel.
+		@type wheelRadius: float
+		"""
+
+	def __applyBraking(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __applyEngineForce(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getConstraintId(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getConstraintType(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getNumWheels(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getWheelOrientationQuaternion(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getWheelPosition(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __getWheelRotation(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setRollInfluence(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setSteeringValue(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setSuspensionCompression(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setSuspensionDamping(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setSuspensionStiffness(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
+	def __setTyreFriction(val):
+		"""
+		TODO - Description
+		
+		@param val: the starting frame of the animation
+		@type val: float
+		
+		@rtype: integer
+		@return: TODO Description
+		"""
diff --git a/source/gameengine/PyDoc/KX_VertexProxy.py b/source/gameengine/PyDoc/KX_VertexProxy.py
index 8dc2752c0376ad7a356ca260bb3d9908ebcc97c8..75bd4d788a61fd87e444a3766fb554a802ed55a8 100644
--- a/source/gameengine/PyDoc/KX_VertexProxy.py
+++ b/source/gameengine/PyDoc/KX_VertexProxy.py
@@ -1,7 +1,9 @@
 # $Id$
 # Documentation for the vertex proxy class
 
-class KX_VertexProxy:
+from SCA_IObject import *
+
+class KX_VertexProxy(SCA_IObject):
 	"""
 	A vertex holds position, UV, colour and normal information.
 	
@@ -34,6 +36,11 @@ class KX_VertexProxy:
 	@ivar v: The v texture coordinate of the vertex.
 	@type v: float
 	
+	@ivar u2: The second u texture coordinate of the vertex.
+	@type u2: float
+	@ivar v2: The second v texture coordinate of the vertex.
+	@type v2: float
+	
 	@group Colour: r, g, b, a
 	@ivar r: The red component of the vertex colour.   0.0 <= r <= 1.0
 	@type r: float
@@ -72,6 +79,21 @@ class KX_VertexProxy:
 		
 		@type uv: list [u, v]
 		"""
+	def getUV2():
+		"""
+		Gets the 2nd UV (texture) coordinates of this vertex.
+		
+		@rtype: list [u, v]
+		@return: this vertexes UV (texture) coordinates.
+		"""
+	def setUV2(uv, unit):
+		"""
+		Sets the 2nd UV (texture) coordinates of this vertex.
+		
+		@type uv: list [u, v]
+		@param unit: optional argument, FLAT==1, SECOND_UV==2, defaults to SECOND_UV
+		@param unit:  int
+		"""
 	def getRGBA():
 		"""
 		Gets the colour of this vertex.
@@ -120,3 +142,11 @@ class KX_VertexProxy:
 		@rtype: list [nx, ny, nz]
 		@return: normalised normal vector.
 		"""
+	def setNormal(normal):
+		"""
+		Sets the normal vector of this vertex.
+
+		@type normal: sequence of floats [r, g, b]
+		@param normal: the new normal of this vertex.
+		"""
+
diff --git a/source/gameengine/PyDoc/KX_VisibilityActuator.py b/source/gameengine/PyDoc/KX_VisibilityActuator.py
index 17d22fa5f83502ac4d8fe0dc850e0a3704f5b6ac..36f25b2423ca13a06e4b9292d70e8555f33a82a3 100644
--- a/source/gameengine/PyDoc/KX_VisibilityActuator.py
+++ b/source/gameengine/PyDoc/KX_VisibilityActuator.py
@@ -5,18 +5,18 @@ from SCA_IActuator import *
 class KX_VisibilityActuator(SCA_IActuator):
 	"""
 	Visibility Actuator.
-    @ivar visibility: whether the actuator makes its parent object visible or invisible
-    @type visibility: boolean
-    @ivar recursion: whether the visibility/invisibility should be propagated to all children of the object
-    @type recursion: boolean
+	@ivar visibility: whether the actuator makes its parent object visible or invisible
+	@type visibility: boolean
+	@ivar occlusion: whether the actuator makes its parent object an occluder or not
+	@type occlusion: boolean
+	@ivar recursion: whether the visibility/occlusion should be propagated to all children of the object
+	@type recursion: boolean
 	"""
 	def set(visible):
 		"""
-        DEPRECATED: Use the visibility property instead.
+		DEPRECATED: Use the visibility property instead.
 		Sets whether the actuator makes its parent object visible or invisible.
-		
+
 		@param visible: - True: Makes its parent visible.
 		                - False: Makes its parent invisible.
 		"""
-
-	
diff --git a/source/gameengine/PyDoc/PyObjectPlus.py b/source/gameengine/PyDoc/PyObjectPlus.py
new file mode 100644
index 0000000000000000000000000000000000000000..1750bcb6ca1f4f6f1d8e4240135958ec459ed6a3
--- /dev/null
+++ b/source/gameengine/PyDoc/PyObjectPlus.py
@@ -0,0 +1,26 @@
+#
+# Documentation for PyObjectPlus base class
+
+class PyObjectPlus:
+	"""
+	PyObjectPlus base class of most other types in the Game Engine.
+	
+	@ivar invalid:	Test if the object has been freed by the game engine and is no longer valid.
+					
+					Normally this is not a problem but when storing game engine data in the GameLogic module,
+					KX_Scenes or other KX_GameObjects its possible to hold a reference to invalid data.
+					Calling an attribute or method on an invalid object will raise a SystemError.
+					
+					The invalid attribute allows testing for this case without exception handling.
+	@type invalid:	bool
+	"""
+	
+	def isA(game_type):
+		"""
+		Check if this is a type or a subtype game_type.
+
+		@param game_type: the name of the type or the type its self from the L{GameTypes} module.
+		@type game_type: string or type
+		@return: True if this object is a type or a subtype of game_type.
+		@rtype: bool
+		"""
diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py
index 6a67cdcc71ba4c738872a57ad20567ded1d527fb..25877364836610e4bfffbd23121345680f4e5fec 100644
--- a/source/gameengine/PyDoc/Rasterizer.py
+++ b/source/gameengine/PyDoc/Rasterizer.py
@@ -44,6 +44,49 @@ Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement M
 
 """
 
+def getScreenPosition(arg):
+	"""
+	Gets the position of an object projected on screen space.
+
+	Example:
+	# For an object in the middle of the screen, coord = [0.5,0.5]
+	coord = Rasterizer.getScreenPosition(object)
+
+	@param arg: L{KX_GameObject}, object name or list [x, y, z]
+	@rtype: list [x, y]
+	@return: the object's position in screen coordinates.
+	"""
+def getScreenVect(x, y):
+	"""
+	Gets the vector from the camera position in the screen coordinate direction.
+
+	Example:
+	# Gets the vector of the camera front direction:
+	m_vect = Rasterizer.getScreenVect(0.5,0.5)
+
+	@type x: float
+	@type y: float
+	@rtype: 3d vector
+	@return: the vector from a screen coordinate.
+	"""
+def getScreenRay(x, y, dist, property):
+	"""
+	Look towards a screen coordinate (x,y) and find first object hit within dist that matches prop.
+	The ray is similar to KX_GameObject->rayCastTo.
+
+	Example:
+	# Gets an object with a property "wall" in front of the camera within a distance of 100:
+	target = Rasterizer.getScreenRay(0.5,0.5,100,"wall")
+
+	@type x: float
+	@type y: float
+	@param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other
+	@type dist: float
+	@param property: property name that object must have; can be omitted => detect any object
+	@type property: string
+	@rtype: L{KX_GameObject}
+	@return: the first object hit or None if no object or object does not match prop
+	"""
 def getWindowWidth():
 	"""
 	Gets the width of the window (in pixels)
@@ -105,6 +148,13 @@ def setMistColor(rgb):
 	
 	@type rgb: list [r, g, b]
 	"""
+	
+def setAmbientColor(rgb):
+	"""
+	Sets the color of ambient light.
+	
+	@type rgb: list [r, g, b]
+	"""
 
 def setMistStart(start):
 	"""
@@ -121,6 +171,13 @@ def setMistEnd(end):
 	@type end: float
 	"""
 	
+def disableMist():
+	"""
+	Disables mist.
+	
+	@note: Set any of the mist properties to enable mist.
+	"""
+	
 def setEyeSeparation(eyesep):
 	"""
 	Sets the eye separation for stereo mode.
@@ -194,3 +251,15 @@ def drawLine(fromVec,toVec,color):
 	@type color: list [r, g, b]
 	"""
 
+def enableMotionBlur(factor):
+	"""
+	Enable the motion blue effect.
+	
+	@param factor: the ammount of motion blur to display.
+	@type factor: float [0.0 - 1.0]
+	"""
+
+def disableMotionBlur():
+	"""
+	Disable the motion blue effect.
+	"""
diff --git a/source/gameengine/PyDoc/SCA_2DFilterActuator.py b/source/gameengine/PyDoc/SCA_2DFilterActuator.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a010e8f221355491850d01528ac4db44d232e02
--- /dev/null
+++ b/source/gameengine/PyDoc/SCA_2DFilterActuator.py
@@ -0,0 +1,44 @@
+# $Id$
+# Documentation for SCA_2DFilterActuator
+from SCA_IActuator import *
+from SCA_ILogicBrick import *
+
+class SCA_2DFilterActuator(SCA_IActuator):
+	"""
+	Create, enable and disable 2D filters
+	
+	Properties:
+	
+	The following properties don't have an immediate effect. 
+	You must active the actuator to get the result.
+	The actuator is not persistent: it automatically stops itself after setting up the filter
+	but the filter remains active. To stop a filter you must activate the actuator with 'type'
+	set to RAS_2DFILTER_DISABLED or RAS_2DFILTER_NOFILTER.
+	
+	@ivar shaderText: shader source code for custom shader
+	@type shaderText: string
+	@ivar disableMotionBlur: action on motion blur: 0=enable, 1=disable
+	@type disableMotionBlur: integer
+	@ivar type: type of 2D filter, use one of the following constants:
+				RAS_2DFILTER_ENABLED      (-2) : enable the filter that was previously disabled
+				RAS_2DFILTER_DISABLED     (-1) : disable the filter that is currently active
+				RAS_2DFILTER_NOFILTER      (0) : disable and destroy the filter that is currently active
+				RAS_2DFILTER_MOTIONBLUR    (1) : create and enable preset filters
+				RAS_2DFILTER_BLUR          (2)
+				RAS_2DFILTER_SHARPEN       (3)
+				RAS_2DFILTER_DILATION      (4)
+				RAS_2DFILTER_EROSION       (5)
+				RAS_2DFILTER_LAPLACIAN     (6)
+				RAS_2DFILTER_SOBEL         (7)
+				RAS_2DFILTER_PREWITT       (8)
+				RAS_2DFILTER_GRAYSCALE     (9)
+				RAS_2DFILTER_SEPIA        (10)
+				RAS_2DFILTER_INVERT       (11)
+				RAS_2DFILTER_CUSTOMFILTER (12) : customer filter, the code code is set via shaderText property
+	@type type: integer				
+	@ivar passNb: order number of filter in the stack of 2D filters. Filters are executed in increasing order of passNb.
+	              Only be one filter can be defined per passNb.
+	@type passNb: integer (0-100)
+	@ivar value: argument for motion blur filter
+	@type value: float (0.0-100.0)
+	"""
diff --git a/source/gameengine/PyDoc/KX_ActuatorSensor.py b/source/gameengine/PyDoc/SCA_ActuatorSensor.py
similarity index 87%
rename from source/gameengine/PyDoc/KX_ActuatorSensor.py
rename to source/gameengine/PyDoc/SCA_ActuatorSensor.py
index b0e138a8009a491c0cad34290bff423b70f43d0a..515354e8716bb2178552a5786061bdb6989d0d2f 100644
--- a/source/gameengine/PyDoc/KX_ActuatorSensor.py
+++ b/source/gameengine/PyDoc/SCA_ActuatorSensor.py
@@ -1,9 +1,10 @@
 # $Id$
-# Documentation for KX_ActuatorSensor
+# Documentation for SCA_ActuatorSensor
 from SCA_IActuator import *
 from SCA_ISensor import *
+from SCA_ILogicBrick import *
 
-class KX_ActuatorSensor(SCA_ISensor):
+class SCA_ActuatorSensor(SCA_ISensor):
 	"""
 	Actuator sensor detect change in actuator state of the parent object.
 	It generates a positive pulse if the corresponding actuator is activated
diff --git a/source/gameengine/PyDoc/SCA_IController.py b/source/gameengine/PyDoc/SCA_IController.py
index f83e7c97dcec8dc9e416c5c9a281905fc65b4e69..cfb4c18a826674dcfb4737600e13056e3130eaa4 100644
--- a/source/gameengine/PyDoc/SCA_IController.py
+++ b/source/gameengine/PyDoc/SCA_IController.py
@@ -5,5 +5,59 @@ from SCA_ILogicBrick import *
 class SCA_IController(SCA_ILogicBrick):
 	"""
 	Base class for all controller logic bricks.
+	
+	@ivar state: the controllers state bitmask.
+	             This can be used with the GameObject's state to test if the controller is active.
+	@type state: int bitmask
+	@ivar sensors: a list of sensors linked to this controller
+					- note: the sensors are not necessarily owned by the same object.
+					- note: when objects are instanced in dupligroups links may be lost from objects outside the dupligroup.
+	@type sensors: sequence supporting index/string lookups and iteration.
+	@ivar actuators: a list of actuators linked to this controller.
+						- note: the sensors are not necessarily owned by the same object.
+						- note: when objects are instanced in dupligroups links may be lost from objects outside the dupligroup.
+	@type actuators: sequence supporting index/string lookups and iteration.
+	
+	@group Deprecated: getState, getSensors, getActuators, getSensor, getActuator
 	"""
 
+	def getState():
+		"""
+		DEPRECATED: use the state property
+		Get the controllers state bitmask, this can be used with the GameObject's state to test if the the controller is active.
+		This for instance will always be true however you could compare with a previous state to see when the state was activated.
+		GameLogic.getCurrentController().getState() & GameLogic.getCurrentController().getOwner().getState()
+		
+		@rtype: int
+		"""
+	def getSensors():
+		"""
+		DEPRECATED: use the sensors property
+		Gets a list of all sensors attached to this controller.
+		
+		@rtype: list [L{SCA_ISensor}]
+		"""
+	def getSensor(name):
+		"""
+		DEPRECATED: use the sensors[name] property
+		Gets the named linked sensor.
+		
+		@type name: string
+		@rtype: L{SCA_ISensor}
+		"""
+	def getActuators():
+		"""
+		DEPRECATED: use the actuators property
+		Gets a list of all actuators linked to this controller.
+		
+		@rtype: list [L{SCA_IActuator}]
+		"""
+	def getActuator(name):
+		"""
+		DEPRECATED: use the actuators[name] property
+		Gets the named linked actuator.
+		
+		@type name: string
+		@rtype: L{SCA_IActuator}
+		"""
+		
\ No newline at end of file
diff --git a/source/gameengine/PyDoc/SCA_ILogicBrick.py b/source/gameengine/PyDoc/SCA_ILogicBrick.py
index 18cb900f28d0f68f8cdaf3dc275657b8add55c4f..a96e77c3249325166eb9dc3a1f779eab4e0711d7 100644
--- a/source/gameengine/PyDoc/SCA_ILogicBrick.py
+++ b/source/gameengine/PyDoc/SCA_ILogicBrick.py
@@ -1,20 +1,28 @@
 # $Id$
 # Documentation for the logic brick base class SCA_ILogicBrick
 from KX_GameObject import *
+from CValue import *
 
-class SCA_ILogicBrick:
+class SCA_ILogicBrick(CValue):
 	"""
 	Base class for all logic bricks.
 	
 	@ivar executePriority: This determines the order controllers are evaluated, and actuators are activated (lower priority is executed first).
 	@type executePriority: int
+	@ivar owner: The game object this logic brick is attached to (read only).
+	@type owner: L{KX_GameObject<KX_GameObject.KX_GameObject>} or None in exceptional cases.
+	@ivar name: The name of this logic brick (read only).
+	@type name: string
+	@group Deprecated: getOwner, setExecutePriority, getExecutePriority
 	"""
 	
 	def getOwner():
 		"""
 		Gets the game object associated with this logic brick.
 		
-		@rtype: L{KX_GameObject}
+		Deprecated: Use the "owner" property instead.
+		
+		@rtype: L{KX_GameObject<KX_GameObject.KX_GameObject>}
 		"""
 
 	#--The following methods are deprecated--
diff --git a/source/gameengine/PyDoc/SCA_IObject.py b/source/gameengine/PyDoc/SCA_IObject.py
new file mode 100644
index 0000000000000000000000000000000000000000..92e4884e815b6dd2073a4fc3fc6c0b2f7d93f693
--- /dev/null
+++ b/source/gameengine/PyDoc/SCA_IObject.py
@@ -0,0 +1,9 @@
+# 
+# Documentation for SCA_IObject class
+
+from CValue import *
+class SCA_IObject(CValue):
+	"""
+	This class has no python functions
+	"""
+	pass
diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py
index ab35996aa50652bcd0f95191b7fccae3c637e5c4..0b72548b103e455522762f35d6aab483a39cf65a 100644
--- a/source/gameengine/PyDoc/SCA_ISensor.py
+++ b/source/gameengine/PyDoc/SCA_ISensor.py
@@ -24,6 +24,7 @@ class SCA_ISensor(SCA_ILogicBrick):
 	@type triggered: boolean
 	@ivar positive: True if this sensor brick is in a positive state. (Read only)
 	@type positive: boolean
+	@group Deprecated: isPositive, isTriggered, getUsePosPulseMode, setUsePosPulseMode, getFrequency, setFrequency, getUseNegPulseMode,	setUseNegPulseMode, getInvert, setInvert, getLevel, setLevel
 	"""
 	
 	def reset():
diff --git a/source/gameengine/PyDoc/SCA_JoystickSensor.py b/source/gameengine/PyDoc/SCA_JoystickSensor.py
index 944ff64dc64a98b0868f77872e8a5536671903a6..13b006e8dd6485056f678280ec628fda10c8a9c3 100644
--- a/source/gameengine/PyDoc/SCA_JoystickSensor.py
+++ b/source/gameengine/PyDoc/SCA_JoystickSensor.py
@@ -8,10 +8,16 @@ class SCA_JoystickSensor(SCA_ISensor):
 	
 	Properties:
 	
-	@ivar axisPosition: (read-only) The state of the joysticks axis as a list of 4 values, each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. 
-	                    The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls.
-	                    left:[-32767, 0, ...], right:[32767, 0, ...], up:[0, -32767, ...], down:[0, 32767, ...]
-	@type axisPosition: [integer, integer, integer, integer]
+	@ivar axisValues: (read-only) The state of the joysticks axis as a list of values L{numAxis} long.
+						each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. 
+						The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls.
+						left:[-32767, 0, ...], right:[32767, 0, ...], up:[0, -32767, ...], down:[0, 32767, ...]
+	@type axisValues: list of ints
+	
+	@ivar axisSingle: (read-only) like L{axisValues} but returns a single axis value that is set by the sensor.
+						Only use this for "Single Axis" type sensors otherwise it will raise an error.
+	@type axisSingle: int
+	
 	@ivar numAxis: (read-only) The number of axes for the joystick at this index.
 	@type numAxis: integer
 	@ivar numButtons: (read-only) The number of buttons for the joystick at this index.
@@ -41,13 +47,13 @@ class SCA_JoystickSensor(SCA_ISensor):
 		Returns a list containing the indicies of the currently pressed buttons.
 		@rtype: list
 		"""
-    def getButtonStatus(buttonIndex):
-        """
-        Returns a bool of the current pressed state of the specified button.
-        @param buttonIndex: the button index, 0=first button
-        @type buttonIndex: integer
-        @rtype: bool
-        """
+	def getButtonStatus(buttonIndex):
+		"""
+		Returns a bool of the current pressed state of the specified button.
+		@param buttonIndex: the button index, 0=first button
+		@type buttonIndex: integer
+		@rtype: bool
+		"""
 	def getIndex():
 		"""
 		DEPRECATED: use the 'index' property.
diff --git a/source/gameengine/PyDoc/SCA_KeyboardSensor.py b/source/gameengine/PyDoc/SCA_KeyboardSensor.py
index f6a7a7d8a97bdcd6d9521cf7cf702af2b99e7416..8abb1fda762754df5173b6d58f950424dd406e11 100644
--- a/source/gameengine/PyDoc/SCA_KeyboardSensor.py
+++ b/source/gameengine/PyDoc/SCA_KeyboardSensor.py
@@ -20,31 +20,34 @@ class SCA_KeyboardSensor(SCA_ISensor):
 	@type targetProperty: string
 	@ivar useAllKeys: Flag to determine whether or not to accept all keys.
 	@type useAllKeys: boolean
+	@ivar events: a list of pressed keys that have either been pressed, or just released, or are active this frame. (read only).
+
+			- 'keycode' matches the values in L{GameKeys}.
+			- 'status' uses...
+				- L{GameLogic.KX_INPUT_NONE}
+				- L{GameLogic.KX_INPUT_JUST_ACTIVATED}
+				- L{GameLogic.KX_INPUT_ACTIVE}
+				- L{GameLogic.KX_INPUT_JUST_RELEASED}
+			
+	@type events: list [[keycode, status], ...]
 	"""
-	def getEventList():
-		"""
-		Get a list of pressed keys that have either been pressed, or just released, or are active this frame.
-		
-		@rtype: list of key status. [[keycode, status]]
-		@return: A list of keyboard events
-		"""
 	
 	def getKeyStatus(keycode):
 		"""
 		Get the status of a key.
 		
-		@rtype: key state (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED)
+		@rtype: key state L{GameLogic} members (KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED)
 		@return: The state of the given key
 		@type keycode: integer
 		@param keycode: The code that represents the key you want to get the state of
 		"""
 	
-	#--The following methods are deprecated--
+	#--The following methods are DEPRECATED--
 	def getKey():
 		"""
 		Returns the key code this sensor is looking for.
 		
-		Deprecated: Use the "key" property instead.
+		B{DEPRECATED: Use the "key" property instead}.
 		
 		@rtype: keycode from L{GameKeys} module
 		"""
@@ -53,7 +56,7 @@ class SCA_KeyboardSensor(SCA_ISensor):
 		"""
 		Set the key this sensor should listen for.
 		
-		Deprecated: Use the "key" property instead.
+		B{DEPRECATED: Use the "key" property instead}.
 		
 		@type keycode: keycode from L{GameKeys} module
 		"""
@@ -62,7 +65,7 @@ class SCA_KeyboardSensor(SCA_ISensor):
 		"""
 		Returns the key code for the first modifier this sensor is looking for.
 		
-		Deprecated: Use the "hold1" property instead.
+		B{DEPRECATED: Use the "hold1" property instead}.
 		
 		@rtype: keycode from L{GameKeys} module
 		"""
@@ -71,7 +74,7 @@ class SCA_KeyboardSensor(SCA_ISensor):
 		"""
 		Sets the key code for the first modifier this sensor should look for.
 		
-		Deprecated: Use the "hold1" property instead.
+		B{DEPRECATED: Use the "hold1" property instead}.
 		
 		@type keycode: keycode from L{GameKeys} module
 		"""
@@ -80,7 +83,7 @@ class SCA_KeyboardSensor(SCA_ISensor):
 		"""
 		Returns the key code for the second modifier this sensor is looking for.
 		
-		Deprecated: Use the "hold2" property instead.
+		B{DEPRECATED: Use the "hold2" property instead}.
 		
 		@rtype: keycode from L{GameKeys} module
 		"""
@@ -89,7 +92,7 @@ class SCA_KeyboardSensor(SCA_ISensor):
 		"""
 		Sets the key code for the second modifier this sensor should look for.
 		
-		Deprecated: Use the "hold2" property instead.
+		B{DEPRECATED: Use the "hold2" property instead.}
 		
 		@type keycode: keycode from L{GameKeys} module
 		"""
@@ -98,7 +101,7 @@ class SCA_KeyboardSensor(SCA_ISensor):
 		"""
 		Get a list of keys that have either been pressed, or just released this frame.
 		
-		Deprecated: Use getEventList() instead.
+		B{DEPRECATED: Use "events" instead.}
 		
 		@rtype: list of key status. [[keycode, status]]
 		"""
@@ -107,7 +110,7 @@ class SCA_KeyboardSensor(SCA_ISensor):
 		"""
 		Get a list of currently pressed keys that have either been pressed, or just released
 		
-		Deprecated: Use getEventList() instead.
+		B{DEPRECATED: Use "events" instead.}
 		
 		@rtype: list of key status. [[keycode, status]]
 		"""
\ No newline at end of file
diff --git a/source/gameengine/PyDoc/SCA_MouseSensor.py b/source/gameengine/PyDoc/SCA_MouseSensor.py
index 9550cbb4105e897e93d8218c253aea721ceea583..278ebe63b8a93d19b4390086f1456e6a548edf70 100644
--- a/source/gameengine/PyDoc/SCA_MouseSensor.py
+++ b/source/gameengine/PyDoc/SCA_MouseSensor.py
@@ -32,3 +32,13 @@ class SCA_MouseSensor(SCA_ISensor):
 		@rtype: integer
 		@return: the current y coordinate of the mouse, in frame coordinates (pixels).
 		"""	
+	def getButtonStatus(button):
+		"""
+		Get the mouse button status.
+		
+		@type button: int
+		@param button: value in GameLogic members KX_MOUSE_BUT_LEFT, KX_MOUSE_BUT_MIDDLE, KX_MOUSE_BUT_RIGHT
+		
+		@rtype: integer
+		@return: value in GameLogic members KX_INPUT_NONE, KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED
+		"""
diff --git a/source/gameengine/PyDoc/SCA_NANDController.py b/source/gameengine/PyDoc/SCA_NANDController.py
new file mode 100644
index 0000000000000000000000000000000000000000..a864ff2981cff9af95b625e22808861d2bab97c3
--- /dev/null
+++ b/source/gameengine/PyDoc/SCA_NANDController.py
@@ -0,0 +1,11 @@
+# $Id$
+# Documentation for SCA_NANDController
+from SCA_IController import *
+
+class SCA_NANDController(SCA_IController):
+	"""
+	An NAND controller activates when all linked sensors are not active.
+	
+	There are no special python methods for this controller.
+	"""
+
diff --git a/source/gameengine/PyDoc/SCA_NORController.py b/source/gameengine/PyDoc/SCA_NORController.py
new file mode 100644
index 0000000000000000000000000000000000000000..0bc0a71d7b15ed98edd31b13298a72eda093068c
--- /dev/null
+++ b/source/gameengine/PyDoc/SCA_NORController.py
@@ -0,0 +1,11 @@
+# $Id$
+# Documentation for SCA_NORController
+from SCA_IController import *
+
+class SCA_NORController(SCA_IController):
+	"""
+	An NOR controller activates only when all linked sensors are de-activated.
+	
+	There are no special python methods for this controller.
+	"""
+
diff --git a/source/gameengine/PyDoc/SCA_PythonController.py b/source/gameengine/PyDoc/SCA_PythonController.py
index 9684b41d48128c0bc78e19369d05c2b01f21af36..7b9b6ccd80a17ac3d81be0c3f37426a618be0cd9 100644
--- a/source/gameengine/PyDoc/SCA_PythonController.py
+++ b/source/gameengine/PyDoc/SCA_PythonController.py
@@ -11,9 +11,8 @@ class SCA_PythonController(SCA_IController):
 	
 	@ivar script: the Python script this controller executes
 	@type script: string, read-only
-	@ivar state: the controllers state bitmask.
-	             This can be used with the GameObject's state to test if the controller is active.
-	@type state: integer
+	
+	@group Deprecated: getScript, setScript
 	"""
 	def activate(actuator):
 		"""
@@ -25,33 +24,6 @@ class SCA_PythonController(SCA_IController):
 		Deactivates an actuator attached to this controller.
 		@type actuator: actuator or the actuator name as a string
 		"""
-		
-	def getSensors():
-		"""
-		Gets a list of all sensors attached to this controller.
-		
-		@rtype: list [L{SCA_ISensor}]
-		"""
-	def getSensor(name):
-		"""
-		Gets the named linked sensor.
-		
-		@type name: string
-		@rtype: L{SCA_ISensor}
-		"""
-	def getActuators():
-		"""
-		Gets a list of all actuators linked to this controller.
-		
-		@rtype: list [L{SCA_IActuator}]
-		"""
-	def getActuator(name):
-		"""
-		Gets the named linked actuator.
-		
-		@type name: string
-		@rtype: L{SCA_IActuator}
-		"""
 	def getScript():
 		"""
 		DEPRECATED: use the script property
@@ -61,17 +33,9 @@ class SCA_PythonController(SCA_IController):
 		"""
 	def setScript(script):
 		"""
+		DEPRECATED: use the script property
 		Sets the Python script this controller executes.
 		
 		@type script: string.
 		"""
-	def getState():
-		"""
-		DEPRECATED: use the state property
-		Get the controllers state bitmask, this can be used with the GameObject's state to test if the the controller is active.
-		This for instance will always be true however you could compare with a previous state to see when the state was activated.
-		GameLogic.getCurrentController().getState() & GameLogic.getCurrentController().getOwner().getState()
-		
-		@rtype: int
-		"""
 
diff --git a/source/gameengine/PyDoc/SCA_RandomSensor.py b/source/gameengine/PyDoc/SCA_RandomSensor.py
index 940b8f879ffd257b1e425d4bf817586e4a1c8409..6dc0a3c23c0377a784d46b5d8fbe5c93a86368dd 100644
--- a/source/gameengine/PyDoc/SCA_RandomSensor.py
+++ b/source/gameengine/PyDoc/SCA_RandomSensor.py
@@ -5,6 +5,11 @@ from SCA_ISensor import *
 class SCA_RandomSensor(SCA_ISensor):
 	"""
 	This sensor activates randomly.
+
+	@ivar lastDraw: The seed of the random number generator.
+	@type lastDraw: int
+	@ivar seed: The seed of the random number generator.
+	@type seed: int
 	"""
 	
 	def setSeed(seed):
@@ -25,4 +30,6 @@ class SCA_RandomSensor(SCA_ISensor):
 	def getLastDraw():
 		"""
 		Returns the last random number generated.
+		
+		@rtype: integer
 		"""
diff --git a/source/gameengine/PyDoc/SCA_XNORController.py b/source/gameengine/PyDoc/SCA_XNORController.py
new file mode 100644
index 0000000000000000000000000000000000000000..5fb2561f35a87ed63670dcae741bacec5cd26126
--- /dev/null
+++ b/source/gameengine/PyDoc/SCA_XNORController.py
@@ -0,0 +1,11 @@
+# $Id$
+# Documentation for SCA_XNORController
+from SCA_IController import *
+
+class SCA_XNORController(SCA_IController):
+	"""
+	An XNOR controller activates when all linked sensors are the same (activated or inative).
+	
+	There are no special python methods for this controller.
+	"""
+
diff --git a/source/gameengine/PyDoc/SCA_XORController.py b/source/gameengine/PyDoc/SCA_XORController.py
new file mode 100644
index 0000000000000000000000000000000000000000..10e20fb0945007ce147b1aec00e48ee08b8a0827
--- /dev/null
+++ b/source/gameengine/PyDoc/SCA_XORController.py
@@ -0,0 +1,11 @@
+# $Id$
+# Documentation for SCA_XORController
+from SCA_IController import *
+
+class SCA_XORController(SCA_IController):
+	"""
+	An XOR controller activates when there is the input is mixed, but not when all are on or off.
+	
+	There are no special python methods for this controller.
+	"""
+
diff --git a/source/gameengine/PyDoc/SConscript b/source/gameengine/PyDoc/SConscript
index ac0b163d7bd00ca84f5817f07f2f28747e49ffc2..ed9712ba2736962e2ef112cdbe79e073437579ed 100644
--- a/source/gameengine/PyDoc/SConscript
+++ b/source/gameengine/PyDoc/SConscript
@@ -3,26 +3,27 @@ Import ('env')
 
 
 from optparse import OptionParser
-try:
-    import epydoc
-except ImportError:
-    print "No epydoc install detected, Python API Docs will not be generated "
-if epydoc:
-    from epydoc.docbuilder import build_doc_index
-    from epydoc import cli
-    names = env.Glob("source/gameengine/PyDoc/*.py")
-    docindex = build_doc_index(names)
-    optvalues = cli.OPTION_DEFAULTS
-    optvalues["verbose"] = 1
-    optvalues["target"] = env["BF_DOCDIR"]+"/BGE_API/"
-    optvalues["url"] = "http://www.blender.org"
-    optvalues["top"] = "Game Engine API"
-    optvalues["name"] = "Blender"
-    optvalues["noprivate"] = 1
-    optvalues["noframes"] = 1
-    optvalues["names"] = names
-    optparser = OptionParser()
-    optparser.set_defaults(**optvalues)
-    (options, args) = optparser.parse_args([])
-    cli.write_html(docindex, options)
+import epydoc
+from epydoc.docbuilder import build_doc_index
+from epydoc import cli
+names = env.Glob("source/gameengine/PyDoc/*.py")
+docindex = build_doc_index(names)
+optvalues = cli.OPTION_DEFAULTS
+optvalues["verbose"] = 1
+optvalues["quiet"] = 0
+optvalues["include_source_code"] = 0
+optvalues["inheritance"] = "included"
+optvalues["show_private"] = 0
+optvalues["target"] = env["BF_DOCDIR"]+"/BGE_API/"
+optvalues["url"] = "http://www.blender.org"
+optvalues["top"] = "Game Engine API"
+optvalues["name"] = "Blender"
+optvalues["noprivate"] = 1
+optvalues["noframes"] = 1
+optvalues["names"] = names
+optparser = OptionParser()
+optparser.set_defaults(**optvalues)
+(options, args) = optparser.parse_args([])
+print "Writing Game Engine epydocs to \"%s\"" % optvalues["target"]
+cli.write_html(docindex, options)
 
diff --git a/source/gameengine/PyDoc/WhatsNew.py b/source/gameengine/PyDoc/WhatsNew.py
index 64bef7ee1c8a4f126451142d19578049124d0cfa..4d86e6ef3c4764e53ebdb6fb3239f52eed5593bc 100644
--- a/source/gameengine/PyDoc/WhatsNew.py
+++ b/source/gameengine/PyDoc/WhatsNew.py
@@ -26,7 +26,7 @@ Blender 2.34
 	- Added getType() and setType() to L{BL_ActionActuator} and L{KX_SoundActuator} (sgefant)
 	- New Scene module: L{KX_Scene}
 	- New Camera module: L{KX_Camera}
-	- New Light module: L{KX_Light}
+	- New Light module: L{KX_LightObject}
 	- Added attributes to L{KX_GameObject}, L{KX_VertexProxy}
 	- L{KX_SCA_AddObjectActuator}.setObject(), L{KX_TrackToActuator}.setObject() and 
 	  L{KX_SceneActuator}.setCamera() now accept L{KX_GameObject}s as parameters
diff --git a/source/gameengine/PyDoc/bge_api_validate_py.txt b/source/gameengine/PyDoc/bge_api_validate_py.txt
new file mode 100644
index 0000000000000000000000000000000000000000..492dcef408b51bbbeece73148410ae103922ac5d
--- /dev/null
+++ b/source/gameengine/PyDoc/bge_api_validate_py.txt
@@ -0,0 +1,145 @@
+#~ 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; version 2 of the License.
+
+#~ 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.
+
+# This script must run from a logic brick so it has access to the game engine api
+# it assumes the root blender source directory is the current working directory
+# 
+# Currently it only prints missing modules and methods (not attributes)
+
+import sys, os
+
+BGE_API_DOC_PATH = 'source/gameengine/PyDoc'
+
+
+mods = ['GameLogic', 'Rasterizer', 'GameKeys']
+mods_dict = {}
+for m in mods:
+	mods_dict[m] = sys.modules[m]
+
+
+import GameTypes
+type_members = {}
+
+for type_name in dir(GameTypes):
+	if type_name.startswith('__'):
+		continue
+	
+	type_object = getattr(GameTypes, type_name)
+	
+	members = []
+	type_members[type_object.__name__] = members
+	
+	for member in type_object.__dict__.keys():
+		if member.startswith('__'):
+			continue
+		
+		# print type_object.__name__ + '.' + k
+		members.append(member)
+
+
+
+doc_dir= os.path.join(os.getcwd(), BGE_API_DOC_PATH)
+
+if doc_dir not in sys.path:
+	sys.path.append(doc_dir)
+
+
+def check_attribute(type_mame, member):
+	filename = 	os.path.join(doc_dir, type_mame + '.py')
+	# print filename
+	
+	file = open(filename, 'rU')
+	
+	for l in file:
+		l = l.strip()
+		
+		'''
+			@ivar foo: blah blah
+		to
+			foo
+			
+		'''
+		
+		if l.startswith('@ivar') or l.startswith('@var'):
+			var = l.split()[1].split(':')[0]
+			
+			if var == member:
+				file.close()
+				return True
+	
+	file.close()
+	return False
+	
+	
+	
+	
+
+
+print '\n\n\nChecking Docs'
+
+PRINT_OK = False
+
+for type_name in sorted(type_members.keys()):
+	members = type_members[type_name]
+	
+	try:
+		mod = __import__(type_name)
+		if PRINT_OK:
+			print "type: %s" % type_name
+	except:
+		print "missing: %s - %s" % (type_name, str(sorted(members)))
+		continue
+	
+	reload(mod) # incase were editing it
+	
+	try:
+		type_class = getattr(mod, type_name)
+	except:
+		print "missing class: %s.%s - %s" % (type_name, type_name, str(sorted(members)))
+		continue
+	
+	for member in sorted(members):
+		try:
+			getattr(type_class, member)
+			if PRINT_OK:
+				print "\tfound: %s.%s" % (type_name, member)
+		except:
+			if check_attribute(type_name, member):
+				if PRINT_OK:
+					print "\tfound attr: %s.%s" % (type_name, member)
+			else:
+				print "\tmissing: %s.%s" % (type_name, member)
+
+
+# Now check the modules
+for mod_name, pymod in mods_dict.iteritems():
+	print pymod
+	del sys.modules[mod_name]
+		
+	# Now well get the python version
+	pydoc = __import__(mod_name)
+	pydoc = reload(pydoc) # avoid using the out dated pyc file only
+	print pydoc.__file__
+	
+	for member in sorted(dir(pymod)):
+		if hasattr(pydoc, member) or check_attribute(mod_name, member):
+			if PRINT_OK:
+				print "\tfound module attr: %s.%s" % (mod_name, member)
+		else:
+			print "\tmissing module attr: %s.%s" % (mod_name, member)
+	
+	# Restore real module
+	sys.modules[mod_name] = pymod
+
+
+sys.path.pop() # remove the pydoc dir from our import paths
+
+
+
+
diff --git a/source/gameengine/PyDoc/epy_docgen.sh b/source/gameengine/PyDoc/epy_docgen.sh
old mode 100644
new mode 100755
index b243101ddcb9f62d083007ec2fc302f802682a6f..ddf39dcc08193fd1ede77f419a67126a0b582c49
--- a/source/gameengine/PyDoc/epy_docgen.sh
+++ b/source/gameengine/PyDoc/epy_docgen.sh
@@ -8,4 +8,4 @@
 LC_ALL=POSIX
 
 epydoc --debug -v  -o BPY_GE --url "http://www.blender.org" --top GameLogic \
- --name "Blender GameEngine" --no-private --no-frames *.py 
+ --name "Blender GameEngine" --no-private --no-frames --no-sourcecode --inheritance=included *.py 
diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt
index 6d53ee53471d14b50f83bab0d5ad1ad9c0834cc1..143209f5a54abd6dd2081e9fbbe17f5216bcb792 100644
--- a/source/gameengine/Rasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/CMakeLists.txt
@@ -29,6 +29,8 @@ FILE(GLOB SRC *.cpp)
 SET(INC
   .
   ../../../source/kernel/gen_system
+  ../../../source/blender/makesdna
+  ../../../source/gameengine/SceneGraph
   ../../../intern/string
   ../../../intern/moto/include
   ../../../extern/glew/include
diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile
index 917f70c7108baac925f04b1fe1e48a4dd303c676..eafa2ded2f20506c397f440ae8d7f20fa7567a25 100644
--- a/source/gameengine/Rasterizer/Makefile
+++ b/source/gameengine/Rasterizer/Makefile
@@ -40,6 +40,8 @@ CPPFLAGS += -I$(OPENGL_HEADERS)
 CPPFLAGS += -I$(NAN_STRING)/include    
 CPPFLAGS += -I$(NAN_MOTO)/include
 CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../../blender/makesdna
+CPPFLAGS += -I../SceneGraph
 CPPFLAGS += -I../BlenderRoutines
 CPPFLAGS += -I../Expressions
 
diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index 282c730628591f29c43e1b355f45997db498890f..239031866ca8ba7b90feabc9636a29f51e2fac7e 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -63,11 +63,9 @@ numberoffilters(0), need_tex_update(true)
 	isshadersupported = GLEW_ARB_shader_objects &&
 		GLEW_ARB_fragment_shader && GLEW_ARB_multitexture;
 
+	/* used to return before 2.49 but need to initialize values so dont */
 	if(!isshadersupported)
-	{
 		std::cout<<"shaders not supported!" << std::endl;
-		return;
-	}
 
 	int passindex;
 	for(passindex =0; passindex<MAX_RENDER_PASS; passindex++)
@@ -435,11 +433,12 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
 	glViewport(0,0, texturewidth, textureheight);
 
 	glDisable(GL_DEPTH_TEST);
+	glPushMatrix();		//GL_MODELVIEW
+	glLoadIdentity();	// GL_MODELVIEW
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
 	glMatrixMode(GL_PROJECTION);
-	glLoadIdentity();
-	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
 	glLoadIdentity();
 
 	for(passindex =0; passindex<MAX_RENDER_PASS; passindex++)
@@ -466,6 +465,9 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
 	glEnable(GL_DEPTH_TEST);
 	glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);
 	EndShaderProgram();	
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
 }
 
 void RAS_2DFilterManager::EnableFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFILTER_MODE mode, int pass, STR_String& text)
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
index f7938bb62e67e28b1ad5800f13487e67730b25dc..200b1c6c89f1d516bf908a59116c44cf39004bc2 100644
--- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
@@ -113,16 +113,26 @@ void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList
 	const MT_Vector3 pnorm(cameratrans.getBasis()[2]);
 
 	for (bit = buckets.begin(); bit != buckets.end(); ++bit)
-		for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit)
-			if (!mit->IsCulled())
-				size++;
+	{
+		SG_DList::iterator<RAS_MeshSlot> mit((*bit)->GetActiveMeshSlots());
+		for(mit.begin(); !mit.end(); ++mit)
+			size++;
+	}
 
 	slots.resize(size);
 
 	for (bit = buckets.begin(); bit != buckets.end(); ++bit)
-		for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit)
-			if (!mit->IsCulled())
-				slots[i++].set(&*mit, *bit, pnorm);
+	{
+		RAS_MaterialBucket* bucket = *bit;
+		RAS_MeshSlot* ms;
+		// remove the mesh slot form the list, it culls them automatically for next frame
+		for(ms = bucket->GetNextActiveMeshSlot();
+			ms!= NULL;
+			ms = bucket->GetNextActiveMeshSlot())
+		{
+			slots[i++].set(ms, bucket, pnorm);
+		}
+	}
 		
 	if(alpha)
 		sort(slots.begin(), slots.end(), backtofront());
@@ -148,6 +158,10 @@ void RAS_BucketManager::RenderAlphaBuckets(
 
 		while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools))
 			sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms));
+
+		// make this mesh slot culled automatically for next frame
+		// it will be culled out by frustrum culling
+		sit->m_ms->SetCulled(true);
 	}
 
 	rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
@@ -157,11 +171,28 @@ void RAS_BucketManager::RenderSolidBuckets(
 	const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
 {
 	BucketList::iterator bit;
-	list<RAS_MeshSlot>::iterator mit;
 
 	rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
 
 	for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
+#if 1
+		RAS_MaterialBucket* bucket = *bit;
+		RAS_MeshSlot* ms;
+		// remove the mesh slot form the list, it culls them automatically for next frame
+		for(ms = bucket->GetNextActiveMeshSlot();
+			ms!= NULL;
+			ms = bucket->GetNextActiveMeshSlot())
+		{
+			rendertools->SetClientObject(rasty, ms->m_clientObj);
+			while (bucket->ActivateMaterial(cameratrans, rasty, rendertools))
+				bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *ms);
+
+			// make this mesh slot culled automatically for next frame
+			// it will be culled out by frustrum culling
+			ms->SetCulled(true);
+		}
+#else
+		list<RAS_MeshSlot>::iterator mit;
 		for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
 			if (mit->IsCulled())
 				continue;
@@ -170,7 +201,12 @@ void RAS_BucketManager::RenderSolidBuckets(
 
 			while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools))
 				(*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit);
+
+			// make this mesh slot culled automatically for next frame
+			// it will be culled out by frustrum culling
+			mit->SetCulled(true);
 		}
+#endif
 	}
 	
 	/* this code draws meshes order front-to-back instead to reduce overdraw.
@@ -268,3 +304,21 @@ void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat)
 	}
 }
 
+void RAS_BucketManager::ReleaseMaterials(RAS_IPolyMaterial * mat)
+{
+	BucketList::iterator bit;
+	list<RAS_MeshSlot>::iterator mit;
+
+	for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
+		if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
+			(*bit)->GetPolyMaterial()->ReleaseMaterial();
+		}
+	}
+	
+	for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) {
+		if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
+			(*bit)->GetPolyMaterial()->ReleaseMaterial();
+		}
+	}
+}
+
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h
index 74526f365a000b0d66ada697043ff3060954221b..2b81ddd3c826b7965e020ccc6d7585479c0985db 100644
--- a/source/gameengine/Rasterizer/RAS_BucketManager.h
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.h
@@ -58,6 +58,7 @@ public:
 	void OptimizeBuckets(MT_Scalar distance);
 	
 	void ReleaseDisplayLists(RAS_IPolyMaterial * material = NULL);
+	void ReleaseMaterials(RAS_IPolyMaterial * material = NULL);
 
 private:
 	void OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha);
diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h
index e3af43fb839d391bdd517f2a6fb2b53cd022534b..c8f4d9a0a17c5a1713d7f56bf99f352bc54c5e09 100644
--- a/source/gameengine/Rasterizer/RAS_CameraData.h
+++ b/source/gameengine/Rasterizer/RAS_CameraData.h
@@ -32,6 +32,7 @@
 struct RAS_CameraData
 {
 	float m_lens;
+	float m_scale;
 	float m_clipstart;
 	float m_clipend;
 	bool m_perspective;
@@ -42,10 +43,11 @@ struct RAS_CameraData
 	int m_viewporttop;
 	float m_focallength;
 
-	RAS_CameraData(float lens = 35.0, float clipstart = 0.1, float clipend = 5000.0, bool perspective = true,
+	RAS_CameraData(float lens = 35.0, float scale = 6.0, float clipstart = 0.1, float clipend = 5000.0, bool perspective = true,
 	float focallength = 0.0f, bool viewport = false, int viewportleft = 0, int viewportbottom = 0, 
 	int viewportright = 0, int viewporttop = 0) :
 		m_lens(lens),
+		m_scale(scale),
 		m_clipstart(clipstart),
 		m_clipend(clipend),
 		m_perspective(perspective),
diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h
index 3332ac4c0a76eaf374fa2cec73368ad6e9880091..fe081dd4aa5754bd7f22763c164dc41e0d568877 100644
--- a/source/gameengine/Rasterizer/RAS_Deformer.h
+++ b/source/gameengine/Rasterizer/RAS_Deformer.h
@@ -44,11 +44,17 @@ public:
 	virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)=0;
 	virtual bool Apply(class RAS_IPolyMaterial *polymat)=0;
 	virtual bool Update(void)=0;
-	virtual RAS_Deformer *GetReplica(class KX_GameObject* replica)=0;
+	virtual bool UpdateBuckets(void)=0;
+	virtual RAS_Deformer *GetReplica()=0;
+	virtual void ProcessReplica()=0;
 	virtual bool SkipVertexTransform()
 	{
 		return false;
 	}
+	virtual bool UseVertexArray()
+	{
+		return true;
+	}
 protected:
 	class RAS_MeshObject	*m_pMesh;
 };
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.cpp b/source/gameengine/Rasterizer/RAS_FramingManager.cpp
index e2bbca48bb57ddd1c4c10b6ca6d8cc4075be9aaf..ea18ffb229896fd7ecbc8897d596473299d4df8d 100644
--- a/source/gameengine/Rasterizer/RAS_FramingManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.cpp
@@ -70,6 +70,39 @@ ComputeDefaultFrustum(
 	frustum.camfar = camfar;
 }
 
+	void
+RAS_FramingManager::
+ComputeDefaultOrtho(
+	const float camnear,
+	const float camfar,
+	const float scale,
+	const float design_aspect_ratio,
+	RAS_FrameFrustum & frustum
+)
+{
+	float halfSize = scale*0.5f;
+	float sizeX;
+	float sizeY;
+
+	if (design_aspect_ratio > 1.f) {
+		// halfsize defines the width
+		sizeX = halfSize;
+		sizeY = halfSize/design_aspect_ratio;
+	} else {
+		// halfsize defines the height
+		sizeX = halfSize * design_aspect_ratio;
+		sizeY = halfSize;
+	}
+		
+	frustum.x2 = sizeX;
+	frustum.x1 = -frustum.x2;
+	frustum.y2 = sizeY;
+	frustum.y1 = -frustum.y2;
+	frustum.camnear = -camfar;
+	frustum.camfar = camfar;
+}
+
+
 	void
 RAS_FramingManager::
 ComputeBestFitViewRect(
@@ -227,5 +260,73 @@ ComputeFrustum(
 	}
 }	
 
+	void
+RAS_FramingManager::
+	ComputeOrtho(
+		const RAS_FrameSettings &settings,
+		const RAS_Rect &availableViewport,
+		const RAS_Rect &viewport,
+		const float scale,
+		const float camnear,
+		const float camfar,
+		RAS_FrameFrustum &frustum
+	)
+{
+	RAS_FrameSettings::RAS_FrameType type = settings.FrameType();
+
+	const float design_width = float(settings.DesignAspectWidth());
+	const float design_height = float(settings.DesignAspectHeight());
+
+	float design_aspect_ratio = float(1);
+
+	if (design_height == float(0)) {
+		// well this is ill defined 
+		// lets just scale the thing
+		type = RAS_FrameSettings::e_frame_scale;
+	} else {
+		design_aspect_ratio = design_width/design_height;
+	}
+
+	
+	ComputeDefaultOrtho(
+		camnear,
+		camfar,
+		scale,
+		design_aspect_ratio,
+		frustum
+	);
+
+	switch (type) {
+
+		case RAS_FrameSettings::e_frame_extend:
+		{
+			RAS_Rect vt;
+			ComputeBestFitViewRect(
+				availableViewport,
+				design_aspect_ratio,	
+				vt
+			);
+
+			// now scale the calculated frustum by the difference
+			// between vt and the viewport in each axis.
+			// These are always > 1
+
+			float x_scale = float(viewport.GetWidth())/float(vt.GetWidth());
+			float y_scale = float(viewport.GetHeight())/float(vt.GetHeight());
+
+			frustum.x1 *= x_scale;
+			frustum.x2 *= x_scale;
+			frustum.y1 *= y_scale;
+			frustum.y2 *= y_scale;
+	
+			break;
+		}	
+		case RAS_FrameSettings::e_frame_scale :
+		case RAS_FrameSettings::e_frame_bars:
+		default :
+			break;
+	}
+	
+}
 
 
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h
index 610bd13ff122a19f80da379689987e736a3069de..4398e2d00c34973f5656c248a3c7c8d95466531e 100644
--- a/source/gameengine/Rasterizer/RAS_FramingManager.h
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.h
@@ -163,6 +163,13 @@ struct RAS_FrameFrustum
 	float x2,y2;
 };	
 
+/* must match R_CULLING_... from DNA_scene_types.h */
+enum RAS_CullingMode
+{
+	RAS_CULLING_DBVT = 0,
+	RAS_CULLING_NORMAL,
+	RAS_CULLING_NONE
+};
 
 /**
  * @section RAS_FramingManager
@@ -200,6 +207,18 @@ public :
 	 * and camera description
 	 */
 
+	static
+		void
+	ComputeOrtho(
+		const RAS_FrameSettings &settings,
+		const RAS_Rect &availableViewport,
+		const RAS_Rect &viewport,
+		const float scale,
+		const float camnear,
+		const float camfar,
+		RAS_FrameFrustum &frustum
+	);
+
 	static
 		void
 	ComputeFrustum(
@@ -222,6 +241,16 @@ public :
 		RAS_FrameFrustum & frustum
 	);	
 
+	static
+		void
+	ComputeDefaultOrtho(
+		const float camnear,
+		const float camfar,
+		const float scale,
+		const float design_aspect_ratio,
+		RAS_FrameFrustum & frustum
+	);
+
 private :
 
 	static
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
index cd88112007be5caa3ae14b89c303024cac0de63f..f2fd96d63e95685807008ab225b59814c06e3764 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
@@ -29,12 +29,71 @@
 #include "RAS_IPolygonMaterial.h"
 #include "RAS_IRasterizer.h"
 
+#include "DNA_image_types.h"
+#include "DNA_meshdata_types.h"
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+void  RAS_IPolyMaterial::Initialize( 
+				const STR_String& texname,
+				const STR_String& matname,
+				int materialindex,
+				int tile,
+				int tilexrep,
+				int tileyrep,
+				int mode,
+				int transp,
+				bool alpha,
+				bool zsort,
+				int lightlayer)
+{
+	m_texturename = texname;
+	m_materialname = matname;
+	m_materialindex = materialindex;
+	m_tile = tile;
+	m_tilexrep = tilexrep;
+	m_tileyrep = tileyrep;
+	m_drawingmode = mode;
+	m_transp = transp;
+	m_alpha = alpha;
+	m_zsort = zsort;
+	m_lightlayer = lightlayer;
+	m_polymatid = m_newpolymatid++;
+	m_flag = 0;
+	m_multimode = 0;
+	m_shininess = 35.0;
+	m_specular.setValue(0.5,0.5,0.5);
+	m_specularity = 1.0;
+	m_diffuse.setValue(0.5,0.5,0.5);
+}
+
+RAS_IPolyMaterial::RAS_IPolyMaterial() 
+		: m_texturename("__Dummy_Texture_Name__"),
+		m_materialname("__Dummy_Material_Name__"),
+		m_materialindex(0),
+		m_tile(0),
+		m_tilexrep(0),
+		m_tileyrep(0),
+		m_drawingmode (0),
+		m_transp(0),
+		m_alpha(false),
+		m_zsort(false),
+		m_lightlayer(0),
+		m_polymatid(0),
+		m_flag(0),
+		m_multimode(0)
+{
+	m_shininess = 35.0;
+	m_specular = MT_Vector3(0.5,0.5,0.5);
+	m_specularity = 1.0;
+	m_diffuse = MT_Vector3(0.5,0.5,0.5);
+}
+
 RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname,
 									 const STR_String& matname,
+									 int materialindex,
 									 int tile,
 									 int tilexrep,
 									 int tileyrep,
@@ -45,6 +104,7 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname,
 									 int lightlayer)
 		: m_texturename(texname),
 		m_materialname(matname),
+		m_materialindex(materialindex),
 		m_tile(tile),
 		m_tilexrep(tilexrep),
 		m_tileyrep(tileyrep),
@@ -95,6 +155,15 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const
 	}
 }
 
+
+void RAS_IPolyMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
+{
+	*rgba++ = 0xFF;
+	*rgba++ = 0xFF;
+	*rgba++ = 0xFF;
+	*rgba++ = 0xFF;
+}
+
 bool RAS_IPolyMaterial::Less(const RAS_IPolyMaterial& rhs) const
 {
 	if (Equals(rhs))
@@ -143,6 +212,25 @@ const STR_String& RAS_IPolyMaterial::GetTextureName() const
 	return m_texturename;
 }
 
+int RAS_IPolyMaterial::GetMaterialIndex() const
+{
+	return m_materialindex;
+}
+
+Material *RAS_IPolyMaterial::GetBlenderMaterial() const
+{
+	return NULL;
+}
+
+Scene* RAS_IPolyMaterial::GetBlenderScene() const
+{
+	return NULL;
+}
+
+void RAS_IPolyMaterial::ReleaseMaterial()
+{
+}
+
 unsigned int	RAS_IPolyMaterial::GetFlag() const
 {
 	return m_flag;
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
index e5b24070c4b10c89dae7348740681928b2d1f294..decd93c3d13e8835a0ca226c4f6d8952fe1cf885 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
@@ -39,6 +39,9 @@
 #include "STR_HashedString.h"
 
 class RAS_IRasterizer;
+struct MTFace;
+struct Material;
+struct Scene;
 
 enum MaterialProps
 {
@@ -71,6 +74,7 @@ protected:
 	bool					m_alpha;
 	bool					m_zsort;
 	int						m_lightlayer;
+	int						m_materialindex;
 	
 	unsigned int			m_polymatid;
 	static unsigned int		m_newpolymatid;
@@ -96,8 +100,10 @@ public:
 		SHADOW				  =8192
 	};
 
+	RAS_IPolyMaterial();
 	RAS_IPolyMaterial(const STR_String& texname,
 					  const STR_String& matname,
+					  int materialindex,
 					  int tile,
 					  int tilexrep,
 					  int tileyrep,
@@ -106,6 +112,17 @@ public:
 					  bool alpha,
 					  bool zsort,
 					  int lightlayer);
+	void Initialize(const STR_String& texname,
+					const STR_String& matname,
+					int materialindex,
+					int tile,
+					int tilexrep,
+					int tileyrep,
+					int mode,
+					int transp,
+					bool alpha,
+					bool zsort,
+					int lightlayer);
 	virtual ~RAS_IPolyMaterial() {};
  
 	/**
@@ -139,10 +156,14 @@ public:
 	dword				GetMaterialNameHash() const;
 	const STR_String&	GetTextureName() const;
 	unsigned int		GetFlag() const;
+	int					GetMaterialIndex() const;
 
+	virtual Material*   GetBlenderMaterial() const;
+	virtual Scene*		GetBlenderScene() const;
+	virtual void		ReleaseMaterial();
+	virtual void		GetMaterialRGBAColor(unsigned char *rgba) const;
 	virtual bool		UsesLighting(RAS_IRasterizer *rasty) const;
 	virtual bool		UsesObjectColor() const;
-	
 	/*
 	 * PreCalculate texture gen
 	 */
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
index cfeda06e670d32fbd4075fdbe610b0f616f0af2f..dc8c3c1ebf8186a4959ae6d3277157157c07ad6a 100644
--- a/source/gameengine/Rasterizer/RAS_IRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -250,9 +250,9 @@ public:
 	 * Sets the modelview matrix.
 	 */
 	virtual void	SetViewMatrix(const MT_Matrix4x4 & mat,
-						const MT_Vector3& campos,
-						const MT_Point3 &camLoc,
-						const MT_Quaternion &camOrientQuat)=0;
+								const MT_Matrix3x3 & ori,
+								const MT_Point3 & pos,
+								bool perspective)=0;
 	/**
 	 */
 	virtual const	MT_Point3& GetCameraPosition()=0;
@@ -280,6 +280,7 @@ public:
 	/**
 	 */
 	virtual void	DisableFog()=0;
+	virtual bool	IsFogEnabled()=0;
 
 	virtual void	SetBackColor(float red,
 								 float green,
@@ -325,6 +326,26 @@ public:
 		float focallength = 0.0f,
 		bool perspective = true
 	)=0;
+
+	/**
+	 * Generates a orthographic projection matrix from the specified frustum.
+	 * @param left the left clipping plane
+	 * @param right the right clipping plane
+	 * @param bottom the bottom clipping plane
+	 * @param top the top clipping plane
+	 * @param frustnear the near clipping plane
+	 * @param frustfar the far clipping plane
+	 * @return a 4x4 matrix representing the projection transform.
+	 */
+	virtual MT_Matrix4x4 GetOrthoMatrix(
+		float left,
+		float right,
+		float bottom,
+		float top,
+		float frustnear,
+		float frustfar
+	)=0;
+
 	/**
 	 * Sets the specular color component of the lighting equation.
 	 */
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
index 20a8e9c357419cfce0afcb9df12e50336a9ccc86..db6394c1ec01d68fc38201f065cf25ce1d869604 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
@@ -42,7 +42,7 @@
 
 /* mesh slot */
 
-RAS_MeshSlot::RAS_MeshSlot()
+RAS_MeshSlot::RAS_MeshSlot() : SG_QList()
 {
 	m_clientObj = NULL;
 	m_pDeformer = NULL;
@@ -56,16 +56,19 @@ RAS_MeshSlot::RAS_MeshSlot()
 	m_DisplayList = NULL;
 	m_bDisplayList = true;
 	m_joinSlot = NULL;
+	m_pDerivedMesh = NULL;
 }
 
 RAS_MeshSlot::~RAS_MeshSlot()
 {
-	vector<RAS_DisplayArray*>::iterator it;
+	RAS_DisplayArrayList::iterator it;
 
+#ifdef USE_SPLIT
 	Split(true);
 
 	while(m_joinedSlots.size())
 		m_joinedSlots.front()->Split(true);
+#endif
 
 	for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
 		(*it)->m_users--;
@@ -79,12 +82,13 @@ RAS_MeshSlot::~RAS_MeshSlot()
 	}
 }
 
-RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot)
+RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) : SG_QList()
 {
-	vector<RAS_DisplayArray*>::iterator it;
+	RAS_DisplayArrayList::iterator it;
 
 	m_clientObj = NULL;
 	m_pDeformer = NULL;
+	m_pDerivedMesh = NULL;
 	m_OpenGLMatrix = NULL;
 	m_mesh = slot.m_mesh;
 	m_bucket = slot.m_bucket;
@@ -203,7 +207,7 @@ RAS_DisplayArray *RAS_MeshSlot::CurrentDisplayArray()
 
 void RAS_MeshSlot::SetDisplayArray(int numverts)
 {
-	vector<RAS_DisplayArray*>::iterator it;
+	RAS_DisplayArrayList::iterator it;
 	RAS_DisplayArray *darray = NULL;
 	
 	for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
@@ -277,6 +281,43 @@ void RAS_MeshSlot::AddPolygonVertex(int offset)
 		m_endindex++;
 }
 
+void RAS_MeshSlot::SetDeformer(RAS_Deformer* deformer)
+{
+	if (deformer && m_pDeformer != deformer) {
+		// we create local copy of RAS_DisplayArray when we have a deformer:
+		// this way we can avoid conflict between the vertex cache of duplicates
+		RAS_DisplayArrayList::iterator it;
+		for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
+			if (deformer->UseVertexArray()) {
+				// the deformer makes use of vertex array, make sure we have our local copy
+				if ((*it)->m_users > 1) {
+					// only need to copy if there are other users
+					// note that this is the usual case as vertex arrays are held by the material base slot
+					RAS_DisplayArray *newarray = new RAS_DisplayArray(*(*it));
+					newarray->m_users = 1;
+					(*it)->m_users--;
+					*it = newarray;
+				}
+			} else {
+				// the deformer is not using vertex array (Modifier), release them
+				(*it)->m_users--;
+				if((*it)->m_users == 0)
+					delete *it;
+			}
+		}
+		if (!deformer->UseVertexArray()) {
+			m_displayArrays.clear();
+			m_startarray = 0;
+			m_startvertex = 0;
+			m_startindex = 0;
+			m_endarray = 0;
+			m_endvertex = 0;
+			m_endindex = 0;
+		}
+	}
+	m_pDeformer = deformer;
+}
+
 bool RAS_MeshSlot::Equals(RAS_MeshSlot *target)
 {
 	if(!m_OpenGLMatrix || !target->m_OpenGLMatrix)
@@ -295,7 +336,7 @@ bool RAS_MeshSlot::Equals(RAS_MeshSlot *target)
 
 bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance)
 {
-	vector<RAS_DisplayArray*>::iterator it;
+	RAS_DisplayArrayList::iterator it;
 	iterator mit;
 	size_t i;
 
@@ -330,6 +371,9 @@ bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance)
 	for(begin(mit); !end(mit); next(mit))
 		for(i=mit.startvertex; i<mit.endvertex; i++)
 			mit.vertex[i].Transform(transform, ntransform);
+	
+	/* We know we'll need a list at least this big, reserve in advance */
+	target->m_displayArrays.reserve(target->m_displayArrays.size() + m_displayArrays.size());
 
 	for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
 		target->m_displayArrays.push_back(*it);
@@ -357,7 +401,7 @@ bool RAS_MeshSlot::Split(bool force)
 {
 	list<RAS_MeshSlot*>::iterator jit;
 	RAS_MeshSlot *target = m_joinSlot;
-	vector<RAS_DisplayArray*>::iterator it, jt;
+	RAS_DisplayArrayList::iterator it, jt;
 	iterator mit;
 	size_t i, found0 = 0, found1 = 0;
 
@@ -417,21 +461,21 @@ bool RAS_MeshSlot::Split(bool force)
 	return false;
 }
 
+
+#ifdef USE_SPLIT	
 bool RAS_MeshSlot::IsCulled()
 {
-	list<RAS_MeshSlot*>::iterator it;
-
 	if(m_joinSlot)
 		return true;
 	if(!m_bCulled)
 		return false;
-	
+	list<RAS_MeshSlot*>::iterator it;
 	for(it=m_joinedSlots.begin(); it!=m_joinedSlots.end(); it++)
 		if(!(*it)->m_bCulled)
 			return false;
-	
 	return true;
 }
+#endif	
 
 /* material bucket sorting */
 
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
index 475f01d549a6234772766cade873ec31acbe73c0..8db75b8b735d8d552fd357c5e30f018eef0d8664 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
@@ -32,6 +32,7 @@
 #include "RAS_TexVert.h"
 #include "GEN_Map.h"
 #include "STR_HashedString.h"
+#include "SG_QList.h"
 
 #include "MT_Transform.h"
 #include "RAS_IPolygonMaterial.h"
@@ -69,6 +70,7 @@ class RAS_DisplayArray;
 class RAS_MeshSlot;
 class RAS_MeshMaterial;
 class RAS_MaterialBucket;
+struct DerivedMesh;
 
 /* An array with data used for OpenGL drawing */
 
@@ -86,9 +88,13 @@ public:
 };
 
 /* Entry of a RAS_MeshObject into RAS_MaterialBucket */
+typedef std::vector<RAS_DisplayArray*>	RAS_DisplayArrayList;
 
-class RAS_MeshSlot
+// The QList is used to link the mesh slots to the object
+// The DList is used to link the visible mesh slots to the material bucket
+class RAS_MeshSlot : public SG_QList
 {
+	friend class RAS_ListRasterizer;
 private:
 	//  indices into display arrays
 	int							m_startarray;
@@ -97,7 +103,7 @@ private:
 	int							m_endindex;
 	int							m_startvertex;
 	int							m_endvertex;
-	vector<RAS_DisplayArray*>	m_displayArrays;
+	RAS_DisplayArrayList		m_displayArrays;
 
 	// for construction only
 	RAS_DisplayArray*			m_currentArray;
@@ -108,6 +114,7 @@ public:
 	RAS_MeshObject*			m_mesh;
 	void*					m_clientObj;
 	RAS_Deformer*			m_pDeformer;
+	DerivedMesh*			m_pDerivedMesh;
 	double*					m_OpenGLMatrix;
 	// visibility
 	bool					m_bVisible;
@@ -146,6 +153,7 @@ public:
 	/* used during construction */
 	void SetDisplayArray(int numverts);
 	RAS_DisplayArray *CurrentDisplayArray();
+	void SetDeformer(RAS_Deformer* deformer);
 
 	void AddPolygon(int numverts);
 	int AddVertex(const RAS_TexVert& tv);
@@ -155,7 +163,12 @@ public:
 	bool Split(bool force=false);
 	bool Join(RAS_MeshSlot *target, MT_Scalar distance);
 	bool Equals(RAS_MeshSlot *target);
+#ifdef USE_SPLIT
 	bool IsCulled();
+#else
+	bool IsCulled() { return m_bCulled; }
+#endif
+	void SetCulled(bool culled) { m_bCulled = culled; }
 };
 
 /* Used by RAS_MeshObject, to point to it's slots in a bucket */
@@ -165,7 +178,6 @@ class RAS_MeshMaterial
 public:
 	RAS_MeshSlot *m_baseslot;
 	class RAS_MaterialBucket *m_bucket;
-
 	GEN_Map<GEN_HashedPtr,RAS_MeshSlot*> m_slots;
 };
 
@@ -202,10 +214,23 @@ public:
 	class RAS_MeshSlot* CopyMesh(class RAS_MeshSlot *ms);
 	void				RemoveMesh(class RAS_MeshSlot* ms);
 	void				Optimize(MT_Scalar distance);
+	void				ActivateMesh(RAS_MeshSlot* slot)
+	{
+		m_activeMeshSlotsHead.AddBack(slot);
+	}
+	SG_DList&			GetActiveMeshSlots()
+	{
+		return m_activeMeshSlotsHead;
+	}
+	RAS_MeshSlot*		GetNextActiveMeshSlot()
+	{
+		return (RAS_MeshSlot*)m_activeMeshSlotsHead.Remove();
+	}
 
 private:
-	list<RAS_MeshSlot>			m_meshSlots;
+	list<RAS_MeshSlot>			m_meshSlots;			// all the mesh slots
 	RAS_IPolyMaterial*			m_material;
+	SG_DList					m_activeMeshSlotsHead;	// only those which must be rendered
 	
 };
 
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
index a907994bf576a5dc15063a9f7e8532e259bf8e68..edd7615efd43fa854b24d5104caf1e9de378798c 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
@@ -179,14 +179,14 @@ list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetLastMaterial()
 
 
 
-void RAS_MeshObject::SetName(STR_String name)
+void RAS_MeshObject::SetName(const char *name)
 {
 	m_name = name;
 }
 
 
 
-const STR_String& RAS_MeshObject::GetName()
+STR_String& RAS_MeshObject::GetName()
 {
 	return m_name;
 }
@@ -215,6 +215,19 @@ RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat)
 	return NULL;
 }
 
+int RAS_MeshObject::GetMaterialId(RAS_IPolyMaterial *mat)
+{
+	list<RAS_MeshMaterial>::iterator mit;
+	int imat;
+
+	/* find a mesh material */
+	for(imat=0, mit = m_materials.begin(); mit != m_materials.end(); mit++, imat++)
+		if(mit->m_bucket->GetPolyMaterial() == mat)
+			return imat;
+
+	return -1;
+}
+
 RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts)
 {
 	RAS_MeshMaterial *mmat;
@@ -229,6 +242,7 @@ RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts
 		RAS_MeshMaterial meshmat;
 		meshmat.m_bucket = bucket;
 		meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts);
+		meshmat.m_baseslot->m_mesh = this;
 		m_materials.push_back(meshmat);
 		mmat = &m_materials.back();
 	}
@@ -291,7 +305,7 @@ void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i,
 	slot = mmat->m_baseslot;
 	darray = slot->CurrentDisplayArray();
 
-	if(!flat) {
+	{ /* Shared Vertex! */
 		/* find vertices shared between faces, with the restriction
 		 * that they exist in the same display array, and have the
 		 * same uv coordinate etc */
@@ -319,7 +333,7 @@ void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i,
 		slot->AddPolygonVertex(offset);
 	poly->SetVertexOffset(i, offset);
 
-	if(!flat) {
+	{ /* Shared Vertex! */
 		SharedVertex shared;
 		shared.m_darray = darray;
 		shared.m_offset = offset;
@@ -368,7 +382,7 @@ RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid,
 	return NULL;
 }
 
-void RAS_MeshObject::AddMeshUser(void *clientobj)
+void RAS_MeshObject::AddMeshUser(void *clientobj, SG_QList *head)
 {
 	list<RAS_MeshMaterial>::iterator it;
 
@@ -378,6 +392,7 @@ void RAS_MeshObject::AddMeshUser(void *clientobj)
 		RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot);
 		ms->m_clientObj = clientobj;
 		it->m_slots.insert(clientobj, ms);
+		head->QAddBack(ms);
 	}
 }
 
@@ -389,7 +404,7 @@ void RAS_MeshObject::UpdateBuckets(void* clientobj,
 							   bool culled)
 {
 	list<RAS_MeshMaterial>::iterator it;
-
+	
 	for(it = m_materials.begin();it!=m_materials.end();++it) {
 		RAS_MeshSlot **msp = it->m_slots[clientobj];
 
@@ -404,9 +419,13 @@ void RAS_MeshObject::UpdateBuckets(void* clientobj,
 		ms->m_RGBAcolor = rgbavec;
 		ms->m_bVisible = visible;
 		ms->m_bCulled = culled || !visible;
+		if (!ms->m_bCulled)
+			ms->m_bucket->ActivateMesh(ms);
 
 		/* split if necessary */
+#ifdef USE_SPLIT
 		ms->Split();
+#endif
 	}
 }
 
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h
index 404b7f16a5919c09cfcc10880997744868e2e4de..fbc3c549a7abb525a71e20390ce005d937f43c34 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.h
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.h
@@ -89,6 +89,7 @@ public:
 
 	RAS_MeshMaterial* 	GetMeshMaterial(unsigned int matid);
 	RAS_MeshMaterial*	GetMeshMaterial(RAS_IPolyMaterial *mat);
+	int					GetMaterialId(RAS_IPolyMaterial *mat);
 
 	list<RAS_MeshMaterial>::iterator GetFirstMaterial();
 	list<RAS_MeshMaterial>::iterator GetLastMaterial();
@@ -96,8 +97,8 @@ public:
 	unsigned int		GetLightLayer();
 
 	/* name */
-	void				SetName(STR_String name);
-	const STR_String&	GetName();
+	void				SetName(const char *name);
+	STR_String&			GetName();
 
 	/* modification state */
 	bool				MeshModified();
@@ -129,7 +130,7 @@ public:
 	RAS_Polygon*		GetPolygon(int num) const;
 	
 	/* buckets */
-	virtual void		AddMeshUser(void *clientobj);
+	virtual void		AddMeshUser(void *clientobj, SG_QList *head);
 	virtual void		UpdateBuckets(
 							void* clientobj,
 							double* oglmatrix,
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
index e4403ace69ff31c46b3e89b81adeb4d780e15c68..fe3d0f6aeea33fc899285983c5df6f68cf1f6f6d 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
@@ -31,8 +31,14 @@ SET(INC
   ../../../../intern/string
   ../../../../intern/moto/include
   ../../../../source/gameengine/Rasterizer
+  ../../../../source/gameengine/Ketsji
+  ../../../../source/gameengine/SceneGraph
   ../../../../extern/glew/include
   ../../../../source/blender/gpu
+  ../../../../source/blender/makesdna
+  ../../../../source/blender/blenkernel
+  ../../../../source/blender/blenlib
+  ../../../../source/blender/blenloader
 )
 
 BLENDERLIB(bf_oglrasterizer "${SRC}" "${INC}")
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
index aee485a22bebe1c5d503fca1db70be1975cda6f7..0327714dc5fdf8e7098e4060bf733bca637ba95b 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
@@ -42,8 +42,14 @@ CPPFLAGS += -I$(NAN_STRING)/include
 CPPFLAGS += -I$(NAN_MOTO)/include
 CPPFLAGS += -I../../../kernel/gen_system
 CPPFLAGS += -I../../../blender/gpu
+CPPFLAGS += -I../../../blender/makesdna
+CPPFLAGS += -I../../../blender/blenlib
+CPPFLAGS += -I../../../blender/blenkernel
 CPPFLAGS += -I../../BlenderRoutines
+CPPFLAGS += -I../../Ketsji
+CPPFLAGS += -I../../SceneGraph
 CPPFLAGS += -I..
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
 
 ifeq ($(OS),darwin)
 	CPPFLAGS += -fpascal-strings
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
index 2c4b55ff9647093cb1e75357dc4c49258b0d9cf2..f5324c6fbc93358b9f835f95bfffded679037f56 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
@@ -104,9 +104,11 @@ bool RAS_ListSlot::End()
 
 RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays, bool lock)
 :	RAS_VAOpenGLRasterizer(canvas, lock),
-	mUseVertexArrays(useVertexArrays)
+	mUseVertexArrays(useVertexArrays),
+	mATI(false)
 {
-	// --
+	if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc."))
+		mATI = true;
 }
 
 RAS_ListRasterizer::~RAS_ListRasterizer() 
@@ -116,10 +118,13 @@ RAS_ListRasterizer::~RAS_ListRasterizer()
 
 void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list)
 {
-	RAS_Lists::iterator it = mLists.begin();
-	while(it != mLists.end()) {
+	if (list->m_flag & LIST_STANDALONE)
+		return ;
+	
+	RAS_ArrayLists::iterator it = mArrayLists.begin();
+	while(it != mArrayLists.end()) {
 		if (it->second == list) {
-			mLists.erase(it);
+			mArrayLists.erase(it);
 			break;
 		}
 		it++;
@@ -136,12 +141,19 @@ RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms)
 	*/
 	RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList;
 	if(!localSlot) {
-		RAS_Lists::iterator it = mLists.find(&ms);
-		if(it == mLists.end()) {
+		if (ms.m_pDerivedMesh) {
+			// that means that we draw based on derived mesh, a display list is possible
+			// but it's unique to this mesh slot
 			localSlot = new RAS_ListSlot(this);
-			mLists.insert(std::pair<RAS_MeshSlot*, RAS_ListSlot*>(&ms, localSlot));
+			localSlot->m_flag |= LIST_STANDALONE;
 		} else {
-			localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef());
+			RAS_ArrayLists::iterator it = mArrayLists.find(ms.m_displayArrays);
+			if(it == mArrayLists.end()) {
+				localSlot = new RAS_ListSlot(this);
+				mArrayLists.insert(std::pair<RAS_DisplayArrayList, RAS_ListSlot*>(ms.m_displayArrays, localSlot));
+			} else {
+				localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef());
+			}
 		}
 	}
 	MT_assert(localSlot);
@@ -150,12 +162,12 @@ RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms)
 
 void RAS_ListRasterizer::ReleaseAlloc()
 {
-	RAS_Lists::iterator it = mLists.begin();
-	while(it != mLists.end()) {
+	RAS_ArrayLists::iterator it = mArrayLists.begin();
+	while(it != mArrayLists.end()) {
 		delete it->second;
 		it++;
 	}
-	mLists.clear();
+	mArrayLists.clear();
 }
 
 void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
@@ -172,8 +184,8 @@ void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
 			return;
 		}
 	}
-	
-	if (mUseVertexArrays)
+	// derived mesh cannot use vertex array
+	if (mUseVertexArrays && !ms.m_pDerivedMesh)
 		RAS_VAOpenGLRasterizer::IndexPrimitives(ms);
 	else
 		RAS_OpenGLRasterizer::IndexPrimitives(ms);
@@ -204,7 +216,7 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
 	// workaround: note how we do not use vertex arrays for making display
 	// lists, since glVertexAttribPointerARB doesn't seem to work correct
 	// in display lists on ATI? either a bug in the driver or in Blender ..
-	if (mUseVertexArrays && !localSlot)
+	if (mUseVertexArrays && !mATI && !ms.m_pDerivedMesh)
 		RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms);
 	else
 		RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms);
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
index 96d6d2a995d6819350b443afe92de46ad812f6dd..912f28af6aa4fc3718d17d7b71d92b9ad4a7998f 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
@@ -9,6 +9,7 @@
 class RAS_ListRasterizer;
 class RAS_ListSlot : public KX_ListSlot
 {
+	friend class RAS_ListRasterizer;
 	unsigned int m_list;
 	unsigned int m_flag;
 	RAS_ListRasterizer* m_rasty;
@@ -32,15 +33,17 @@ enum RAS_ListSlotFlags	{
 	LIST_NOCREATE	=8,
 	LIST_BEGIN		=16,
 	LIST_END		=32,
-	LIST_REGEN		=64
+	LIST_REGEN		=64,
+	LIST_STANDALONE =128,
 };
 
-typedef std::map<class RAS_MeshSlot*, RAS_ListSlot*> RAS_Lists;
+typedef std::map<RAS_DisplayArrayList, RAS_ListSlot*> RAS_ArrayLists;
 
 class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer
 {
 	bool mUseVertexArrays;
-	RAS_Lists mLists;
+	bool mATI;
+	RAS_ArrayLists mArrayLists;
 
 	RAS_ListSlot* FindOrAdd(class RAS_MeshSlot& ms);
 	void ReleaseAlloc();
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 1a9a28916de1c1794fe37029cd6813c81517eea2..3fe5e26abc367e0149fdefba0932eae655c2f3d7 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -35,11 +35,20 @@
 
 #include "RAS_Rect.h"
 #include "RAS_TexVert.h"
+#include "RAS_MeshObject.h"
 #include "MT_CmMatrix4x4.h"
 #include "RAS_IRenderTools.h" // rendering text
 
 #include "GPU_draw.h"
 #include "GPU_material.h"
+#include "GPU_extensions.h"
+
+#include "DNA_image_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_DerivedMesh.h"
 
 /**
  *  32x32 bit masks for vinterlace stereo mode
@@ -201,6 +210,10 @@ void RAS_OpenGLRasterizer::DisableFog()
 	m_fogenabled = false;
 }
 
+bool RAS_OpenGLRasterizer::IsFogEnabled()
+{
+	return m_fogenabled;
+}
 
 
 void RAS_OpenGLRasterizer::DisplayFog()
@@ -703,6 +716,51 @@ void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
 	IndexPrimitivesInternal(ms, true);
 }
 
+static bool current_wireframe;
+static RAS_MaterialBucket *current_bucket;
+static RAS_IPolyMaterial *current_polymat;
+static RAS_MeshSlot *current_ms;
+static RAS_MeshObject *current_mesh;
+static int current_blmat_nr;
+static GPUVertexAttribs current_gpu_attribs;
+static int CheckMaterialDM(int matnr, void *attribs)
+{
+	// only draw the current material
+	if (matnr != current_blmat_nr)
+		return 0;
+	GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
+	if (gattribs)
+		memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
+	return 1;
+}
+static int CheckTexfaceDM(void *mcol, int index)
+{
+
+	// index is the original face index, retrieve the polygon
+	RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
+		current_mesh->GetPolygon(index) : NULL;
+	if (polygon && polygon->GetMaterial() == current_bucket) {
+		// must handle color.
+		if (current_wireframe)
+			return 2;
+		if (current_ms->m_bObjectColor) {
+			MT_Vector4& rgba = current_ms->m_RGBAcolor;
+			glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+			// don't use mcol
+			return 2;
+		}
+		if (!mcol) {
+			// we have to set the color from the material
+			unsigned char rgba[4];
+			current_polymat->GetMaterialRGBAColor(rgba);
+			glColor4ubv((const GLubyte *)rgba);
+			return 2;
+		}
+		return 1;
+	}
+	return 0;
+}
+
 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
 { 
 	bool obcolor = ms.m_bObjectColor;
@@ -710,6 +768,31 @@ void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
 	MT_Vector4& rgba = ms.m_RGBAcolor;
 	RAS_MeshSlot::iterator it;
 
+	if (ms.m_pDerivedMesh) {
+		// mesh data is in derived mesh, 
+		current_bucket = ms.m_bucket;
+		current_polymat = current_bucket->GetPolyMaterial();
+		current_ms = &ms;
+		current_mesh = ms.m_mesh;
+		current_wireframe = wireframe;
+		MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL);
+		if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
+			// GetMaterialIndex return the original mface material index, 
+			// increment by 1 to match what derived mesh is doing
+			current_blmat_nr = current_polymat->GetMaterialIndex()+1;
+			// For GLSL we need to retrieve the GPU material attribute
+			Material* blmat = current_polymat->GetBlenderMaterial();
+			Scene* blscene = current_polymat->GetBlenderScene();
+			if (!wireframe && blscene && blmat)
+				GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), &current_gpu_attribs);
+			else
+				memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
+			ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
+		} else {
+			ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
+		}
+		return;
+	}
 	// iterate over display arrays, each containing an index + vertex array
 	for(ms.begin(it); !ms.end(it); ms.next(it)) {
 		RAS_TexVert *vertex;
@@ -838,17 +921,40 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
 	return result;
 }
 
+MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix(
+	float left,
+	float right,
+	float bottom,
+	float top,
+	float frustnear,
+	float frustfar
+){
+	MT_Matrix4x4 result;
+	double mat[16];
+
+	// stereo is meaning less for orthographic, disable it
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glOrtho(left, right, bottom, top, frustnear, frustfar);
+		
+	glGetDoublev(GL_PROJECTION_MATRIX, mat);
+	result.setValue(mat);
+
+	return result;
+}
+
 
 // next arguments probably contain redundant info, for later...
-void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vector3& campos,
-		const MT_Point3 &, const MT_Quaternion &camOrientQuat)
+void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, 
+										 const MT_Matrix3x3 & camOrientMat3x3,
+										 const MT_Point3 & pos,
+										 bool perspective)
 {
 	m_viewmatrix = mat;
 
 	// correction for stereo
-	if(Stereo())
+	if(Stereo() && perspective)
 	{
-		MT_Matrix3x3 camOrientMat3x3(camOrientQuat);
 		MT_Vector3 unitViewDir(0.0, -1.0, 0.0);  // minus y direction, Blender convention
 		MT_Vector3 unitViewupVec(0.0, 0.0, 1.0);
 		MT_Vector3 viewDir, viewupVec;
@@ -894,7 +1000,7 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto
 
 	glMatrixMode(GL_MODELVIEW);
 	glLoadMatrixd(glviewmat);
-	m_campos = campos;
+	m_campos = pos;
 }
 
 
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
index 83a9f759a8b3f2a6d1d0a1db9648c13870708379..4d51a477d48c630c47660aebacaee9b84c568d19 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
@@ -163,9 +163,9 @@ public:
 	virtual void	SetProjectionMatrix(const MT_Matrix4x4 & mat);
 	virtual void	SetViewMatrix(
 						const MT_Matrix4x4 & mat,
-						const MT_Vector3& campos,
-						const MT_Point3 &camLoc,
-						const MT_Quaternion &camOrientQuat
+						const MT_Matrix3x3 & ori,
+						const MT_Point3 & pos,
+						bool perspective
 					);
 
 	virtual const	MT_Point3& GetCameraPosition();
@@ -190,6 +190,7 @@ public:
 
 	void			DisableFog();
 	virtual void	DisplayFog();
+	virtual bool	IsFogEnabled();
 
 	virtual void	SetBackColor(
 						float red,
@@ -215,6 +216,15 @@ public:
 							bool perspective
 						);
 
+	virtual MT_Matrix4x4 GetOrthoMatrix(
+							float left,
+							float right,
+							float bottom,
+							float top,
+							float frustnear,
+							float frustfar
+						);
+
 	virtual void	SetSpecularity(
 						float specX,
 						float specY,
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
index 2cb3b52adfb7e5d61cb83a87fc01159e66ef3d65..00f0f27b6c1437888357ed65471deeea36c9fa52 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
@@ -110,6 +110,12 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
 	RAS_MeshSlot::iterator it;
 	GLenum drawmode;
 
+	if (ms.m_pDerivedMesh) {
+		// cannot be handled here, pass to RAS_OpenGLRasterizer
+		RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, false);
+		return;
+	}
+
 	if(!wireframe)
 		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
@@ -167,6 +173,12 @@ void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
 	RAS_MeshSlot::iterator it;
 	GLenum drawmode;
 
+	if (ms.m_pDerivedMesh) {
+		// cannot be handled here, pass to RAS_OpenGLRasterizer
+		RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true);
+		return;
+	}
+
 	if(!wireframe)
 		EnableTextures(true);
 
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
index 6731da9a776796c2046292a8c9f30ed027ddfe4a..d4b029ea34d37dc3fe84bb1c2f17bd8e2634bbe5 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
@@ -5,6 +5,8 @@ sources = env.Glob('*.cpp')
 
 incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines '
 incs += ' #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC']
+incs += ' #source/blender/gameengine/Ketsji #source/gameengine/SceneGraph #source/blender/makesdna #source/blender/blenkernel'
+incs += ' #intern/guardedalloc #source/blender/blenlib'
 
 cxxflags = []
 if env['OURPLATFORM']=='win32-vc':
diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp
index 66b14bb60b0c078ed584825384608d24f325aeac..eacc128516646788d2489d3c9e2f421e0d763c57 100644
--- a/source/gameengine/Rasterizer/RAS_Polygon.cpp
+++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp
@@ -97,6 +97,17 @@ void RAS_Polygon::SetCollider(bool visible)
 	else m_polyflags &= ~COLLIDER;
 }
 
+bool RAS_Polygon::IsTwoside()
+{
+	return (m_polyflags & TWOSIDE) != 0;
+}
+
+void RAS_Polygon::SetTwoside(bool twoside)
+{
+	if(twoside) m_polyflags |= TWOSIDE;
+	else m_polyflags &= ~TWOSIDE;
+}
+
 RAS_MaterialBucket* RAS_Polygon::GetMaterial()
 {
 	return m_bucket;
diff --git a/source/gameengine/Rasterizer/RAS_Polygon.h b/source/gameengine/Rasterizer/RAS_Polygon.h
index 224a7e0eed26877f69ffe8974655ec22ea939fa1..41eaa6bdd4a1a1da0487cbef0024eff9eb124b3b 100644
--- a/source/gameengine/Rasterizer/RAS_Polygon.h
+++ b/source/gameengine/Rasterizer/RAS_Polygon.h
@@ -56,7 +56,8 @@ class RAS_Polygon
 public:
 	enum {
 		VISIBLE = 1,
-		COLLIDER = 2
+		COLLIDER = 2,
+		TWOSIDE = 4
 	};
 
 	RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray* darray, int numvert);
@@ -79,6 +80,9 @@ public:
 	bool				IsCollider();
 	void				SetCollider(bool collider);
 
+	bool				IsTwoside();
+	void				SetTwoside(bool twoside);
+
 	RAS_MaterialBucket*	GetMaterial();
 	RAS_DisplayArray*	GetDisplayArray();
 };
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp
index 210addfb927de0dbedf9f8278accbea0e2a35da5..8eee24ac7f04bf2b487208da6d84d1d42ba06d77 100644
--- a/source/gameengine/Rasterizer/RAS_TexVert.cpp
+++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp
@@ -113,19 +113,20 @@ void RAS_TexVert::SetTangent(const MT_Vector3& tangent)
 	tangent.getValue(m_tangent);
 }
 
+
 // compare two vertices, and return TRUE if both are almost identical (they can be shared)
-#define _VEC_EQUAL3(_v1, _v2) (_v1[0]==_v2[0] && _v1[1]==_v2[1] && _v1[2]==_v2[2])
-#define _VEC_EQUAL2(_v1, _v2) (_v1[0]==_v2[0] && _v1[1]==_v2[1])
 bool RAS_TexVert::closeTo(const RAS_TexVert* other)
 {
-	return (m_flag == other->m_flag &&
+	return (
+		/* m_flag == other->m_flag && */
+		/* at the moment the face only stores the smooth/flat setting so dont bother comparing it */
 		m_rgba == other->m_rgba &&
-		_VEC_EQUAL3(m_normal, other->m_normal) &&
-		_VEC_EQUAL3(m_tangent, other->m_tangent) &&
-		_VEC_EQUAL2(m_uv1, other->m_uv1) &&
-		_VEC_EQUAL2(m_uv2, other->m_uv2) // p --
-		/* we know the verts must be shared so dont need to check this */
-		/*&& FAST_MT_fuzzyEqual3(m_localxyz, other->m_localxyz)*/) ;
+		MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) &&
+		MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) &&
+		MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) &&
+		MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) /* &&
+		MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))*/) ;
+	/* dont bother comparing m_localxyz since we know there from the same vert */
 }
 
 short RAS_TexVert::getFlag() const
diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript
index a16a04b85145f2d7e2a9bfc044d1d672c6ab9266..771d3399485091a5098713b71d5a0bf66bb467b8 100644
--- a/source/gameengine/Rasterizer/SConscript
+++ b/source/gameengine/Rasterizer/SConscript
@@ -4,7 +4,7 @@ Import ('env')
 sources = env.Glob('*.cpp')
 
 
-incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/blender/blenkernel #source/blender/makesdna'
+incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/gameengine/SceneGraph #source/blender/blenkernel #source/blender/makesdna'
 incs += ' ' + env['BF_PYTHON_INC']
 
 cxxflags = []
diff --git a/source/gameengine/SceneGraph/SG_BBox.cpp b/source/gameengine/SceneGraph/SG_BBox.cpp
index a44262d04f756efbda6ff5e348e4c9a26becb1e2..66fcc5c740897c61db8301613ce6de5af424f4fd 100644
--- a/source/gameengine/SceneGraph/SG_BBox.cpp
+++ b/source/gameengine/SceneGraph/SG_BBox.cpp
@@ -188,6 +188,13 @@ void SG_BBox::getaa(MT_Point3 *box, const MT_Transform &world) const
 	*box++ = max;
 }
 
+void SG_BBox::getmm(MT_Point3 *box, const MT_Transform &world) const
+{
+	const MT_Point3 min(world(m_min)), max(world(m_max));
+	*box++ = min;
+	*box++ = max;
+}
+
 void SG_BBox::split(SG_BBox &left, SG_BBox &right) const
 {
 	MT_Scalar sizex = m_max[0] - m_min[0];
diff --git a/source/gameengine/SceneGraph/SG_BBox.h b/source/gameengine/SceneGraph/SG_BBox.h
index b7e8ff6586521dab81583cba3e14812b2f2ae359..c39ad268e25bcd45fc9b37f5261ddc98553149fb 100644
--- a/source/gameengine/SceneGraph/SG_BBox.h
+++ b/source/gameengine/SceneGraph/SG_BBox.h
@@ -122,6 +122,8 @@ public:
 	 */
 	void getaa(MT_Point3 *box, const MT_Transform &world) const;
 	
+	void getmm(MT_Point3 *box, const MT_Transform &world) const;
+
 	void split(SG_BBox &left, SG_BBox &right) const;
 	
 	friend class SG_Tree;
diff --git a/source/gameengine/SceneGraph/SG_DList.h b/source/gameengine/SceneGraph/SG_DList.h
new file mode 100644
index 0000000000000000000000000000000000000000..7bef13cc9e3dc8564e5737919c797b81a105786a
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_DList.h
@@ -0,0 +1,161 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __SG_DLIST
+#define __SG_DLIST
+
+#include <stdlib.h>
+
+/**
+ * Double circular linked list
+ */
+class SG_DList
+{
+protected :
+	SG_DList* m_flink;
+	SG_DList* m_blink;
+
+public:
+	template<typename T> class iterator
+	{
+	private:
+		SG_DList&	m_head;
+		T*			m_current;
+	public:
+		typedef iterator<T> _myT;
+		iterator(SG_DList& head) : m_head(head), m_current(NULL) {}
+		~iterator() {}
+
+		void begin()
+		{
+			m_current = (T*)m_head.Peek();
+		}
+		void back()
+		{
+			m_current = (T*)m_head.Back();
+		}
+		bool end()
+		{
+			return (m_current == (T*)m_head.Self());
+		}
+		bool add_back(T* item)
+		{
+			return m_current->AddBack(item);
+		}
+		T* operator*()
+		{
+			return m_current;
+		}
+		_myT& operator++()
+		{
+			// no check of NULL! make sure you don't try to increment beyond end
+			m_current = (T*)m_current->Peek();
+			return *this;
+		}
+		_myT& operator--()
+		{
+			// no check of NULL! make sure you don't try to increment beyond end
+			m_current = (T*)m_current->Back();
+			return *this;
+		}
+	};
+
+    SG_DList() 
+    { 
+        m_flink = m_blink = this; 
+    }
+	SG_DList(const SG_DList& other)
+	{
+        m_flink = m_blink = this; 
+	}
+    virtual ~SG_DList() 
+    {
+		Delink();
+    }
+
+    inline bool Empty()               // Check for empty queue
+    {     
+        return ( m_flink == this ); 
+    }
+    bool AddBack( SG_DList *item )  // Add to the back
+    {
+		if (!item->Empty())
+			return false;
+        item->m_blink = m_blink;
+        item->m_flink = this;
+        m_blink->m_flink = item;
+        m_blink = item;
+		return true;
+    }
+    bool AddFront( SG_DList *item )  // Add to the back
+    {
+		if (!item->Empty())
+			return false;
+        item->m_flink = m_flink;
+        item->m_blink = this;
+        m_flink->m_blink = item;
+        m_flink = item;
+		return true;
+    }
+    SG_DList *Remove()           // Remove from the front
+    {
+        if (Empty()) 
+        {
+            return NULL;
+        }
+        SG_DList* item = m_flink;
+        m_flink = item->m_flink;
+        m_flink->m_blink = this;
+        item->m_flink = item->m_blink = item;
+        return item;
+    }
+    bool Delink()             // Remove from the middle
+    {
+		if (Empty())
+			return false;
+		m_blink->m_flink = m_flink;
+		m_flink->m_blink = m_blink;
+		m_flink = m_blink = this;
+		return true;
+    }
+    inline SG_DList *Peek()			// Look at front without removing
+    { 
+        return m_flink; 
+    }  
+    inline SG_DList *Back()			// Look at front without removing
+    { 
+        return m_blink; 
+    }  
+    inline SG_DList *Self() 
+    { 
+        return this; 
+    }
+};
+
+#endif //__SG_DLIST
+
diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp
index d0bdac5c8f0215b1a09e28c5ef0713bc8617cad3..5795ca57113ebec56da85733f1b5f071aefcc522 100644
--- a/source/gameengine/SceneGraph/SG_IObject.cpp
+++ b/source/gameengine/SceneGraph/SG_IObject.cpp
@@ -33,23 +33,26 @@
 #include <config.h>
 #endif
 
+SG_Stage gSG_Stage = SG_STAGE_UNKNOWN;
+
 SG_IObject::
 SG_IObject(
 	void* clientobj,
 	void* clientinfo,
-	SG_Callbacks callbacks
+	SG_Callbacks& callbacks
 ): 
+	SG_QList(),
 	m_SGclientObject(clientobj),
-	m_SGclientInfo(clientinfo),
-	m_callbacks(callbacks) 
+	m_SGclientInfo(clientinfo)
 {
-	//nothing to do
+	m_callbacks = callbacks;
 }
 
 SG_IObject::
 SG_IObject(
 	const SG_IObject &other
 ) :
+	SG_QList(),
 	m_SGclientObject(other.m_SGclientObject),
 	m_SGclientInfo(other.m_SGclientInfo),
 	m_callbacks(other.m_callbacks) 
@@ -72,92 +75,17 @@ RemoveAllControllers(
 	m_SGcontrollers.clear(); 
 }
 
-/// Needed for replication
-	SGControllerList&	
-SG_IObject::
-GetSGControllerList(
-){ 
-	return m_SGcontrollers; 
-}
-
-	void*				
-SG_IObject::
-GetSGClientObject(
-){ 
-	return m_SGclientObject;
-}
-
-const 
-	void*			
-SG_IObject::
-GetSGClientObject(
-) const	{
-	return m_SGclientObject;
-}
-
-	void	
-SG_IObject::
-SetSGClientObject(
-	void* clientObject
-){
-	m_SGclientObject = clientObject;
-}
-
-
-	bool
-SG_IObject::
-ActivateReplicationCallback(
-	SG_IObject *replica
-){
-	if (m_callbacks.m_replicafunc)
-	{
-		// Call client provided replication func
-		if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL)
-			return false;
-	}
-	return true;
-};	
-
-	void
-SG_IObject::
-ActivateDestructionCallback(
-){
-	if (m_callbacks.m_destructionfunc)
-	{
-		// Call client provided destruction function on this!
-		m_callbacks.m_destructionfunc(this,m_SGclientObject,m_SGclientInfo);
-	}
-	else
-	{
-		// no callback but must still destroy the node to avoid memory leak
-		delete this;
-	}
-}
-
-	void
-SG_IObject::
-ActivateUpdateTransformCallback(
-){
-	if (m_callbacks.m_updatefunc)
-	{
-		// Call client provided update func.
-		m_callbacks.m_updatefunc(this, m_SGclientObject, m_SGclientInfo);
-	}
-}
-
-	void 
-SG_IObject::
-SetControllerTime(
-	double time
-){
+void SG_IObject::SetControllerTime(double time)
+{
 	SGControllerList::iterator contit;
-
 	for (contit = m_SGcontrollers.begin();contit!=m_SGcontrollers.end();++contit)
 	{
 		(*contit)->SetSimulatedTime(time);
 	}
 }
 
+/// Needed for replication
+
 
 SG_IObject::
 ~SG_IObject()
diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h
index 7f6bdfbbb1cb29b22d12700b51990eeb1bfe4dac..b4dd9a9ddf2bd970f682b84f559ec3ee84da1966 100644
--- a/source/gameengine/SceneGraph/SG_IObject.h
+++ b/source/gameengine/SceneGraph/SG_IObject.h
@@ -29,8 +29,39 @@
 #ifndef __SG_IOBJECT
 #define __SG_IOBJECT
 
+#include "SG_QList.h"
 #include <vector>
 
+// used for debugging: stage of the game engine main loop at which a Scenegraph modification is done
+enum SG_Stage
+{
+	SG_STAGE_UNKNOWN = 0,
+	SG_STAGE_NETWORK,
+	SG_STAGE_NETWORK_UPDATE,
+	SG_STAGE_PHYSICS1,
+	SG_STAGE_PHYSICS1_UPDATE,
+	SG_STAGE_CONTROLLER,
+	SG_STAGE_CONTROLLER_UPDATE,
+	SG_STAGE_ACTUATOR,
+	SG_STAGE_ACTUATOR_UPDATE,
+	SG_STAGE_PHYSICS2,
+	SG_STAGE_PHYSICS2_UPDATE,
+	SG_STAGE_SCENE,
+	SG_STAGE_RENDER,
+	SG_STAGE_CONVERTER,
+	SG_STAGE_CULLING,
+	SG_STAGE_MAX
+};
+
+extern SG_Stage gSG_Stage;
+
+inline void SG_SetActiveStage(SG_Stage stage)
+{
+	gSG_Stage = stage;
+}
+	
+
+
 class SG_Controller;
 class SG_IObject;
 
@@ -54,6 +85,18 @@ typedef void  (*SG_UpdateTransformCallback)(
 	void*	clientinfo
 );
 
+typedef bool  (*SG_ScheduleUpdateCallback)(
+	SG_IObject* sgobject,
+	void*	clientobj,
+	void*	clientinfo
+);
+
+typedef bool  (*SG_RescheduleUpdateCallback)(
+	SG_IObject* sgobject,
+	void*	clientobj,
+	void*	clientinfo
+);
+
 
 /**
  * SG_Callbacks hold 2 call backs to the outside world.
@@ -76,30 +119,38 @@ struct	SG_Callbacks
 	):
 		m_replicafunc(NULL),
 		m_destructionfunc(NULL),
-		m_updatefunc(NULL)
+		m_updatefunc(NULL),
+		m_schedulefunc(NULL),
+		m_reschedulefunc(NULL)
 	{
 	};
 		
 	SG_Callbacks(
 		SG_ReplicationNewCallback repfunc,
 		SG_DestructionNewCallback destructfunc,
-		SG_UpdateTransformCallback updatefunc
+		SG_UpdateTransformCallback updatefunc,
+		SG_ScheduleUpdateCallback schedulefunc,
+		SG_RescheduleUpdateCallback reschedulefunc
 	): 
 		m_replicafunc(repfunc),
 		m_destructionfunc(destructfunc),
-		m_updatefunc(updatefunc)
+		m_updatefunc(updatefunc),
+		m_schedulefunc(schedulefunc),
+		m_reschedulefunc(reschedulefunc)
 	{
 	};
 
 	SG_ReplicationNewCallback	m_replicafunc;
 	SG_DestructionNewCallback	m_destructionfunc;
 	SG_UpdateTransformCallback	m_updatefunc;
+	SG_ScheduleUpdateCallback	m_schedulefunc;
+	SG_RescheduleUpdateCallback m_reschedulefunc;
 };
 
 /**
 base object that can be part of the scenegraph.
 */
-class SG_IObject
+class SG_IObject : public SG_QList
 {
 private :
 
@@ -147,9 +198,10 @@ public:
 	 * using STL? 
 	 */
 
-		SGControllerList&	
-	GetSGControllerList(
-	);
+	SGControllerList& GetSGControllerList()
+	{ 
+		return m_SGcontrollers; 
+	}
 
 	
 	/**
@@ -162,16 +214,16 @@ public:
 	 * This may be NULL.
 	 */
 
-		void*				
-	GetSGClientObject(
-	);
+	inline const void* GetSGClientObject() const	
+	{
+		return m_SGclientObject;
+	}
 
-	const 
-		void*			
-	GetSGClientObject(
-	) const	;
+	inline void* GetSGClientObject()
+	{ 
+		return m_SGclientObject;
+	}
 
-	
 	/**
 	 * Set the client object for this node. This is just a 
 	 * pointer to an object allocated that should exist for 
@@ -179,10 +231,10 @@ public:
 	 * this function is called again.
 	 */
 	
-		void	
-	SetSGClientObject(
-		void* clientObject
-	);
+	void SetSGClientObject(void* clientObject)
+	{
+		m_SGclientObject = clientObject;
+	}
 
 	/** 
 	 * Set the current simulation time for this node.
@@ -190,10 +242,7 @@ public:
 	 * the nodes list of controllers and calls their SetSimulatedTime methods
 	 */
  
-		void		
-	SetControllerTime(
-		double time
-	);
+	void SetControllerTime(double time);
 	
 	virtual 
 		void		
@@ -205,20 +254,76 @@ protected :
 		bool
 	ActivateReplicationCallback(
 		SG_IObject *replica
-	);
+	)
+	{
+		if (m_callbacks.m_replicafunc)
+		{
+			// Call client provided replication func
+			if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL)
+				return false;
+		}
+		return true;
+	}
+
 
 		void
 	ActivateDestructionCallback(
-	);
+	)
+	{
+		if (m_callbacks.m_destructionfunc)
+		{
+			// Call client provided destruction function on this!
+			m_callbacks.m_destructionfunc(this,m_SGclientObject,m_SGclientInfo);
+		}
+		else
+		{
+			// no callback but must still destroy the node to avoid memory leak
+			delete this;
+		}
+	}
 	
 		void
 	ActivateUpdateTransformCallback(
-	);
+	)
+	{
+		if (m_callbacks.m_updatefunc)
+		{
+			// Call client provided update func.
+			m_callbacks.m_updatefunc(this, m_SGclientObject, m_SGclientInfo);
+		}
+	}
+
+		bool
+	ActivateScheduleUpdateCallback(
+	)
+	{
+		// HACK, this check assumes that the scheduled nodes are put on a DList (see SG_Node.h)
+		// The early check on Empty() allows up to avoid calling the callback function
+		// when the node is already scheduled for update.
+		if (Empty() && m_callbacks.m_schedulefunc)
+		{
+			// Call client provided update func.
+			return m_callbacks.m_schedulefunc(this, m_SGclientObject, m_SGclientInfo);
+		}
+		return false;
+	}
+
+		void
+	ActivateRecheduleUpdateCallback(
+	)
+	{
+		if (m_callbacks.m_reschedulefunc)
+		{
+			// Call client provided update func.
+			m_callbacks.m_reschedulefunc(this, m_SGclientObject, m_SGclientInfo);
+		}
+	}
+
 
 	SG_IObject(
 		void* clientobj,
 		void* clientinfo,
-		SG_Callbacks callbacks
+		SG_Callbacks& callbacks
 	);
 
 	SG_IObject(
diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp
index 8de7ac834779605b5b7a13fa34d10ff9233a6aeb..4cd43e852b8bc8c2fe14d307c7c15803759682af 100644
--- a/source/gameengine/SceneGraph/SG_Node.cpp
+++ b/source/gameengine/SceneGraph/SG_Node.cpp
@@ -40,12 +40,13 @@ using namespace std;
 SG_Node::SG_Node(
 	void* clientobj,
 	void* clientinfo,
-	SG_Callbacks callbacks
+	SG_Callbacks& callbacks
 
 )
 	: SG_Spatial(clientobj,clientinfo,callbacks),
 	m_SGparent(NULL)
 {
+	m_modified = true;
 }
 
 SG_Node::SG_Node(
@@ -55,7 +56,7 @@ SG_Node::SG_Node(
 	m_children(other.m_children),
 	m_SGparent(other.m_SGparent)
 {
-	// nothing to do
+	m_modified = true;
 }
 
 SG_Node::~SG_Node()
@@ -141,22 +142,6 @@ Destruct()
 	ActivateDestructionCallback();
 }
 
-
-	SG_Node*			
-SG_Node::
-GetSGParent(
-) const { 
-	return m_SGparent;
-}
-
-	void				
-SG_Node::
-SetSGParent(
-	SG_Node* parent
-){
-	m_SGparent = parent;
-}
-
 const 
 	SG_Node*	
 SG_Node::
@@ -165,28 +150,6 @@ GetRootSGParent(
 	return (m_SGparent ? (const SG_Node*) m_SGparent->GetRootSGParent() : (const SG_Node*) this);
 }
 
-	bool
-SG_Node::
-IsVertexParent()
-{
-	if (m_parent_relation)
-	{
-		return m_parent_relation->IsVertexRelation();
-	}
-	return false;
-}
-
-	bool
-SG_Node::
-IsSlowParent()
-{
-	if (m_parent_relation)
-	{
-		return m_parent_relation->IsSlowRelation();
-	}
-	return false;
-}
-
 	void 
 SG_Node::
 DisconnectFromParent(
@@ -199,8 +162,6 @@ DisconnectFromParent(
 
 }
 
-
-
 void SG_Node::AddChild(SG_Node* child)
 {
 	m_children.push_back(child);
@@ -219,40 +180,26 @@ void SG_Node::RemoveChild(SG_Node* child)
 
 
 
-void SG_Node::UpdateWorldData(double time)
+void SG_Node::UpdateWorldData(double time, bool parentUpdated)
 {
 	//if (!GetSGParent())
 	//	return;
 
-	if (UpdateSpatialData(GetSGParent(),time))
+	if (UpdateSpatialData(GetSGParent(),time,parentUpdated))
+		// to update the 
 		ActivateUpdateTransformCallback();
 
+	// The node is updated, remove it from the update list
+	Delink();
+
 	// update children's worlddata
 	for (NodeList::iterator it = m_children.begin();it!=m_children.end();++it)
 	{
-		(*it)->UpdateWorldData(time);
+		(*it)->UpdateWorldData(time, parentUpdated);
 	}
 }
 
 
-NodeList& SG_Node::GetSGChildren()
-{
-	return this->m_children;
-}
-
-
-const NodeList& SG_Node::GetSGChildren() const
-{
-	return this->m_children;
-}
-
-
-void SG_Node::ClearSGChildren()
-{
-	m_children.clear();
-}
-
-
 
 void SG_Node::SetSimulatedTime(double time,bool recurse)
 {
diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h
index ffaaad861e2db097ceb0cde59e178631a2f19da5..7c6ef92f670647d3c9fb7d68099cb383f713da14 100644
--- a/source/gameengine/SceneGraph/SG_Node.h
+++ b/source/gameengine/SceneGraph/SG_Node.h
@@ -44,7 +44,7 @@ public:
 	SG_Node(
 		void* clientobj,
 		void* clientinfo,
-		SG_Callbacks callbacks
+		SG_Callbacks& callbacks
 	);
 
 	SG_Node(
@@ -85,45 +85,47 @@ public:
 	 * @return a reference to the list of children of this node.
 	 */
 	
-		NodeList&		
-	GetSGChildren(
-	);
+	NodeList& GetSGChildren()
+	{
+		return this->m_children;
+	}
 
 	/**
 	 * Get the current list of children.
 	 * @return a const reference to the current list of children of this node.
 	 */
 
-	const 
-		NodeList&	
-	GetSGChildren(
-	) const;
+	const NodeList& GetSGChildren() const
+	{
+		return this->m_children;
+	}
 
 	/** 
 	 * Clear the list of children associated with this node
 	 */
 
-		void				
-	ClearSGChildren(
-	);
+	void ClearSGChildren()
+	{
+		m_children.clear();
+	}
 
 	/**
 	 * return the parent of this node if it exists.
 	 */
 		
-		SG_Node*			
-	GetSGParent(
-	) const ;
-
+	SG_Node* GetSGParent() const 
+	{ 
+		return m_SGparent;
+	}
 
 	/**
 	 * Set the parent of this node. 
 	 */
 
-		void				
-	SetSGParent(
-		SG_Node* parent
-	);
+	void SetSGParent(SG_Node* parent)
+	{
+		m_SGparent = parent;
+	}
 
 	/**
 	 * Return the top node in this node's Scene graph hierarchy
@@ -142,31 +144,34 @@ public:
 	DisconnectFromParent(
 	);
 
-	/**
-	 * Tell this node to treat it's parent as a vertex parent.
-	 */
-
-		void	
-	SetVertexParent(
-		bool isvertexparent
-	) ;
-
-
 	/**
 	 * Return vertex parent status.
 	 */
+	bool IsVertexParent()
+	{
+		if (m_parent_relation)
+		{
+			return m_parent_relation->IsVertexRelation();
+		}
+		return false;
+	}
+
 
-		bool	
-	IsVertexParent(
-	) ;
-	
 	/**
 	 * Return slow parent status.
 	 */
 
-		bool	
-	IsSlowParent(
-	) ;
+	bool IsSlowParent()
+	{
+		if (m_parent_relation)
+		{
+			return m_parent_relation->IsSlowRelation();
+		}
+		return false;
+	}
+
+
+
 
 	/**		
 	 * Update the spatial data of this node. Iterate through
@@ -175,7 +180,8 @@ public:
 
 		void		
 	UpdateWorldData(
-		double time
+		double time,
+		bool parentUpdated=false
 	);
 
 	/**
@@ -189,6 +195,42 @@ public:
 		bool recurse
 	);
 
+	/**
+	 * Schedule this node for update by placing it in head queue
+	 */
+	bool Schedule(SG_QList& head)
+	{
+		// Put top parent in front of list to make sure they are updated before their
+		// children => the children will be udpated and removed from the list before
+		// we get to them, should they be in the list too.
+		return (m_SGparent)?head.AddBack(this):head.AddFront(this);
+	}
+
+	/**
+	 * Used during Scenegraph update
+	 */
+	static SG_Node* GetNextScheduled(SG_QList& head)
+	{
+		return static_cast<SG_Node*>(head.Remove());
+	}
+
+	/**
+	 * Make this node ready for schedule on next update. This is needed for nodes
+	 * that must always be updated (slow parent, bone parent)
+	 */
+	bool Reschedule(SG_QList& head)
+	{
+		return head.QAddBack(this);
+	}
+
+	/**
+	 * Used during Scenegraph update
+	 */
+	static SG_Node* GetNextRescheduled(SG_QList& head)
+	{
+		return static_cast<SG_Node*>(head.QRemove());
+	}
+
 	/**
 	 * Node replication functions.
 	 */
diff --git a/source/gameengine/SceneGraph/SG_ParentRelation.h b/source/gameengine/SceneGraph/SG_ParentRelation.h
index 6507cb98519d245210555a2794edb8065f08b189..8f45df09b27b72fb40520e8a110d228f89b8a236 100644
--- a/source/gameengine/SceneGraph/SG_ParentRelation.h
+++ b/source/gameengine/SceneGraph/SG_ParentRelation.h
@@ -69,7 +69,8 @@ public :
 		bool
 	UpdateChildCoordinates(
 		SG_Spatial * child,
-		const SG_Spatial * parent
+		const SG_Spatial * parent,
+		bool& parentUpdated
 	) = 0;
 
 	virtual 
diff --git a/source/gameengine/SceneGraph/SG_QList.h b/source/gameengine/SceneGraph/SG_QList.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a6b2e466c9812f7d7b906eebe36724b364afdda
--- /dev/null
+++ b/source/gameengine/SceneGraph/SG_QList.h
@@ -0,0 +1,157 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __SG_QLIST
+#define __SG_QLIST
+
+#include "SG_DList.h"
+
+/**
+ * Double-Double circular linked list
+ * For storing an object is two lists simultaneously
+ */
+class SG_QList : public SG_DList
+{
+protected :
+	SG_QList* m_fqlink;
+	SG_QList* m_bqlink;
+
+public:
+	template<typename T> class iterator
+	{
+	private:
+		SG_QList&	m_head;
+		T*			m_current;
+	public:
+		typedef iterator<T> _myT;
+		iterator(SG_QList& head) : m_head(head), m_current(NULL) {}
+		~iterator() {}
+
+		void begin()
+		{
+			m_current = (T*)m_head.QPeek();
+		}
+		void back()
+		{
+			m_current = (T*)m_head.QBack();
+		}
+		bool end()
+		{
+			return (m_current == (T*)m_head.Self());
+		}
+		bool add_back(T* item)
+		{
+			return m_current->QAddBack(item);
+		}
+		T* operator*()
+		{
+			return m_current;
+		}
+		_myT& operator++()
+		{
+			m_current = (T*)m_current->QPeek();
+			return *this;
+		}
+		_myT& operator--()
+		{
+			// no check on NULL! make sure you don't try to increment beyond end
+			m_current = (T*)m_current->QBack();
+			return *this;
+		}
+	};
+
+	SG_QList() : SG_DList()
+    { 
+        m_fqlink = m_bqlink = this; 
+    }
+	SG_QList(const SG_QList& other) : SG_DList()
+	{
+        m_fqlink = m_bqlink = this; 
+	}
+    virtual ~SG_QList() 
+    {
+		QDelink();
+    }
+
+    inline bool QEmpty()               // Check for empty queue
+    {     
+        return ( m_fqlink == this ); 
+    }
+    bool QAddBack( SG_QList *item )  // Add to the back
+    {
+		if (!item->QEmpty())
+			return false;
+        item->m_bqlink = m_bqlink;
+        item->m_fqlink = this;
+        m_bqlink->m_fqlink = item;
+        m_bqlink = item;
+		return true;
+    }
+    bool QAddFront( SG_QList *item )  // Add to the back
+    {
+		if (!item->Empty())
+			return false;
+        item->m_fqlink = m_fqlink;
+        item->m_bqlink = this;
+        m_fqlink->m_bqlink = item;
+        m_fqlink = item;
+		return true;
+    }
+    SG_QList *QRemove()           // Remove from the front
+    {
+        if (QEmpty()) 
+        {
+            return NULL;
+        }
+        SG_QList* item = m_fqlink;
+        m_fqlink = item->m_fqlink;
+        m_fqlink->m_bqlink = this;
+        item->m_fqlink = item->m_bqlink = item;
+        return item;
+    }
+    bool QDelink()             // Remove from the middle
+    {
+		if (QEmpty())
+			return false;
+		m_bqlink->m_fqlink = m_fqlink;
+		m_fqlink->m_bqlink = m_bqlink;
+		m_fqlink = m_bqlink = this;
+		return true;
+    }
+    inline SG_QList *QPeek()			// Look at front without removing
+    { 
+        return m_fqlink; 
+    }  
+    inline SG_QList *QBack()			// Look at front without removing
+    { 
+        return m_bqlink; 
+    }  
+};
+
+#endif //__SG_QLIST
+
diff --git a/source/gameengine/SceneGraph/SG_Spatial.cpp b/source/gameengine/SceneGraph/SG_Spatial.cpp
index 99aeb3e72eeb6ff7585d92926ee945f3a1b0f915..5a47f07f5737c3468014ab6edd499b64d454aa18 100644
--- a/source/gameengine/SceneGraph/SG_Spatial.cpp
+++ b/source/gameengine/SceneGraph/SG_Spatial.cpp
@@ -40,7 +40,7 @@ SG_Spatial::
 SG_Spatial(
 	void* clientobj,
 	void* clientinfo,
-	SG_Callbacks callbacks
+	SG_Callbacks& callbacks
 ): 
 
 	SG_IObject(clientobj,clientinfo,callbacks),
@@ -55,7 +55,9 @@ SG_Spatial(
 	m_parent_relation (NULL),
 	
 	m_bbox(MT_Point3(-1.0, -1.0, -1.0), MT_Point3(1.0, 1.0, 1.0)),
-	m_radius(1.0)
+	m_radius(1.0),
+	m_modified(false),
+	m_ogldirty(false)
 {
 }
 
@@ -75,7 +77,9 @@ SG_Spatial(
 	m_parent_relation(NULL),
 	
 	m_bbox(other.m_bbox),
-	m_radius(other.m_radius)
+	m_radius(other.m_radius),
+	m_modified(false),
+	m_ogldirty(false)
 {
 	// duplicate the parent relation for this object
 	m_parent_relation = other.m_parent_relation->NewCopy();
@@ -87,13 +91,6 @@ SG_Spatial::
 	delete (m_parent_relation);
 }
 
-	SG_ParentRelation *
-SG_Spatial::
-GetParentRelation(
-){
-	return m_parent_relation;
-}
-
 	void
 SG_Spatial::
 SetParentRelation(
@@ -101,6 +98,7 @@ SetParentRelation(
 ){
 	delete (m_parent_relation);
 	m_parent_relation = relation;
+	SetModified();
 }
 
 
@@ -114,7 +112,8 @@ SetParentRelation(
 SG_Spatial::
 UpdateSpatialData(
 	const SG_Spatial *parent,
-	double time
+	double time,
+	bool& parentUpdated
 ){
 
     bool bComputesWorldTransform = false;
@@ -135,16 +134,11 @@ UpdateSpatialData(
 	// our world coordinates.
 
 	if (!bComputesWorldTransform)
-		bComputesWorldTransform = ComputeWorldTransforms(parent);
+		bComputesWorldTransform = ComputeWorldTransforms(parent, parentUpdated);
 
 	return bComputesWorldTransform;
 }
 
-bool	SG_Spatial::ComputeWorldTransforms(const SG_Spatial *parent)
-{
-	return m_parent_relation->UpdateChildCoordinates(this,parent);
-}
-
 /**
  * Position and translation methods
  */
@@ -166,52 +160,14 @@ RelativeTranslate(
 			m_localPosition += trans;
 		}
 	}
+	SetModified();
 }	
 	
-	void 
-SG_Spatial::
-SetLocalPosition(
-	const MT_Point3& trans
-){
-	m_localPosition = trans;
-}
-
-	void				
-SG_Spatial::
-SetWorldPosition(
-	const MT_Point3& trans
-) {
-	m_worldPosition = trans;
-}
 
 /**
  * Scaling methods.
  */ 
 
-	void 
-SG_Spatial::
-RelativeScale(
-	const MT_Vector3& scale
-){
-	m_localScaling = m_localScaling * scale;
-}
-
-	void 
-SG_Spatial::
-SetLocalScale(
-	const MT_Vector3& scale
-){
-	m_localScaling = scale;
-}
-
-
-	void				
-SG_Spatial::
-SetWorldScale(
-	const MT_Vector3& scale
-){ 
-	m_worldScaling = scale;
-}
 
 /**
  * Orientation and rotation methods.
@@ -229,91 +185,11 @@ RelativeRotate(
 		rot 
 	:
 	(GetWorldOrientation().inverse() * rot * GetWorldOrientation()));
-}
-
-	void 
-SG_Spatial::
-SetLocalOrientation(const MT_Matrix3x3& rot)
-{
-	m_localRotation = rot;
+	SetModified();
 }
 
 
 
-	void				
-SG_Spatial::
-SetWorldOrientation(
-	const MT_Matrix3x3& rot
-) {
-	m_worldRotation = rot;
-}
-
-const 
-	MT_Point3&
-SG_Spatial::
-GetLocalPosition(
-) const	{
-	 return m_localPosition;
-}
-
-const 
-	MT_Matrix3x3&
-SG_Spatial::
-GetLocalOrientation(
-) const	{
-	return m_localRotation;
-}
-
-const 
-	MT_Vector3&	
-SG_Spatial::
-GetLocalScale(
-) const{
-	return m_localScaling;
-}
-
-
-const 
-	MT_Point3&
-SG_Spatial::
-GetWorldPosition(
-) const	{
-	return m_worldPosition;
-}
-
-const 
-	MT_Matrix3x3&	
-SG_Spatial::
-GetWorldOrientation(
-) const	{
-	return m_worldRotation;
-}
-
-const 
-	MT_Vector3&	
-SG_Spatial::
-GetWorldScaling(
-) const	{
-	return m_worldScaling;
-}
-
-void SG_Spatial::SetWorldFromLocalTransform()
-{
-	m_worldPosition= m_localPosition;
-	m_worldScaling= m_localScaling;
-	m_worldRotation= m_localRotation;
-}
-
-SG_BBox& SG_Spatial::BBox()
-{
-	return m_bbox;
-}
-
-void SG_Spatial::SetBBox(SG_BBox& bbox)
-{
-	m_bbox = bbox;
-}
-
 MT_Transform SG_Spatial::GetWorldTransform() const
 {
 	return MT_Transform(m_worldPosition, 
diff --git a/source/gameengine/SceneGraph/SG_Spatial.h b/source/gameengine/SceneGraph/SG_Spatial.h
index 6ccec2aa9c107a50004b951e3d608ded7b0cb5f8..d1fc95cceac61519476a34794649eb38694ffe1b 100644
--- a/source/gameengine/SceneGraph/SG_Spatial.h
+++ b/source/gameengine/SceneGraph/SG_Spatial.h
@@ -35,6 +35,7 @@
 #include <MT_Matrix3x3.h> // or Quaternion later ?
 #include "SG_IObject.h"
 #include "SG_BBox.h"
+#include "SG_ParentRelation.h"
 
 
 class SG_Node;
@@ -61,10 +62,25 @@ protected:
 	
 	SG_BBox			m_bbox;
 	MT_Scalar		m_radius;
-	
+	bool			m_modified;
+	bool			m_ogldirty;		// true if the openGL matrix for this object must be recomputed
 
 public:
 
+	inline void ClearModified() 
+	{ 
+		m_modified = false; 
+		m_ogldirty = true;
+	}
+	inline void SetModified()
+	{
+		m_modified = true;
+		ActivateScheduleUpdateCallback();
+	}
+	inline void ClearDirty()
+	{
+		m_ogldirty = false;
+	}
 	/** 
 	 * Define the realtionship this node has with it's parent
 	 * node. You should pass an unshared instance of an SG_ParentRelation
@@ -84,9 +100,12 @@ public:
 		SG_ParentRelation *relation
 	);
 	
-		SG_ParentRelation *
-	GetParentRelation(
-	);
+	SG_ParentRelation * GetParentRelation()
+	{
+		return m_parent_relation;
+	}
+
+
 
 
 	/**
@@ -105,15 +124,17 @@ public:
 		bool local
 	);
 
-		void				
-	SetLocalPosition(
-		const MT_Point3& trans
-	);
+	void SetLocalPosition(const MT_Point3& trans)
+	{
+		m_localPosition = trans;
+		SetModified();
+	}
+
+	void SetWorldPosition(const MT_Point3& trans)
+	{
+		m_worldPosition = trans;
+	}
 
-		void				
-	SetWorldPosition(
-		const MT_Point3& trans
-	);
 	
 		void				
 	RelativeRotate(
@@ -121,81 +142,110 @@ public:
 		bool local
 	);
 
-		void				
-	SetLocalOrientation(
-		const MT_Matrix3x3& rot
-	);
-
-		void				
-	SetWorldOrientation(
-		const MT_Matrix3x3& rot
-	);
-
-		void				
-	RelativeScale(
-		const MT_Vector3& scale
-	);
-
-		void				
-	SetLocalScale(
-		const MT_Vector3& scale
-	);
-
-		void				
-	SetWorldScale(
-		const MT_Vector3& scale
-	);
-
-	const 
-		MT_Point3&
-	GetLocalPosition(
-	) const	;
+	void SetLocalOrientation(const MT_Matrix3x3& rot)
+	{
+		m_localRotation = rot;
+		SetModified();
+	}
+
+	void SetWorldOrientation(const MT_Matrix3x3& rot) 
+	{
+		m_worldRotation = rot;
+	}
+
+	void RelativeScale(const MT_Vector3& scale)
+	{
+		m_localScaling = m_localScaling * scale;
+		SetModified();
+	}
+
+	void SetLocalScale(const MT_Vector3& scale)
+	{
+		m_localScaling = scale;
+		SetModified();
+	}
+
+	void SetWorldScale(const MT_Vector3& scale)
+	{ 
+		m_worldScaling = scale;
+	}
+
+	const MT_Point3& GetLocalPosition() const	
+	{
+		return m_localPosition;
+	}
+
+	const MT_Matrix3x3& GetLocalOrientation() const	
+	{
+		return m_localRotation;
+	}
+
+	const MT_Vector3& GetLocalScale() const
+	{
+		return m_localScaling;
+	}
+
+	const MT_Point3& GetWorldPosition() const	
+	{
+		return m_worldPosition;
+	}
+
+	const MT_Matrix3x3&	GetWorldOrientation() const	
+	{
+		return m_worldRotation;
+	}
+
+	const MT_Vector3& GetWorldScaling() const	
+	{
+		return m_worldScaling;
+	}
+
+	void SetWorldFromLocalTransform()
+	{
+		m_worldPosition= m_localPosition;
+		m_worldScaling= m_localScaling;
+		m_worldRotation= m_localRotation;
+	}
 
-	const 
-		MT_Matrix3x3&
-	GetLocalOrientation(
-	) const	;
 
-	const 
-		MT_Vector3&	
-	GetLocalScale(
-	) const;
-
-	const 
-		MT_Point3&
-	GetWorldPosition(
-	) const	;
-
-	const 
-		MT_Matrix3x3&	
-	GetWorldOrientation(
-	) const	;
-
-	const 
-		MT_Vector3&	
-	GetWorldScaling(
-	) const	;
-
-	void SetWorldFromLocalTransform();
 
 	MT_Transform GetWorldTransform() const;
 
-	bool	ComputeWorldTransforms(		const SG_Spatial *parent);
+	bool	ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated)
+	{
+		return m_parent_relation->UpdateChildCoordinates(this,parent,parentUpdated);
+	}
+
 
 	/**
 	 * Bounding box functions.
 	 */
-	SG_BBox& BBox();
-	void SetBBox(SG_BBox & bbox);
+	SG_BBox& BBox()
+	{
+		return m_bbox;
+	}
+
+	void SetBBox(SG_BBox& bbox)
+	{
+		m_bbox = bbox;
+	}
+
+
 	bool inside(const MT_Point3 &point) const;
 	void getBBox(MT_Point3 *box) const;
 	void getAABBox(MT_Point3 *box) const;
 	
 	MT_Scalar Radius() const { return m_radius; }
 	void SetRadius(MT_Scalar radius) { m_radius = radius; }
+	bool IsModified() { return m_modified; }
+	bool IsDirty() { return m_ogldirty; }
 	
 protected:
 	friend class SG_Controller;
+	friend class KX_BoneParentRelation;
+	friend class KX_VertexParentRelation;
+	friend class KX_SlowParentRelation;
+	friend class KX_NormalParentRelation;
 	
 	/** 
 	 * Protected constructor this class is not
@@ -205,7 +255,7 @@ protected:
 	SG_Spatial(
 		void* clientobj,
 		void* clientinfo,
-		SG_Callbacks callbacks
+		SG_Callbacks& callbacks
 	);
 
 	SG_Spatial(
@@ -223,7 +273,8 @@ protected:
 		bool 
 	UpdateSpatialData(
 		const SG_Spatial *parent,
-		double time
+		double time,
+		bool& parentUpdated
 	);
 
 };
diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h
index ac3ed8812a6d1e8b62ca61a8e5f0d6b759294367..8b243c439129d96d4ae5a6e6c58ea9dd5d2f4352 100644
--- a/source/gameengine/VideoTexture/BlendType.h
+++ b/source/gameengine/VideoTexture/BlendType.h
@@ -25,6 +25,7 @@ http://www.gnu.org/copyleft/lesser.txt.
 
 
 /// class allows check type of blender python object and access its contained object
+/// MUST ONLY BE USED FOR KX classes that are descendent of PyObjectPlus
 template <class PyObj> class BlendType
 {
 public:
@@ -48,8 +49,9 @@ public:
 		// if pointer to type is set and don't match to type of provided object, return NULL
 		else if (obj->ob_type != m_objType) 
 			return NULL;
-		// return pointer to object
-		return (PyObj*)obj;
+		// return pointer to object, this class can only be used for KX object =>
+		// the Py object is actually a proxy
+		return (PyObj*)BGE_PROXY_REF(obj);
 	}
 
 	/// parse arguments to get object
diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
index 43d7566102a550792825a5f6e330f0e247c4631b..6b23105a2782a828e15d21cd47b3d6dac552b9c5 100644
--- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp
+++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
@@ -135,8 +135,13 @@ static PyGetSetDef filterBSGetSets[] =
 // define python type
 PyTypeObject FilterBlueScreenType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.FilterBlueScreen",   /*tp_name*/
 	sizeof(PyFilter),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp
index 22ee729b200f7bb3fc8767146cea3ff1e5f476e3..5ff1f7f11cec276f9c59c561474e250db9fc5bcd 100644
--- a/source/gameengine/VideoTexture/FilterColor.cpp
+++ b/source/gameengine/VideoTexture/FilterColor.cpp
@@ -41,8 +41,13 @@ static PyGetSetDef filterGrayGetSets[] =
 // define python type
 PyTypeObject FilterGrayType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.FilterGray",   /*tp_name*/
 	sizeof(PyFilter),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
@@ -173,8 +178,13 @@ static PyGetSetDef filterColorGetSets[] =
 // define python type
 PyTypeObject FilterColorType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.FilterColor",   /*tp_name*/
 	sizeof(PyFilter),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
@@ -307,8 +317,13 @@ static PyGetSetDef filterLevelGetSets[] =
 // define python type
 PyTypeObject FilterLevelType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.FilterLevel",   /*tp_name*/
 	sizeof(PyFilter),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp
index 03a79c1c8ce95eaf7d3f2d866ae72632af06ea8d..9a2b1e90d5a4c9836964ddcb7baa70583c42fb3a 100644
--- a/source/gameengine/VideoTexture/FilterNormal.cpp
+++ b/source/gameengine/VideoTexture/FilterNormal.cpp
@@ -74,7 +74,7 @@ static int setColor (PyFilter * self, PyObject * value, void * closure)
 	// check validity of parameter
 	if (value == NULL || !PyInt_Check(value))
 	{
-		PyErr_SetString(PyExc_TypeError, "The value must be a int");
+		PyErr_SetString(PyExc_TypeError, "filt.colorIdx = int: VideoTexture.FilterNormal, expected the value must be a int");
 		return -1;
 	}
 	// set color index
@@ -94,15 +94,20 @@ static PyObject * getDepth (PyFilter * self, void * closure)
 static int setDepth (PyFilter * self, PyObject * value, void * closure)
 {
 	// check validity of parameter
-	if (value == NULL || !PyFloat_Check(value))
+	if (value)
 	{
-		PyErr_SetString(PyExc_TypeError, "The value must be a float");
-		return -1;
+		float depth= (float)PyFloat_AsDouble(value);
+		if ((depth==-1 && PyErr_Occurred()) == 0) /* no error converting to a float? */
+		{
+			// set depth
+			getFilter(self)->setDepth(depth);
+			// success
+			return 0;
+		}
 	}
-	// set depth
-	getFilter(self)->setDepth(float(PyFloat_AsDouble(value)));
-	// success
-	return 0;
+
+	PyErr_SetString(PyExc_TypeError, "filt.depth = float: VideoTexture.FilterNormal, expected the value must be a float");
+	return -1;
 }
 
 
@@ -119,8 +124,13 @@ static PyGetSetDef filterNormalGetSets[] =
 // define python type
 PyTypeObject FilterNormalType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.FilterNormal",   /*tp_name*/
 	sizeof(PyFilter),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp
index f3676e93a6d6665ec6aa849c176e7cd6a5d4bfbd..4c75e14bbac1fc7b21a640cd0a3f7a74744f7928 100644
--- a/source/gameengine/VideoTexture/FilterSource.cpp
+++ b/source/gameengine/VideoTexture/FilterSource.cpp
@@ -36,8 +36,13 @@ http://www.gnu.org/copyleft/lesser.txt.
 // define python type
 PyTypeObject FilterRGB24Type =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.FilterRGB24",   /*tp_name*/
 	sizeof(PyFilter),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
@@ -82,8 +87,13 @@ PyTypeObject FilterRGB24Type =
 // define python type
 PyTypeObject FilterRGBA32Type =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.FilterRGBA32",   /*tp_name*/
 	sizeof(PyFilter),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
@@ -128,8 +138,13 @@ PyTypeObject FilterRGBA32Type =
 // define python type
 PyTypeObject FilterBGR24Type =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.FilterBGR24",   /*tp_name*/
 	sizeof(PyFilter),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h
index 6385ed5108f7414658969d0457ebe9b6363b94df..254e0a026792c0fb0335625803bbb97c2e46e29f 100644
--- a/source/gameengine/VideoTexture/FilterSource.h
+++ b/source/gameengine/VideoTexture/FilterSource.h
@@ -225,7 +225,7 @@ protected:
 				// otherwise if only vertical interpolation is needed
 			}
 		}
-		else if ((y & 1) == 1)
+		else if ((y & 1) == 1) {
 			// if this pixel is on the edge
 			if (isEdge(x, y, size))
 			{
@@ -239,6 +239,7 @@ protected:
 				d = interpolV(m_buffU + offset) - 128;
 				e = interpolV(m_buffV + offset) - 128;
 			}
+		}
 		// convert to RGB
 		// R = clip(( 298 * C           + 409 * E + 128) >> 8)
 		// G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp
index 19ad17ac64326cd09dad2eb6e2707d0752266160..c8e62aff240847f766a8d154f8af5329c6141b28 100644
--- a/source/gameengine/VideoTexture/ImageBuff.cpp
+++ b/source/gameengine/VideoTexture/ImageBuff.cpp
@@ -123,8 +123,13 @@ static PyGetSetDef imageBuffGetSets[] =
 // define python type
 PyTypeObject ImageBuffType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.ImageBuff",   /*tp_name*/
 	sizeof(PyImage),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp
index b07b362818cf968511a9062c280bdb4af18331af..2418ba254e42ebc341d7d4857ee36cff8d36f8a6 100644
--- a/source/gameengine/VideoTexture/ImageMix.cpp
+++ b/source/gameengine/VideoTexture/ImageMix.cpp
@@ -162,8 +162,13 @@ static PyGetSetDef imageMixGetSets[] =
 // define python type
 PyTypeObject ImageMixType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.ImageMix",   /*tp_name*/
 	sizeof(PyImage),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index 58697ed3cc7e7102c5b01c78802cf3c2461f79c4..db4461325d83c5d9bcd7520707d834d0e6e0e3ca 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -181,7 +181,6 @@ void ImageRender::Render()
         frustrum.camnear = -mirrorOffset[2];
         frustrum.camfar = -mirrorOffset[2]+m_clip;
     }
-    const float ortho = 100.0;
     const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode();
 
     // The screen area that ImageViewport will copy is also the rendering zone
@@ -214,44 +213,48 @@ void ImageRender::Render()
 		float farfrust = m_camera->GetCameraFar();
         float aspect_ratio = 1.0f;
         Scene *blenderScene = m_scene->GetBlenderScene();
+		MT_Matrix4x4 projmat;
 
-        if (orthographic) {
-			lens *= ortho;
-			nearfrust = (nearfrust + 1.0)*ortho;
-			farfrust *= ortho;
-		}
 		// compute the aspect ratio from frame blender scene settings so that render to texture
         // works the same in Blender and in Blender player
         if (blenderScene->r.ysch != 0)
-            aspect_ratio = float(blenderScene->r.xsch) / float(blenderScene->r.ysch);
-
-        RAS_FramingManager::ComputeDefaultFrustum(
-            nearfrust,
-            farfrust,
-            lens,
-            aspect_ratio,
-            frustrum);
-		
-		MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(
-			frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar);
-
+            aspect_ratio = float(blenderScene->r.xsch*blenderScene->r.xasp) / float(blenderScene->r.ysch*blenderScene->r.yasp);
+
+		if (orthographic) {
+
+			RAS_FramingManager::ComputeDefaultOrtho(
+				nearfrust,
+				farfrust,
+				m_camera->GetScale(),
+				aspect_ratio,
+				frustrum
+			);
+
+			projmat = m_rasterizer->GetOrthoMatrix(
+				frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar);
+		} else 
+		{
+			RAS_FramingManager::ComputeDefaultFrustum(
+				nearfrust,
+				farfrust,
+				lens,
+				aspect_ratio,
+				frustrum);
+			
+			projmat = m_rasterizer->GetFrustumMatrix(
+				frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar);
+		}
 		m_camera->SetProjectionMatrix(projmat);
 	}
 
 	MT_Transform camtrans(m_camera->GetWorldToCamera());
-	if (!m_camera->GetCameraData()->m_perspective)
-		camtrans.getOrigin()[2] *= ortho;
 	MT_Matrix4x4 viewmat(camtrans);
 	
-	m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldPosition(),
-		m_camera->GetCameraLocation(), m_camera->GetCameraOrientation());
+	m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldOrientation(), m_camera->NodeGetWorldPosition(), m_camera->GetCameraData()->m_perspective);
 	m_camera->SetModelviewMatrix(viewmat);
     // restore the stereo mode now that the matrix is computed
     m_rasterizer->SetStereoMode(stereomode);
 
-    // do not update the mesh, we don't want to do it more than once per frame
-    //m_scene->UpdateMeshTransformations();
-
 	m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera);
 
 	m_scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
@@ -373,8 +376,13 @@ static PyGetSetDef imageRenderGetSets[] =
 // define python type
 PyTypeObject ImageRenderType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.ImageRender",   /*tp_name*/
 	sizeof(PyImage),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
@@ -434,26 +442,35 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds
 	{
 		// get scene pointer
 		KX_Scene * scenePtr (NULL);
-        if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type)) 
-            scenePtr = static_cast<KX_Scene*>(scene);
-        else
+        if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type))
+            scenePtr = static_cast<KX_Scene*>BGE_PROXY_REF(scene);
+		else
             THRWEXCP(SceneInvalid, S_OK);
-
+		
+		if(scenePtr==NULL) /* incase the python proxy reference is invalid */
+			THRWEXCP(SceneInvalid, S_OK);
+		
 		// get observer pointer
 		KX_GameObject * observerPtr (NULL);
 		if (observer != NULL && PyObject_TypeCheck(observer, &KX_GameObject::Type))
-            observerPtr = static_cast<KX_GameObject*>(observer);
+            observerPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(observer);
         else if (observer != NULL && PyObject_TypeCheck(observer, &KX_Camera::Type))
-            observerPtr = static_cast<KX_Camera*>(observer);
+            observerPtr = static_cast<KX_Camera*>BGE_PROXY_REF(observer);
 		else
             THRWEXCP(ObserverInvalid, S_OK);
+		
+		if(observerPtr==NULL) /* incase the python proxy reference is invalid */
+			THRWEXCP(ObserverInvalid, S_OK);
 
 		// get mirror pointer
 		KX_GameObject * mirrorPtr (NULL);
 		if (mirror != NULL && PyObject_TypeCheck(mirror, &KX_GameObject::Type))
-            mirrorPtr = static_cast<KX_GameObject*>(mirror);
+            mirrorPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(mirror);
 		else
             THRWEXCP(MirrorInvalid, S_OK);
+		
+		if(mirrorPtr==NULL) /* incase the python proxy reference is invalid */
+			THRWEXCP(MirrorInvalid, S_OK);
 
         // locate the material in the mirror
 		RAS_IPolyMaterial * material = getMaterial(mirror, materialID);
@@ -698,8 +715,13 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj
 // define python type
 PyTypeObject ImageMirrorType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.ImageMirror",   /*tp_name*/
 	sizeof(PyImage),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp
index 4c2c81e2208b599407dc5907dfff6fdb4fd1f1fd..b808b06eb2b73dac4d30b87f0f769caf8031f8d1 100644
--- a/source/gameengine/VideoTexture/ImageViewport.cpp
+++ b/source/gameengine/VideoTexture/ImageViewport.cpp
@@ -289,8 +289,13 @@ static PyGetSetDef imageViewportGetSets[] =
 // define python type
 PyTypeObject ImageViewportType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.ImageViewport",   /*tp_name*/
 	sizeof(PyImage),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp
index 66c67023e38b5ec64ea5771567cc0a953d44265f..a8ece4bc17ecdfdf5252382c29db8da53a895799 100644
--- a/source/gameengine/VideoTexture/Texture.cpp
+++ b/source/gameengine/VideoTexture/Texture.cpp
@@ -163,11 +163,12 @@ void Texture_dealloc (Texture * self)
 	// release renderer
 	Py_XDECREF(self->m_source);
 	// close texture
-	Texture_close(self);
+	PyObject* ret = Texture_close(self);
+	Py_DECREF(ret);
 	// release scaled image buffer
 	delete [] self->m_scaledImg;
 	// release object
-	self->ob_type->tp_free((PyObject*)self);
+	((PyObject *)self)->ob_type->tp_free((PyObject*)self);
 }
 
 
@@ -434,8 +435,13 @@ static PyGetSetDef textureGetSets[] =
 // class Texture declaration
 PyTypeObject TextureType =
 {
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.Texture",   /*tp_name*/
 	sizeof(Texture),           /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp
index 10117c3af9e08d5b304f54384354b62890c7bd89..3c703d75cdaba6c7f92f6cbebb7a71d356746c17 100644
--- a/source/gameengine/VideoTexture/VideoBase.cpp
+++ b/source/gameengine/VideoTexture/VideoBase.cpp
@@ -22,7 +22,7 @@ http://www.gnu.org/copyleft/lesser.txt.
 
 #if defined WIN32
 #define WINDOWS_LEAN_AND_MEAN
-#include <Windows.h>
+#include <windows.h>
 #endif
 
 #include "VideoBase.h"
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index 5265b0ecb93efa11cc7849d9e27d43e7b6e08ba8..08c02628f05694889f1299ad19b5e788a190666d 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -1123,8 +1123,13 @@ static PyGetSetDef videoGetSets[] =
 // python type declaration
 PyTypeObject VideoFFmpegType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.VideoFFmpeg",   /*tp_name*/
 	sizeof(PyImage),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
@@ -1241,8 +1246,13 @@ static PyGetSetDef imageGetSets[] =
 // python type declaration
 PyTypeObject ImageFFmpegType =
 { 
-	PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+	PyVarObject_HEAD_INIT(NULL, 0)
+#else
+	/* python 2.5 and below */
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                         /*ob_size*/
+#endif
 	"VideoTexture.ImageFFmpeg",   /*tp_name*/
 	sizeof(PyImage),          /*tp_basicsize*/
 	0,                         /*tp_itemsize*/
diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp
index ec066811a52c5a4c44d1e9f36193042e6d18cf29..239f43763b86ca06fcf4acb10b79197d1b7963c6 100644
--- a/source/gameengine/VideoTexture/blendVideoTex.cpp
+++ b/source/gameengine/VideoTexture/blendVideoTex.cpp
@@ -1,6 +1,6 @@
 /* $Id$
 -----------------------------------------------------------------------------
-This source file is part of VideoTexure library
+This source file is part of VideoTexture library
 
 Copyright (c) 2006 The Zdeno Ash Miklas
 
@@ -49,14 +49,14 @@ static PyObject * getMaterialID (PyObject *self, PyObject *args)
 	char * matName;
 
 	// get parameters
-	if (!PyArg_ParseTuple(args, "Os", &obj, &matName))
+	if (!PyArg_ParseTuple(args, "Os:materialID", &obj, &matName))
 		return NULL;
 	// get material id
 	short matID = getMaterialID(obj, matName);
 	// if material was not found, report errot
 	if (matID < 0)
 	{
-		PyErr_SetString(PyExc_RuntimeError, "object doesn't have material with given name");
+		PyErr_SetString(PyExc_RuntimeError, "VideoTexture.materialID(ob, string): Object doesn't have material with given name");
 		return NULL;
 	}
 	// return material ID
@@ -67,7 +67,7 @@ static PyObject * getMaterialID (PyObject *self, PyObject *args)
 // get last error description
 static PyObject * getLastError (PyObject *self, PyObject *args)
 {
-	return Py_BuildValue("s", Exception::m_lastError.c_str());
+	return PyString_FromString(Exception::m_lastError.c_str());
 }
 
 // set log file
@@ -89,7 +89,7 @@ static PyObject * imageToArray (PyObject * self, PyObject *args)
 	if (!PyArg_ParseTuple(args, "O", &pyImg) || !pyImageTypes.in(pyImg->ob_type))
 	{
 		// if object is incorect, report error
-		PyErr_SetString(PyExc_TypeError, "The value must be a image source object");
+		PyErr_SetString(PyExc_TypeError, "VideoTexture.imageToArray(image): The value must be a image source object");
 		return NULL;
 	}
 	// get image structure
@@ -159,8 +159,25 @@ static void registerAllTypes(void)
 	pyFilterTypes.add(&FilterBGR24Type, "FilterBGR24");
 }
 
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef VideoTexture_module_def = {
+	{}, /* m_base */
+	"VideoTexture",  /* m_name */
+	"Module that allows to play video files on textures in GameBlender.",  /* m_doc */
+	0,  /* m_size */
+	moduleMethods,  /* m_methods */
+	0,  /* m_reload */
+	0,  /* m_traverse */
+	0,  /* m_clear */
+	0,  /* m_free */
+};
+#endif
+
 PyObject* initVideoTexture(void) 
 {
+	PyObject * m;
+	
 	// initialize GL extensions
 	//bgl::InitExtensions(0);
 
@@ -175,9 +192,25 @@ PyObject* initVideoTexture(void)
 	if (PyType_Ready(&TextureType) < 0) 
 		return NULL;
 
-	PyObject * m = Py_InitModule4("VideoTexture", moduleMethods,
-		"Module that allows to play video files on textures in GameBlender.",
-		(PyObject*)NULL,PYTHON_API_VERSION);
+	/* Use existing module where possible
+	 * be careful not to init any runtime vars after this */
+	m = PyImport_ImportModule( "VideoTexture" );
+	if(m) {
+		Py_DECREF(m);
+		return m;
+	}
+	else {
+		PyErr_Clear();
+	
+#if (PY_VERSION_HEX >= 0x03000000)
+		m = PyModule_Create(&VideoTexture_module_def);
+#else
+		m = Py_InitModule4("VideoTexture", moduleMethods,
+			"Module that allows to play video files on textures in GameBlender.",
+			(PyObject*)NULL,PYTHON_API_VERSION);
+#endif
+	}
+	
 	if (m == NULL) 
 		return NULL;
 
@@ -187,9 +220,10 @@ PyObject* initVideoTexture(void)
 
 	Py_INCREF(&TextureType);
 	PyModule_AddObject(m, (char*)"Texture", (PyObject*)&TextureType);
-
+	
 	// init last error description
 	Exception::m_lastError[0] = '\0';
+	
 	return m;
 }
 
diff --git a/source/kernel/gen_system/GEN_HashedPtr.cpp b/source/kernel/gen_system/GEN_HashedPtr.cpp
index 6dbed1fb7a8d6159451ba2ec0213cf7cfcc5a6c2..ff9de465a347605b07181b54db51cd3208e9b9c8 100644
--- a/source/kernel/gen_system/GEN_HashedPtr.cpp
+++ b/source/kernel/gen_system/GEN_HashedPtr.cpp
@@ -40,11 +40,12 @@
 // is a 32-bit integer, use all the bits of the pointer as long
 // as possible.
 //
-
+#if 1
 unsigned int GEN_Hash(void * inDWord)
 {
 	uintptr_t key = (uintptr_t)inDWord;
-
+#if 0
+	// this is way too complicated
 	key += ~(key << 16);
 	key ^=  (key >>  5);
 	key +=  (key <<  3);
@@ -53,4 +54,8 @@ unsigned int GEN_Hash(void * inDWord)
 	key ^=  (key >> 17);
 
   	return (unsigned int)(key & 0xffffffff);
+#else
+	return (unsigned int)(key ^ (key>>4));
+#endif
 }
+#endif
\ No newline at end of file
diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk
index 027a97eaf8e2a6988f1ce43796fa1bc239b5433d..f7bcd47930c3c444aa8ccbf8bbccad9305a1ba97 100644
--- a/source/nan_definitions.mk
+++ b/source/nan_definitions.mk
@@ -516,7 +516,7 @@ endif
     ifeq ($(FREE_WINDOWS), true)
       export NAN_GETTEXT_LIB ?= $(NAN_GETTEXT)/lib/freegettext.a $(NAN_ICONV)/lib/freeiconv.a
       export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION)
-      export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/freepy.a
+      export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/lib25_vs2005/libpython25.a
       export NAN_FREETYPE ?= $(LCGDIR)/gcc/freetype
       export NAN_ODE ?= $(LCGDIR)/gcc/ode
       export NAN_SDL ?= $(LCGDIR)/gcc/sdl
diff --git a/tools/Blender.py b/tools/Blender.py
index 9c978fccf4986375d23a2a9457cc3ff4e90ef081..7f9df0687544a58b79fb5f045f244923160624c3 100644
--- a/tools/Blender.py
+++ b/tools/Blender.py
@@ -126,8 +126,6 @@ def setup_staticlibs(lenv):
 		libincs += Split(lenv['BF_SDL_LIBPATH'])
 	if lenv['WITH_BF_FFMPEG']:
 		libincs += Split(lenv['BF_FFMPEG_LIBPATH'])
-	if lenv['WITH_BF_STATICCXX']:
-		statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
 	if lenv['WITH_BF_OPENEXR']:
 		libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
 		if lenv['WITH_BF_STATICOPENEXR']:
@@ -141,6 +139,8 @@ def setup_staticlibs(lenv):
 			statlibs += Split(lenv['BF_OPENAL_LIB_STATIC'])
 	if lenv['WITH_BF_STATICOPENGL']:
 		statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
+	if lenv['WITH_BF_STATICCXX']:
+		statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
 
 	if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
 		statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
diff --git a/tools/btools.py b/tools/btools.py
index 911376856adf84e7ced30fdad7035ec879bdbf73..96048a545fff15f752017ad8452820cf23c34433 100755
--- a/tools/btools.py
+++ b/tools/btools.py
@@ -36,6 +36,8 @@ def validate_arguments(args, bc):
 			'WITH_BF_FFMPEG', 'BF_FFMPEG_LIB','BF_FFMPEG_EXTRA', 'BF_FFMPEG',  'BF_FFMPEG_INC',
 			'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB',
 			'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH',
+			'WITH_BF_OPENJPEG', 'BF_OPENJPEG', 'BF_OPENJPEG_INC', 'BF_OPENJPEG_LIB', 'BF_OPENJPEG_LIBPATH',
+			'WITH_BF_REDCODE', 'BF_REDCODE', 'BF_REDCODE_INC', 'BF_REDCODE_LIB', 'BF_REDCODE_LIBPATH',
 			'WITH_BF_PNG', 'BF_PNG', 'BF_PNG_INC', 'BF_PNG_LIB', 'BF_PNG_LIBPATH',
 			'BF_TIFF', 'BF_TIFF_INC', 'BF_TIFF_LIB', 'BF_TIFF_LIBPATH',
 			'WITH_BF_ZLIB', 'BF_ZLIB', 'BF_ZLIB_INC', 'BF_ZLIB_LIB', 'BF_ZLIB_LIBPATH',
@@ -95,7 +97,7 @@ def validate_arguments(args, bc):
 		if (k in opts_list) or (k in arg_list):
 			okdict[k] = v
 		elif k in opts_list_split:
-			okdict[k] = v.split() # "" have alredy been stripped
+			okdict[k] = v.split() # "" have already been stripped
 		else:
 			print '\t'+bc.WARNING+'Invalid argument: '+bc.ENDC+k+'='+v
 
@@ -298,7 +300,7 @@ def read_opts(cfg, args):
 ##BF_PARANOID = True
 ##
 ### enable freetype2 support for text objects
-		(BoolVariable('WITH_BF_FREETYPE', 'Use FreeType2 if true', False)),
+		(BoolVariable('WITH_BF_FREETYPE', 'Use FreeType2 if true', True)),
 		('BF_FREETYPE', 'Freetype base path', ''),
 		('BF_FREETYPE_INC', 'Freetype include path', ''),
 		('BF_FREETYPE_LIB', 'Freetype library', ''),