svn merge -r 16174:16215 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorAndre Susano Pinto <andresusanopinto@gmail.com>
Thu, 21 Aug 2008 22:57:25 +0000 (22:57 +0000)
committerAndre Susano Pinto <andresusanopinto@gmail.com>
Thu, 21 Aug 2008 22:57:25 +0000 (22:57 +0000)
48 files changed:
extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj
release/scripts/flt_dofedit.py [new file with mode: 0644]
release/scripts/flt_lodedit.py [new file with mode: 0644]
release/scripts/flt_properties.py
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_collision.h
source/blender/blenkernel/BKE_effect.h
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/implicit.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/BIF_resources.h
source/blender/makesdna/DNA_ipo_types.h
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/python/api2_2x/Material.c
source/blender/python/api2_2x/Mesh.c
source/blender/python/api2_2x/Object.c
source/blender/python/api2_2x/doc/Material.py
source/blender/python/api2_2x/doc/Object.py
source/blender/src/buttons_object.c
source/blender/src/drawipo.c
source/blender/src/editipo.c
source/blender/src/editipo_lib.c
source/blender/src/resources.c
source/blender/src/space.c
source/blender/src/usiblender.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/GamePlayer/ghost/GPG_Application.h
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_Scene.h
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Physics/Bullet/SConscript
source/gameengine/Physics/common/PHY_DynamicTypes.h

index 29719ec9a3ec3becfc9d39d3aaf966f435913df3..1017c8af6eafb5f47360e954886d0e6d413cc00d 100644 (file)
@@ -856,10 +856,26 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform,
                                btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
                                btScalar height = coneShape->getHeight();//+coneShape->getMargin();
                                btVector3 start = worldTransform.getOrigin();
-                               getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(radius,btScalar(0.),btScalar(-0.5)*height),color);
-                               getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(-radius,btScalar(0.),btScalar(-0.5)*height),color);
-                               getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),radius,btScalar(-0.5)*height),color);
-                               getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),-radius,btScalar(-0.5)*height),color);
+                               // insert here Bullet 2.69 that fixes representation of cone
+                               int upAxis= coneShape->getConeUpIndex();
+                               
+                               btVector3       offsetHeight(0,0,0);
+                               offsetHeight[upAxis] = height * btScalar(0.5);
+                               btVector3       offsetRadius(0,0,0);
+                               offsetRadius[(upAxis+1)%3] = radius;
+                               btVector3       offset2Radius(0,0,0);
+                               offset2Radius[(upAxis+2)%3] = radius;
+
+                               getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offsetRadius),color);
+                               getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color);
+                               getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offset2Radius),color);
+                               getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offset2Radius),color);
+
+                               // buggy code that does not take into account the direction of the cone
+                               //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(radius,btScalar(0.),btScalar(-0.5)*height),color);
+                               //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(-radius,btScalar(0.),btScalar(-0.5)*height),color);
+                               //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),radius,btScalar(-0.5)*height),color);
+                               //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),-radius,btScalar(-0.5)*height),color);
                                break;
 
                        }
index 9a807f2d39a692558ae7de61fed8a296a7b8e64a..76fde7612e3e6b964b8398a90df180a7c387be66 100644 (file)
@@ -19,7 +19,7 @@
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet"
+                               AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\gameengine\Rasterizer"
                                PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
                                MinimalRebuild="FALSE"
                                BasicRuntimeChecks="3"
@@ -64,7 +64,7 @@
                        CharacterSet="2">
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet"
+                               AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\gameengine\Rasterizer"
                                PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
                                RuntimeLibrary="0"
                                UsePrecompiledHeader="2"
                        CharacterSet="2">
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet"
+                               AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\kernel\gen_system;..\..\..\..\..\source\gameengine\Rasterizer"
                                PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
                                RuntimeLibrary="0"
                                UsePrecompiledHeader="2"
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet"
+                               AdditionalIncludeDirectories="..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\..\source\gameengine\Physics\common;..\..\..\..\..\source\gameengine\Physics\Bullet;..\..\..\..\..\source\gameengine\Rasterizer;..\..\..\..\..\source\kernel\gen_system"
                                PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
                                MinimalRebuild="FALSE"
                                BasicRuntimeChecks="3"
diff --git a/release/scripts/flt_dofedit.py b/release/scripts/flt_dofedit.py
new file mode 100644 (file)
index 0000000..36e8e4d
--- /dev/null
@@ -0,0 +1,835 @@
+#!BPY
+
+"""
+Name: 'FLT DOF Editor'
+Blender: 240
+Group: 'Misc'
+Tooltip: 'Degree of Freedom editor for FLT nodes'
+"""
+
+__author__ = "Geoffrey Bantle"
+__version__ = "1.0 11/21/07"
+__email__ = ('scripts', 'Author, ')
+__url__ = ('blender', 'blenderartists.org')
+
+__bpydoc__ ="""\
+This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a
+registered trademark of MultiGen-Paradigm, Inc.
+
+Feature overview and more availible at:
+http://wiki.blender.org/index.php/Scripts/Manual/FLTools
+"""
+
+# --------------------------------------------------------------------------
+# flt_palettemanager.py version 0.1 2005/04/08
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2007: Blender Foundation
+#
+# 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.Draw as Draw
+from Blender.BGL import *
+import Blender
+import flt_properties
+reload(flt_properties)
+from flt_properties import *
+
+#event codes
+evcode = {
+       "DOF_MAKE" : 100,
+       "DOF_UPDATE" : 138,
+       "DOF_DELETE" : 101,
+       "DOF_TRANSX" : 102,
+       "DOF_TRANSY" : 103,
+       "DOF_TRANSZ" : 104,
+       "DOF_ROTX" : 105,
+       "DOF_ROTY" : 106,
+       "DOF_ROTZ" : 107,
+       "DOF_SCALEX" : 108,
+       "DOF_SCALEY" : 109,
+       "DOF_SCALEZ" : 110,
+       "DOF_MIN_TRANSX" : 111,
+       "DOF_MIN_TRANSY" : 112,
+       "DOF_MIN_TRANSZ" : 113,
+       "DOF_MIN_ROTX" : 114,
+       "DOF_MIN_ROTY" : 115,
+       "DOF_MIN_ROTZ" : 116,
+       "DOF_MIN_SCALEX" : 117,
+       "DOF_MIN_SCALEY" : 118,
+       "DOF_MIN_SCALEZ" : 119,
+       "DOF_MAX_TRANSX" : 120,
+       "DOF_MAX_TRANSY" : 121,
+       "DOF_MAX_TRANSZ" : 122,
+       "DOF_MAX_ROTX" : 123,
+       "DOF_MAX_ROTY" : 124,
+       "DOF_MAX_ROTZ" : 125,
+       "DOF_MAX_SCALEX" : 126,
+       "DOF_MAX_SCALEY" : 127,
+       "DOF_MAX_SCALEZ" : 128,
+       "DOF_STEP_TRANSX" : 129,
+       "DOF_STEP_TRANSY" : 130,
+       "DOF_STEP_TRANSZ" : 131,
+       "DOF_STEP_ROTX" : 132,
+       "DOF_STEP_ROTY" : 133,
+       "DOF_STEP_ROTZ" : 134,
+       "DOF_STEP_SCALEX" : 135,
+       "DOF_STEP_SCALEY" : 136,
+       "DOF_STEP_SCALEZ" : 137
+}
+
+#system
+DOF_MAKE = None
+DOF_UPDATE = None
+DOF_DELETE = None
+
+#toggle buttons
+DOF_TRANSX = None
+DOF_TRANSY = None
+DOF_TRANSZ = None
+DOF_ROTX = None
+DOF_ROTY = None
+DOF_ROTZ = None
+DOF_SCALEX = None
+DOF_SCALEY = None
+DOF_SCALEZ = None
+
+#Minimums
+DOF_MIN_TRANSX = None
+DOF_MIN_TRANSY = None
+DOF_MIN_TRANSZ = None
+DOF_MIN_ROTX = None
+DOF_MIN_ROTY = None
+DOF_MIN_ROTZ = None
+DOF_MIN_SCALEX = None
+DOF_MIN_SCALEY = None
+DOF_MIN_SCALEZ = None
+
+#maximums
+DOF_MAX_TRANSX = None
+DOF_MAX_TRANSY = None
+DOF_MAX_TRANSZ = None
+DOF_MAX_ROTX = None
+DOF_MAX_ROTY = None
+DOF_MAX_ROTZ = None
+DOF_MAX_SCALEX = None
+DOF_MAX_SCALEY = None
+DOF_MAX_SCALEZ = None
+
+#step
+DOF_STEP_TRANSX = None
+DOF_STEP_TRANSY = None
+DOF_STEP_TRANSZ = None
+DOF_STEP_ROTX = None
+DOF_STEP_ROTY = None
+DOF_STEP_ROTZ = None
+DOF_STEP_SCALEX = None
+DOF_STEP_SCALEY = None
+DOF_STEP_SCALEZ = None
+
+#labels
+DOF_ROTSTRING = None
+DOF_TRANSTRING = None
+DOF_SCALESTRING = None
+DOF_EDITLABEL = None
+
+#make ID props easier/morereadable
+zmin = '14d!ZMIN'
+zmax = '15d!ZMAX'
+zcur = '16d!ZCUR'
+zstep = '17d!ZSTEP'
+ymin = '18d!YMIN'
+ymax = '19d!YMAX'
+ycur = '20d!YCUR'
+ystep = '21d!YSTEP'
+xmin = '22d!XMIN'
+xmax = '23d!XMAX'
+xcur = '24d!XCUR'
+xstep = '25d!XSTEP'
+pitchmin = '26d!PITCH-MIN'
+pitchmax = '27d!PITCH-MAX'
+pitchcur = '28d!PITCH-CUR'
+pitchstep = '29d!PITCH-STEP'
+rollmin = '30d!ROLL-MIN'
+rollmax = '31d!ROLL-MAX'
+rollcur = '32d!ROLL-CUR'
+rollstep = '33d!ROLL-STEP'
+yawmin = '34d!YAW-MIN'
+yawmax = '35d!YAW-MAX'
+yawcur = '36d!YAW-CUR'
+yawstep = '37d!YAW-STEP'
+zscalemin = '38d!ZSIZE-MIN'
+zscalemax = '39d!ZSIZE-MAX'
+zscalecur = '40d!ZSIZE-CUR'
+zscalestep = '41d!ZSIZE-STEP'
+yscalemin = '42d!YSIZE-MIN'
+yscalemax = '43d!YSIZE-MAX'
+yscalecur = '44d!YSIZE-CUR'
+yscalestep = '45d!YSIZE-STEP'
+xscalemin = '46d!XSIZE-MIN'
+xscalemax = '47d!XSIZE-MAX'
+xscalecur = '48d!XSIZE-CUR'
+xscalestep = '49d!XSIZE-STEP'
+
+
+
+def update_state():
+       state = dict()
+       state["activeScene"] = Blender.Scene.GetCurrent()
+       state["activeObject"] = state["activeScene"].objects.active
+       if state["activeObject"] and not state["activeObject"].sel:
+               state["activeObject"] = None
+       state["activeMesh"] = None
+       if state["activeObject"] and state["activeObject"].type == 'Mesh':
+               state["activeMesh"] = state["activeObject"].getData(mesh=True)
+       
+
+       state["activeFace"] = None
+       if state["activeMesh"]:
+               if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
+                       state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
+               
+               
+       #update editmode
+       state["editmode"]       = Blender.Window.EditMode()
+
+       return state
+       
+def idprops_append(object, typecode, props):
+       object.properties["FLT"] = dict()
+       object.properties["FLT"]['type'] = typecode 
+       for prop in props:
+               object.properties["FLT"][prop] = props[prop]
+       object.properties["FLT"]['3t8!id'] = object.name
+
+def idprops_kill():
+       state = update_state()
+       if state["activeObject"] and state["activeObject"].properties.has_key('FLT'):
+               state["activeObject"].properties.pop('FLT')
+
+def idprops_copy(source):
+       state = update_state()
+       if source.properties.has_key('FLT'):
+               for object in state["activeScene"].objects:
+                       if object.sel and object != source and (state["activeScene"].Layers & object.Layers):
+                               idprops_kill(object)
+                               object.properties['FLT'] = dict()
+                               for key in source.properties['FLT']:
+                                       object.properties['FLT'][key] = source.properties['FLT'][key]
+
+def select_by_typecode(typecode):
+       state = update_state()
+       
+       for object in state["activeScene"].objects:
+               if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers:
+                               object.select(1)
+
+def DOF_get_frame():
+       state = update_state()
+       
+       if not state["activeObject"] and not id_props_type(state["activeObject"], 14):
+               return
+       
+       #Warning! assumes 1 BU == 10 meters.
+       #do origin
+       state["activeObject"].properties['FLT']['5d!ORIGX'] = state["activeObject"].getLocation('worldspace')[0]*10.0
+       state["activeObject"].properties['FLT']['6d!ORIGY'] = state["activeObject"].getLocation('worldspace')[1]*10.0
+       state["activeObject"].properties['FLT']['7d!ORIGZ'] = state["activeObject"].getLocation('worldspace')[2]*10.0
+       #do X axis
+       x = Blender.Mathutils.Vector(1.0,0.0,0.0)
+       x = x * state["activeObject"].getMatrix('worldspace')
+       x = x * 10.0
+       state["activeObject"].properties['FLT']['8d!XAXIS-X'] = x[0]
+       state["activeObject"].properties['FLT']['9d!XAXIS-Y'] = x[1]
+       state["activeObject"].properties['FLT']['10d!XAXIS-Z'] = x[2]
+       #do X/Y plane
+       x = Blender.Mathutils.Vector(0.0,1.0,0.0)
+       x.normalize()
+       x = x * state["activeObject"].getMatrix('worldspace')
+       x = x * 10.0
+       state["activeObject"].properties['FLT']['11d!XYPLANE-X'] = x[0]
+       state["activeObject"].properties['FLT']['12d!XYPLANE-Y'] = x[1]
+       state["activeObject"].properties['FLT']['13d!XZPLANE-Z'] = x[2]
+
+def idprops_type(object, typecode):
+       if object.properties.has_key('FLT') and object.properties['FLT'].has_key('type') and object.properties['FLT']['type'] == typecode:
+               return True
+       return False
+
+#ui type code
+def get_prop(typecode, prop):
+       
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"], typecode):
+               props = state["activeObject"].properties['FLT']
+       else:
+               props =  flt_properties.FLTDOF
+               
+       return props[prop]      
+
+def set_prop(typecode, prop, value):
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"],typecode):
+               state["activeObject"].properties['FLT'][prop] = value           
+
+lockxtrans = (1 << 31)
+lockytrans = (1 << 30)
+lockztrans = (1 << 29)
+lockxrot = (1 << 28)
+lockyrot = (1 << 27)
+lockzrot = (1 << 26)
+lockxscale = (1 << 25)
+lockyscale = (1 << 24)
+lockzscale = (1 << 23)
+
+def get_lockmask(mask):        
+       state = update_state()
+       if state["activeObject"]:
+               flag = get_prop(14,'50I!FLAG')
+               if flag & mask:
+                       return True
+       return False    
+
+def set_lockmask(mask):
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"], 14):
+               oldvalue = state["activeObject"].properties['FLT']['50I!FLAG']
+               oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0]
+               oldvalue |= mask
+               state["activeObject"].properties['FLT']['50I!FLAG'] = struct.unpack('>i', struct.pack(">I", oldvalue))[0]
+
+def clear_lockmask(mask):
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"], 14):
+               oldvalue = state["activeObject"].properties['FLT']['50I!FLAG']
+               oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0]
+               oldvalue &= ~mask
+               state["activeObject"].properties['FLT']['50I!FLAG'] = struct.unpack('>i',struct.pack('>I',oldvalue))[0] 
+
+       
+def create_dof():
+       state = update_state()
+       actobj = state["activeObject"]
+       if actobj and not idprops_type(actobj, 14):
+               idprops_kill()
+               idprops_append(actobj,14, flt_properties.FLTDOF)
+               DOF_get_frame()
+       
+               
+def event(evt,val):
+       if evt == Draw.ESCKEY:
+               Draw.Exit()
+               
+def but_event(evt):
+       global DOF_MAKE
+       global DOF_UPDATE
+       global DOF_DELETE
+
+       global DOF_TRANSX
+       global DOF_TRANSY
+       global DOF_TRANSZ
+       global DOF_ROTX
+       global DOF_ROTY
+       global DOF_ROTZ
+       global DOF_SCALEX
+       global DOF_SCALEY
+       global DOF_SCALEZ
+
+       global DOF_MIN_TRANSX
+       global DOF_MIN_TRANSY
+       global DOF_MIN_TRANSZ
+       global DOF_MIN_ROTX
+       global DOF_MIN_ROTY
+       global DOF_MIN_ROTZ
+       global DOF_MIN_SCALEX
+       global DOF_MIN_SCALEY
+       global DOF_MIN_SCALEZ
+
+       global DOF_MAX_TRANSX
+       global DOF_MAX_TRANSY
+       global DOF_MAX_TRANSZ
+       global DOF_MAX_ROTX
+       global DOF_MAX_ROTY
+       global DOF_MAX_ROTZ
+       global DOF_MAX_SCALEX
+       global DOF_MAX_SCALEY
+       global DOF_MAX_SCALEZ
+
+       global DOF_STEP_TRANSX
+       global DOF_STEP_TRANSY
+       global DOF_STEP_TRANSZ
+       global DOF_STEP_ROTX
+       global DOF_STEP_ROTY
+       global DOF_STEP_ROTZ
+       global DOF_STEP_SCALEX
+       global DOF_STEP_SCALEY
+       global DOF_STEP_SCALEZ
+       
+       #labels
+       global DOF_ROTSTRING
+       global DOF_TRANSTRING
+       global DOF_SCALESTRING
+       
+       
+       #masks
+       global lockxtrans
+       global lockytrans
+       global lockztrans
+       global lockxrot
+       global lockyrot
+       global lockzrot
+       global lockxscale
+       global lockyscale
+       global lockzscale
+
+       global zmin
+       global zmax
+       global zcur
+       global zstep
+       global ymin
+       global ymax
+       global ycur
+       global ystep
+       global xmin
+       global xmax
+       global xcur
+       global xstep
+       global pitchmin
+       global pitchmax
+       global pitchcur
+       global pitchstep
+       global rollmin
+       global rollmax
+       global rollcur
+       global rollstep
+       global yawmin
+       global yawmax
+       global yawcur
+       global yawstep
+       global zscalemin
+       global zscalemax
+       global zscalecur
+       global zscalestep
+       global yscalemin
+       global yscalemax
+       global yscalecur
+       global yscalestep
+       global xscalemin
+       global xscalemax
+       global xscalecur
+       global xscalestep       
+
+       
+       
+       #do "system" events
+       if evt == evcode["DOF_MAKE"]:
+               create_dof()
+
+       if evt == evcode["DOF_UPDATE"]:
+               DOF_get_frame()
+       
+       if evt == evcode["DOF_DELETE"]:
+               idprops_kill()
+       #do translation lock events
+       if evt == evcode["DOF_TRANSX"]:
+               if DOF_TRANSX.val == True:
+                       set_lockmask(lockxtrans)
+               else:
+                       clear_lockmask(lockxtrans)
+
+       if evt == evcode["DOF_TRANSY"]:
+               if DOF_TRANSY.val == True:
+                       set_lockmask(lockytrans)
+               else:
+                       clear_lockmask(lockytrans)
+
+       if evt == evcode["DOF_TRANSZ"]:
+               if DOF_TRANSZ.val == True:
+                       set_lockmask(lockztrans)
+               else:
+                       clear_lockmask(lockztrans)
+
+
+       #do rotation lock events
+       if evt == evcode["DOF_ROTX"]:
+               if DOF_ROTX.val == True:
+                       set_lockmask(lockxrot)
+               else:
+                       clear_lockmask(lockxrot)
+
+       if evt == evcode["DOF_ROTY"]:
+               if DOF_ROTY.val == True:
+                       set_lockmask(lockyrot)
+               else:
+                       clear_lockmask(lockyrot)
+
+       if evt == evcode["DOF_ROTZ"]:
+               if DOF_ROTZ.val == True:
+                       set_lockmask(lockzrot)
+               else:
+                       clear_lockmask(lockzrot)
+
+       #do scale lock events
+       if evt == evcode["DOF_SCALEX"]:
+               if DOF_SCALEX.val == True:
+                       set_lockmask(lockxscale)
+               else:
+                       clear_lockmask(lockxscale)
+
+       if evt == evcode["DOF_SCALEY"]:
+               if DOF_SCALEY.val == True:
+                       set_lockmask(lockyscale)
+               else:
+                       clear_lockmask(lockyscale)
+
+       if evt == evcode["DOF_SCALEZ"]:
+               if DOF_SCALEZ.val == True:
+                       set_lockmask(lockzscale)
+               else:
+                       clear_lockmask(lockzscale)
+                       
+       
+       #do translation buttons
+       if evt == evcode["DOF_MIN_TRANSX"]:
+               set_prop(14, xmin, DOF_MIN_TRANSX.val)
+       if evt == evcode["DOF_MAX_TRANSX"]:
+               set_prop(14,xmax, DOF_MAX_TRANSX.val)
+       if evt == evcode["DOF_STEP_TRANSX"]:
+               set_prop(14,xstep, DOF_STEP_TRANSX.val)
+               
+       if evt == evcode["DOF_MIN_TRANSY"]:
+               set_prop(14, ymin, DOF_MIN_TRANSY.val)
+       if evt == evcode["DOF_MAX_TRANSY"]:
+               set_prop(14,ymax, DOF_MAX_TRANSY.val)
+       if evt == evcode["DOF_STEP_TRANSY"]:
+               set_prop(14,ystep, DOF_STEP_TRANSY.val)
+               
+       if evt == evcode["DOF_MIN_TRANSZ"]:
+               set_prop(14, zmin, DOF_MIN_TRANSZ.val)
+       if evt == evcode["DOF_MAX_TRANSZ"]:
+               set_prop(14, zmax, DOF_MAX_TRANSZ.val)
+       if evt == evcode["DOF_STEP_TRANSZ"]:
+               set_prop(14, zstep, DOF_STEP_TRANSZ.val)
+
+       #do rotation buttons
+       if evt == evcode["DOF_MIN_ROTX"]:
+               set_prop(14, pitchmin, DOF_MIN_ROTX.val)
+       if evt == evcode["DOF_MAX_ROTX"]:
+               set_prop(14, pitchmax, DOF_MAX_ROTX.val)
+       if evt == evcode["DOF_STEP_ROTX"]:
+               set_prop(14, pitchstep, DOF_STEP_ROTX.val)
+
+       if evt == evcode["DOF_MIN_ROTY"]:
+               set_prop(14, rollmin, DOF_MIN_ROTY.val)
+       if evt == evcode["DOF_MAX_ROTY"]:
+               set_prop(14, rollmax, DOF_MAX_ROTY.val)
+       if evt == evcode["DOF_STEP_ROTY"]:
+               set_prop(14, rollstep, DOF_STEP_ROTY.val)       
+
+       if evt == evcode["DOF_MIN_ROTZ"]:
+               set_prop(14, yawmin, DOF_MIN_ROTZ.val)
+       if evt == evcode["DOF_MAX_ROTZ"]:
+               set_prop(14, yawmax, DOF_MAX_ROTZ.val)
+       if evt == evcode["DOF_STEP_ROTZ"]:
+               set_prop(14, yawstep, DOF_STEP_ROTZ.val)        
+               
+       #do scale buttons
+       if evt == evcode["DOF_MIN_SCALEX"]:
+               set_prop(14, xscalemin, DOF_MIN_SCALEX.val)
+       if evt == evcode["DOF_MAX_SCALEX"]:
+               set_prop(14, xscalemax, DOF_MAX_SCALEX.val)
+       if evt == evcode["DOF_STEP_SCALEX"]:
+               set_prop(14, xscalestep, DOF_STEP_SCALEX.val)
+       
+       if evt == evcode["DOF_MIN_SCALEY"]:
+               set_prop(14, yscalemin, DOF_MIN_SCALEY.val)
+       if evt == evcode["DOF_MAX_SCALEY"]:
+               set_prop(14, yscalemax, DOF_MAX_SCALEY.val)
+       if evt == evcode["DOF_STEP_SCALEY"]:
+               set_prop(14, yscalestep, DOF_STEP_SCALEY.val)   
+
+       if evt == evcode["DOF_MIN_SCALEZ"]:
+               set_prop(14, zscalemin, DOF_MIN_SCALEZ.val)
+       if evt == evcode["DOF_MAX_SCALEZ"]:
+               set_prop(14, zscalemax, DOF_MAX_SCALEZ.val)
+       if evt == evcode["DOF_STEP_SCALEZ"]:
+               set_prop(14, zscalestep, DOF_STEP_SCALEZ.val)
+
+
+       Draw.Redraw(1)
+       Blender.Window.RedrawAll()
+
+def draw_propsheet(x,y):
+       #UI buttons
+       global DOF_MAKE
+       global DOF_UPDATE
+       global DOF_DELETE
+
+       global DOF_TRANSX
+       global DOF_TRANSY
+       global DOF_TRANSZ
+       global DOF_ROTX
+       global DOF_ROTY
+       global DOF_ROTZ
+       global DOF_SCALEX
+       global DOF_SCALEY
+       global DOF_SCALEZ
+
+       global DOF_MIN_TRANSX
+       global DOF_MIN_TRANSY
+       global DOF_MIN_TRANSZ
+       global DOF_MIN_ROTX
+       global DOF_MIN_ROTY
+       global DOF_MIN_ROTZ
+       global DOF_MIN_SCALEX
+       global DOF_MIN_SCALEY
+       global DOF_MIN_SCALEZ
+
+       global DOF_MAX_TRANSX
+       global DOF_MAX_TRANSY
+       global DOF_MAX_TRANSZ
+       global DOF_MAX_ROTX
+       global DOF_MAX_ROTY
+       global DOF_MAX_ROTZ
+       global DOF_MAX_SCALEX
+       global DOF_MAX_SCALEY
+       global DOF_MAX_SCALEZ
+
+       global DOF_STEP_TRANSX
+       global DOF_STEP_TRANSY
+       global DOF_STEP_TRANSZ
+       global DOF_STEP_ROTX
+       global DOF_STEP_ROTY
+       global DOF_STEP_ROTZ
+       global DOF_STEP_SCALEX
+       global DOF_STEP_SCALEY
+       global DOF_STEP_SCALEZ
+
+       #labels
+       global DOF_ROTSTRING
+       global DOF_TRANSTRING
+       global DOF_SCALESTRING  
+       global DOF_EDITLABEL
+       
+       #masks
+       global lockxtrans
+       global lockytrans
+       global lockztrans
+       global lockxrot
+       global lockyrot
+       global lockzrot
+       global lockxscale
+       global lockyscale
+       global lockzscale
+       
+       global zmin
+       global zmax
+       global zcur
+       global zstep
+       global ymin
+       global ymax
+       global ycur
+       global ystep
+       global xmin
+       global xmax
+       global xcur
+       global xstep
+       global pitchmin
+       global pitchmax
+       global pitchcur
+       global pitchstep
+       global rollmin
+       global rollmax
+       global rollcur
+       global rollstep
+       global yawmin
+       global yawmax
+       global yawcur
+       global yawstep
+       global zscalemin
+       global zscalemax
+       global zscalecur
+       global zscalestep
+       global yscalemin
+       global yscalemax
+       global yscalecur
+       global yscalestep
+       global xscalemin
+       global xscalemax
+       global xscalecur
+       global xscalestep       
+
+       
+       global evcode
+       
+       state = update_state()
+       
+       row_height = 20
+       toggle_width = 50
+       input_width = 100
+       pad = 10
+       origx = x
+       origy = (row_height * 15) + (pad * 15)
+
+
+       #editor label
+       x = origx
+       y = origy
+       #y = y - (row_height + pad)
+       DOF_EDITLABEL = Blender.Draw.Label("FLT Degree of Freedom Editor", x, y, 200, row_height)
+
+
+       #draw Translation limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_TRANSTRING = Blender.Draw.Label("Translation Limits", x, y, input_width, row_height)
+
+
+       #X limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_TRANSX = Blender.Draw.Toggle("LimX", evcode["DOF_TRANSX"], x, y, toggle_width, row_height, get_lockmask(lockxtrans), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_TRANSX = Blender.Draw.Number("MinX", evcode["DOF_MIN_TRANSX"], x, y, input_width, row_height,get_prop(14,xmin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_TRANSX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_TRANSX"], x, y, input_width, row_height,get_prop(14,xmax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_TRANSX = Blender.Draw.Number("StepX", evcode["DOF_STEP_TRANSX"], x, y, input_width, row_height,get_prop(14,xstep), -1000000.0, 1000000.0, "")
+       
+       #Y limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_TRANSY = Blender.Draw.Toggle("LimY", evcode["DOF_TRANSY"], x, y, toggle_width, row_height, get_lockmask(lockytrans), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_TRANSY = Blender.Draw.Number("MinY", evcode["DOF_MIN_TRANSY"], x, y, input_width, row_height, get_prop(14,ymin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_TRANSY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_TRANSY"], x, y, input_width, row_height, get_prop(14,ymax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_TRANSY = Blender.Draw.Number("StepY", evcode["DOF_STEP_TRANSY"], x, y, input_width, row_height, get_prop(14,ystep), -1000000.0, 1000000.0, "") 
+       
+       #Z limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_TRANSZ = Blender.Draw.Toggle("LimZ", evcode["DOF_TRANSZ"], x, y, toggle_width, row_height, get_lockmask(lockztrans), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_TRANSZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_TRANSZ"], x, y, input_width, row_height, get_prop(14,zmin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_TRANSZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_TRANSZ"], x, y, input_width, row_height, get_prop(14,zmax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_TRANSZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_TRANSZ"], x, y, input_width, row_height, get_prop(14,zstep), -1000000.0, 1000000.0, "")
+       
+       #draw Rotation limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_ROTSTRING = Blender.Draw.Label("Rotation Limits", x, y, input_width, row_height)
+
+       #draw Rotation limits
+       #X limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_ROTX = Blender.Draw.Toggle("LimX", evcode["DOF_ROTX"], x, y, toggle_width, row_height, get_lockmask(lockxrot), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_ROTX = Blender.Draw.Number("MinX", evcode["DOF_MIN_ROTX"], x, y, input_width, row_height, get_prop(14,pitchmin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_ROTX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_ROTX"], x, y, input_width, row_height, get_prop(14,pitchmax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_ROTX = Blender.Draw.Number("StepX", evcode["DOF_STEP_ROTX"], x, y, input_width, row_height, get_prop(14,pitchstep), -1000000.0, 1000000.0, "")
+               
+       #Y limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_ROTY = Blender.Draw.Toggle("LimY", evcode["DOF_ROTY"], x, y, toggle_width, row_height, get_lockmask(lockyrot), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_ROTY = Blender.Draw.Number("MinY", evcode["DOF_MIN_ROTY"], x, y, input_width, row_height, get_prop(14,rollmin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_ROTY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_ROTY"], x, y, input_width, row_height, get_prop(14,rollmax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_ROTY = Blender.Draw.Number("StepY", evcode["DOF_STEP_ROTY"], x, y, input_width, row_height, get_prop(14,rollstep), -1000000.0, 1000000.0, "")
+               
+       #Z limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_ROTZ = Blender.Draw.Toggle("LimZ", evcode["DOF_ROTZ"], x, y, toggle_width, row_height, get_lockmask(lockzrot), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_ROTZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_ROTZ"], x, y, input_width, row_height, get_prop(14, yawmin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_ROTZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_ROTZ"], x, y, input_width, row_height, get_prop(14, yawmax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_ROTZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_ROTZ"], x, y, input_width, row_height, get_prop(14, yawstep), -1000000.0, 1000000.0, "")
+                       
+
+       #draw Scale limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_SCALESTRING = Blender.Draw.Label("Scale Limits", x, y, input_width, row_height)
+
+       #draw Scale limits
+       #X limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_SCALEX = Blender.Draw.Toggle("LimX", evcode["DOF_SCALEX"], x, y, toggle_width, row_height, get_lockmask(lockxscale), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_SCALEX = Blender.Draw.Number("MinX", evcode["DOF_MIN_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalemin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_SCALEX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalemax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_SCALEX = Blender.Draw.Number("StepX", evcode["DOF_STEP_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalestep), -1000000.0, 1000000.0, "")
+               
+       #Y limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_SCALEY = Blender.Draw.Toggle("LimY", evcode["DOF_SCALEY"], x, y, toggle_width, row_height, get_lockmask(lockyscale), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_SCALEY = Blender.Draw.Number("MinY", evcode["DOF_MIN_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalemin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_SCALEY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalemax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_SCALEY = Blender.Draw.Number("StepY", evcode["DOF_STEP_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalestep), -1000000.0, 1000000.0, "")           
+
+       #Z limits
+       x = origx
+       y = y- (row_height + pad)
+       DOF_SCALEZ = Blender.Draw.Toggle("LimZ", evcode["DOF_SCALEZ"], x, y, toggle_width, row_height, get_lockmask(lockzscale), "")
+       x = x + (toggle_width + pad)
+       DOF_MIN_SCALEZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalemin),  -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_MAX_SCALEZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalemax), -1000000.0, 1000000.0, "")
+       x = x + (input_width + pad)
+       DOF_STEP_SCALEZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalestep), -1000000.0, 1000000.0, "")           
+
+       #System
+       x = origx
+       y = y - (row_height + (pad)*3)
+       DOF_MAKE = Blender.Draw.PushButton("Make DOF", evcode["DOF_MAKE"], x, y, input_width, row_height, "Make a Dof Node out of Active Object")
+       x = x + (input_width + pad)
+       DOF_UPDATE = Blender.Draw.PushButton("Grab Loc/Rot", evcode["DOF_UPDATE"], x, y, input_width, row_height, "Update the Dof Node position/orientation")
+       x = x + (input_width + pad)
+       DOF_DELETE = Blender.Draw.PushButton("Delete DOF", evcode["DOF_DELETE"], x, y, input_width, row_height, "Delete the Dof Node properties")
+
+
+       
+       
+def gui():
+       #draw the propsheet/toolbox.
+       psheety = 800
+       #psheetx = psheety + 10
+       draw_propsheet(20,psheety)
+
+Draw.Register(gui,event,but_event)
+       
\ No newline at end of file
diff --git a/release/scripts/flt_lodedit.py b/release/scripts/flt_lodedit.py
new file mode 100644 (file)
index 0000000..58319b9
--- /dev/null
@@ -0,0 +1,502 @@
+#!BPY
+
+"""
+Name: 'FLT LOD Editor'
+Blender: 240
+Group: 'Misc'
+Tooltip: 'Level of Detail Edtior for FLT nodes'
+"""
+
+__author__ = "Geoffrey Bantle"
+__version__ = "1.0 11/21/07"
+__email__ = ('scripts', 'Author, ')
+__url__ = ('blender', 'blenderartists.org')
+
+__bpydoc__ ="""\
+This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a
+registered trademark of MultiGen-Paradigm, Inc.
+
+Feature overview and more availible at:
+http://wiki.blender.org/index.php/Scripts/Manual/FLTools
+"""
+
+# --------------------------------------------------------------------------
+# flt_palettemanager.py version 0.1 2005/04/08
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2007: Blender Foundation
+#
+# 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.Draw as Draw
+from Blender.BGL import *
+import Blender
+import flt_properties
+reload(flt_properties)
+from flt_properties import *
+
+#event codes
+evcode = {
+       "LOD_MAKE" : 100,
+       "LOD_DELETE" : 101,
+       "LOD_CALC_CENTER" : 102,
+       "LOD_GRAB_CENTER" : 103,
+       "LOD_X" : 104,
+       "LOD_Y" : 105,
+       "LOD_Z" : 106,
+       "LOD_FREEZE" : 107,
+       "LOD_SIG" : 108,
+       "LOD_IN" : 109,
+       "LOD_OUT" : 110,
+       "LOD_TRANS" : 111,              
+       "LOD_PREVIOUS" : 112
+}
+
+
+#system
+LOD_MAKE = None                        #PushButton
+LOD_DELETE = None              #PushButton
+LOD_CALC_CENTER = None #PushButton
+LOD_GRAB_CENTER = None #Pushbutton
+LOD_FREEZE = None              #Toggle
+LOD_PREVIOUS = None            #Toggle
+
+LOD_X = None                   #Input
+LOD_Y = None                   #Input
+LOD_Z = None                   #Input
+
+LOD_SIG = None                 #Input
+LOD_IN = None                  #Input
+LOD_OUT = None                 #Input
+LOD_TRANS = None               #Input
+
+#labels
+LOD_EDITLABEL = None
+LOD_SWITCHLABEL = None
+LOD_CENTERLABEL = None
+
+LOD_XLABEL = None
+LOD_YLABEL = None
+LOD_ZLABEL = None
+LOD_SIGLABEL = None
+LOD_INLABEL = None
+LOD_OUTLABEL = None
+LOD_TRANSLABEL = None
+
+
+#ID Props
+switch_in = '5d!switch in'
+switch_out = '6d!switch out'
+xco = '10d!X co'
+yco = '11d!Y co'
+zco = '12d!Z co'
+trans = '13d!Transition'
+sig_size = '14d!Sig Size'
+
+#Flags
+lodflag = '9I!flags'
+previous_mask = (1 << 31)
+freeze_mask = (1 << 29)
+
+def update_state():
+       state = dict()
+       state["activeScene"] = Blender.Scene.GetCurrent()
+       state["activeObject"] = state["activeScene"].objects.active
+       if state["activeObject"] and not state["activeObject"].sel:
+               state["activeObject"] = None
+       state["activeMesh"] = None
+       if state["activeObject"] and state["activeObject"].type == 'Mesh':
+               state["activeMesh"] = state["activeObject"].getData(mesh=True)
+       
+       state["activeFace"] = None
+       if state["activeMesh"]:
+               if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
+                       state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
+               
+               
+       #update editmode
+       state["editmode"]       = Blender.Window.EditMode()
+
+       return state
+       
+def idprops_append(object, typecode, props):
+       object.properties["FLT"] = dict()
+       object.properties["FLT"]['type'] = typecode 
+       for prop in props:
+               object.properties["FLT"][prop] = props[prop]
+       object.properties["FLT"]['3t8!id'] = object.name
+
+def idprops_kill():
+       state = update_state()
+       if state["activeObject"] and state["activeObject"].properties.has_key('FLT'):
+               state["activeObject"].properties.pop('FLT')
+
+def idprops_copy(source):
+       state = update_state()
+       if source.properties.has_key('FLT'):
+               for object in state["activeScene"].objects:
+                       if object.sel and object != source and (state["activeScene"].Layers & object.Layers):
+                               idprops_kill(object)
+                               object.properties['FLT'] = dict()
+                               for key in source.properties['FLT']:
+                                       object.properties['FLT'][key] = source.properties['FLT'][key]
+
+def select_by_typecode(typecode):
+       state = update_state()
+       
+       for object in state["activeScene"].objects:
+               if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers:
+                               object.select(1)
+
+def idprops_type(object, typecode):
+       if object.properties.has_key('FLT') and object.properties['FLT'].has_key('type') and object.properties['FLT']['type'] == typecode:
+               return True
+       return False
+
+#ui type code
+def get_prop(typecode, prop):
+       
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"], typecode):
+               props = state["activeObject"].properties['FLT']
+       else:
+               props =  flt_properties.FLTLOD
+               
+       return props[prop]      
+
+def set_prop(typecode, prop, value):
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"],typecode):
+               state["activeObject"].properties['FLT'][prop] = value           
+
+
+
+def get_lockmask(mask):
+       global lodflag
+       state = update_state()
+       if state["activeObject"]:
+               flag = get_prop(73,lodflag)
+               if flag & mask:
+                       return True
+       return False    
+
+def set_lockmask(mask):
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"], 73):
+               oldvalue = state["activeObject"].properties['FLT'][lodflag]
+               oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0]
+               oldvalue |= mask
+               state["activeObject"].properties['FLT'][lodflag] = struct.unpack('>i', struct.pack(">I", oldvalue))[0]
+
+def clear_lockmask(mask):
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"], 73):
+               oldvalue = state["activeObject"].properties['FLT'][lodflag]
+               oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0]
+               oldvalue &= ~mask
+               state["activeObject"].properties['FLT'][lodflag] = struct.unpack('>i',struct.pack('>I',oldvalue))[0]    
+
+def findchildren(object):
+       state = update_state()
+       children = list()
+       for candidate in state["activeScene"].objects:
+               if candidate.parent == object:
+                       children.append(candidate)
+       retlist = list(children)
+       for child in children:
+               retlist = retlist + findchildren(child)
+       return retlist
+
+def get_object_center(object):
+       bbox = object.getBoundBox(1)
+       average = Blender.Mathutils.Vector(0.0, 0.0, 0.0)
+       
+       for point in bbox:
+               average[0] += point[0]
+               average[1] += point[1]
+               average[2] += point[2]
+       
+       average[0] = average[0] / 8.0
+       average[1] = average[1] / 8.0
+       average[2] = average[2] / 8.0
+       
+       return average
+       
+
+def calc_center():
+       
+       global xco
+       global yco
+       global zco
+       
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"], 73):
+               average = Blender.Mathutils.Vector(0.0, 0.0, 0.0)
+               children = findchildren(state["activeObject"]) #get children objects    
+               if children:
+                       for child in children:
+                               center = get_object_center(child)
+                               average[0] += center[0]
+                               average[1] += center[1]
+                               average[2] += center[2]
+                       
+                       average[0] = average[0] / len(children)
+                       average[1] = average[1] / len(children)
+                       average[2] = average[2] / len(children)
+                       
+               set_prop(73, xco, average[0])
+               set_prop(73, yco, average[1])
+               set_prop(73, zco, average[2])
+               
+
+def grab_center():
+       
+       global xco
+       global yco
+       global zco
+       
+       state = update_state()
+       if state["activeObject"] and idprops_type(state["activeObject"], 73):
+               center = Blender.Window.GetCursorPos()
+               
+               set_prop(73, xco, center[0])
+               set_prop(73, yco, center[1])
+               set_prop(73, zco, center[2])    
+
+
+def create_lod():
+       state = update_state()
+       actobj = state["activeObject"]
+       if actobj and not idprops_type(actobj, 73):
+               idprops_kill()
+               idprops_append(actobj,73, flt_properties.FLTLOD)
+               calc_center()
+
+       
+               
+def event(evt,val):
+       if evt == Draw.ESCKEY:
+               Draw.Exit()
+               
+def but_event(evt):
+
+       global LOD_MAKE
+       global LOD_DELETE
+       global LOD_CALC_CENTER
+       global LOD_GRAB_CENTER
+       global LOD_FREEZE
+       global LOD_PREVIOUS
+       global LOD_X
+       global LOD_Y
+       global LOD_Z
+       global LOD_SIG
+       global LOD_IN
+       global LOD_OUT
+       global LOD_TRANS
+       
+       global switch_in
+       global switch_out
+       global xco
+       global yco
+       global zco
+       global trans
+       global sig_size
+       
+       global lodflag
+       global previous_mask
+       global freeze_mask
+       
+       global evcode
+       
+       #do "system" events
+       if evt == evcode["LOD_MAKE"]:
+               create_lod()
+
+       if evt == evcode["LOD_CALC_CENTER"]:
+               calc_center()
+       
+       if evt == evcode["LOD_DELETE"]:
+               idprops_kill()
+       
+       if evt == evcode["LOD_GRAB_CENTER"]:
+               grab_center()
+
+       #do mask events
+       if evt == evcode["LOD_FREEZE"]:
+               if LOD_FREEZE.val == True:
+                       set_lockmask(freeze_mask)
+               else:
+                       clear_lockmask(freeze_mask)
+                       
+       if evt == evcode["LOD_PREVIOUS"]:
+               if LOD_PREVIOUS.val == True:
+                       set_lockmask(previous_mask)
+               else:
+                       clear_lockmask(previous_mask)
+                       
+       #do input events
+       if evt == evcode["LOD_X"]:
+               set_prop(73, xco, LOD_X.val)
+       if evt == evcode["LOD_Y"]:
+               set_prop(73, yco, LOD_Y.val)
+       if evt == evcode["LOD_Z"]:
+               set_prop(73, zco, LOD_Z.val)
+       if evt == evcode["LOD_SIG"]:
+               set_prop(73, sig_size, LOD_SIG.val)
+       if evt == evcode["LOD_IN"]:
+               set_prop(73, switch_in, LOD_IN.val)
+       if evt == evcode["LOD_OUT"]:
+               set_prop(73, switch_out, LOD_OUT.val)
+       if evt == evcode["LOD_TRANS"]:
+               set_prop(73, trans, LOD_TRANS.val)      
+                               
+
+       Draw.Redraw(1)
+       Blender.Window.RedrawAll()
+
+def draw_propsheet(x,y):
+
+       global LOD_MAKE
+       global LOD_DELETE
+       global LOD_CALC_CENTER
+       global LOD_GRAB_CENTER
+       global LOD_FREEZE
+       global LOD_PREVIOUS
+       global LOD_X
+       global LOD_Y
+       global LOD_Z
+       global LOD_SIG
+       global LOD_IN
+       global LOD_OUT
+       global LOD_TRANS
+
+       #labels
+       global LOD_EDITLABEL
+       global LOD_SWITCHLABEL
+       global LOD_CENTERLABEL
+       global LOD_XLABEL
+       global LOD_YLABEL
+       global LOD_ZLABEL
+       global LOD_SIGLABEL
+       global LOD_INLABEL
+       global LOD_OUTLABEL
+       global LOD_TRANSLABEL
+       
+       
+       global switch_in
+       global switch_out
+       global xco
+       global yco
+       global zco
+       global trans
+       global sig_size
+       
+       global lodflag
+       global previous_mask
+       global freeze_mask
+       
+       global evcode
+
+
+       global evcode
+       
+       state = update_state()
+
+       label_width = 100       
+       row_height = 20
+       toggle_width = 50
+       input_width = 100
+       pad = 10
+       origx = x
+       origy = (row_height * 16) + (pad * 16)
+
+
+       #editor label
+       x = origx
+       y = origy
+       LOD_EDITLABEL = Blender.Draw.Label("FLT Level of Detail Editor", x, y, 250, row_height)
+
+
+       #Center inputs
+       x = origx
+       y = y- (row_height + pad)
+       LOD_CENTERLABEL = Blender.Draw.Label("LOD center", x, y, label_width, row_height)
+       y = y- (row_height + pad)
+       LOD_XLABEL = Blender.Draw.Label("X Coordinate", x, y, label_width, row_height)
+       x = origx + (label_width + pad)
+       LOD_X = Blender.Draw.Number("", evcode["LOD_X"], x, y, input_width, row_height,get_prop(73,xco),  -1000000.0, 1000000.0, "")
+       x = origx
+       y = y- (row_height + pad)
+       LOD_YLABEL = Blender.Draw.Label("Y Coordinate", x, y, label_width, row_height)  
+       x = origx + (label_width + pad)
+       LOD_Y = Blender.Draw.Number("", evcode["LOD_Y"], x, y, input_width, row_height,get_prop(73,yco), -1000000.0,  1000000.0, "")
+       x = origx
+       y = y- (row_height + pad)
+       LOD_ZLABEL = Blender.Draw.Label("Z Coordinate", x, y, label_width, row_height)
+       x = origx + (label_width + pad)         
+       LOD_Z = Blender.Draw.Number("", evcode["LOD_Z"], x, y, input_width, row_height,get_prop(73,zco), -1000000.0, 1000000.0, "")
+
+
+       #Switch inputs
+       x = origx
+       y = y- (row_height + pad)
+       LOD_SWITCHLABEL = Blender.Draw.Label("Switch Settings", x, y, input_width, row_height)
+       y = y- (row_height + pad)
+       LOD_SIGLABEL = Blender.Draw.Label("Significant Size", x, y, label_width, row_height)
+       x = origx + (label_width + pad)
+       LOD_SIG = Blender.Draw.Number("", evcode["LOD_SIG"], x, y, input_width, row_height, get_prop(73,sig_size),  -1000000.0, 1000000.0, "")
+       x = origx
+       y = y- (row_height + pad)
+       LOD_INLABEL = Blender.Draw.Label("Switch In", x, y, label_width, row_height)
+       x = origx + (label_width + pad)
+       LOD_IN = Blender.Draw.Number("", evcode["LOD_IN"], x, y, input_width, row_height, get_prop(73,switch_in), -1000000.0, 1000000.0, "")
+       x = origx
+       y = y- (row_height + pad)
+       LOD_OUTLABEL = Blender.Draw.Label("Switch Out", x, y, label_width, row_height)  
+       x = origx + (label_width + pad)
+       LOD_OUT = Blender.Draw.Number("", evcode["LOD_OUT"], x, y, input_width, row_height, get_prop(73,switch_out), -1000000.0, 1000000.0, "")
+       x = origx
+       y = y- (row_height + pad)
+       LOD_TRANSLABEL = Blender.Draw.Label("Transition", x, y, label_width, row_height)                
+       x = origx + (label_width + pad)
+       LOD_TRANS = Blender.Draw.Number("", evcode["LOD_TRANS"], x, y, input_width, row_height, get_prop(73,trans), -1000000.0, 1000000.0, "")  
+
+
+       x = origx
+       y = y - (row_height + pad)      
+       LOD_MAKE = Blender.Draw.PushButton("Make LOD", evcode["LOD_MAKE"], x, y, input_width + label_width + pad, row_height, "Make a LOD Node out of Active Object")
+       y = y - (row_height + pad)      
+       LOD_DELETE = Blender.Draw.PushButton("Delete LOD", evcode["LOD_DELETE"], x, y, input_width + label_width + pad, row_height, "Delete the LOD Node properties")
+       y = y - (row_height + pad)
+       LOD_CALC_CENTER = Blender.Draw.PushButton("Calculate Center", evcode["LOD_CALC_CENTER"], x, y, input_width + label_width + pad, row_height, "Calculate the center of this LOD")
+       y = y - (row_height + pad)
+       LOD_GRAB_CENTER = Blender.Draw.PushButton("Grab Center", evcode["LOD_GRAB_CENTER"], x, y, input_width + label_width + pad, row_height, "Grab center from 3d cursor")
+       y = y - (row_height + pad)
+       LOD_FREEZE = Blender.Draw.Toggle("Freeze Center", evcode["LOD_FREEZE"], x, y, input_width + label_width + pad, row_height, get_lockmask(freeze_mask), "")
+       y = y - (row_height + pad)
+       LOD_PREVIOUS = Blender.Draw.Toggle("Previous Range", evcode["LOD_PREVIOUS"], x, y, input_width + label_width + pad, row_height, get_lockmask(previous_mask), "")
+
+def gui():
+       #draw the propsheet/toolbox.
+       psheety = 800
+       #psheetx = psheety + 10
+       draw_propsheet(20,psheety)
+
+Draw.Register(gui,event,but_event)
+       
\ No newline at end of file
index bc7c972ca6676fa9c549a56ab8e4db11471ba442..4c841e9c0c03b7d5b06a4e05ddd7b9b338d3979b 100644 (file)
@@ -197,7 +197,10 @@ def write_prop(fw,type,value,length):
        elif type == 'i':
                fw.write_int(value)
        elif type == 'I':
-               fw.write_uint(value)
+               #NOTE!:
+               #there is no unsigned int type in python, but we can only store signed ints in ID props
+               newvalue = struct.unpack('>I', struct.pack('>i', value))[0]
+               fw.write_uint(newvalue)
        elif type == 'd':
                fw.write_double(value)
        elif type == 'f':
@@ -267,16 +270,16 @@ FLTObjectDisplay = [10]
 FLTLOD = {
        '3t8!id' : 'L',
        '4i!reserved' : 0,
-       '5d!switch in' : 0,
-       '6d!switch out' : 0,
+       '5d!switch in' : 0.0,
+       '6d!switch out' : 0.0,
        '7s!sfx ID1' : 0,
        '8s!sfx ID2' : 0,
        '9I!flags' : 0,
-       '10d!X co' : 0,
-       '11d!Y co' : 0,
-       '12d!Z co' : 0,
-       '13d!Transition' : 0,
-       '14d!Sig Size' : 0
+       '10d!X co' : 0.0,
+       '11d!Y co' : 0.0,
+       '12d!Z co' : 0.0,
+       '13d!Transition' : 0.0,
+       '14d!Sig Size' : 0.0
 }
 FLTLODDisplay = [4]
 
index e1eb6718a3069e9d535c7b3f75ce97fe17b06555..e403fc33e068289008df363de47ddaa714b67a43 100644 (file)
@@ -41,7 +41,7 @@ struct ListBase;
 struct MemFile;
 
 #define BLENDER_VERSION                        247
-#define BLENDER_SUBVERSION             0
+#define BLENDER_SUBVERSION             1
 
 #define BLENDER_MINVERSION             245
 #define BLENDER_MINSUBVERSION  15
index 2966d932a49837151bd240eff57bc3ab123c6b25..c483148e4de4a3804ce2d01d6f965cb97a9388d9 100644 (file)
@@ -119,8 +119,10 @@ FaceCollPair;
 /////////////////////////////////////////////////
 // used in modifier.c from collision.c
 /////////////////////////////////////////////////
+
 BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon );
 void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving );
+
 /////////////////////////////////////////////////
 
 LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr );
@@ -133,6 +135,15 @@ void collision_move_object ( CollisionModifierData *collmd, float step, float pr
 void collisions_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 );
 void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 );
 
+/////////////////////////////////////////////////
+// used in effect.c
+/////////////////////////////////////////////////
+CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj);
+
+/////////////////////////////////////////////////
+
+
+
 /////////////////////////////////////////////////
 
 #endif
index 3b4c3198179c1467a80b80f80c4dc4270dde5138..6475f7a71ac12a5b7eb4db0f6b2d3f3e82d7ad14 100644 (file)
@@ -66,7 +66,7 @@ void                  pdEndEffectors(struct ListBase *lb);
 void                   pdDoEffectors(struct ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags);
 
 /* required for particle_system.c */
-void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise);
+void do_physical_effector(Object *ob, float *opco, short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, float charge, float pa_size);
 float effector_falloff(struct PartDeflect *pd, float *eff_velocity, float *vec_to_part);
 
 
index cfcab54058d02885b118712453ab23baec49c7c2..b5e09d551f038f371d2a6e180e9beef136cf1112 100644 (file)
 
 #include "BKE_cloth.h"
 
-#include "DNA_group_types.h"
-#include "DNA_object_types.h"
 #include "DNA_cloth_types.h"
+#include "DNA_group_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
 #include "DNA_scene_types.h"
 
 #include "BKE_DerivedMesh.h"
@@ -1307,9 +1308,34 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
        for ( base = G.scene->base.first; base; base = base->next )
        {
                coll_ob = base->object;
-               collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
-       
-               if ( !collmd )
+               
+               if(coll_ob->pd && coll_ob->pd->deflect)
+               {
+                       collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+               }
+               
+               if ( collmd )
+               {
+                       if(coll_ob == self)
+                               continue;
+                       
+                       if(numobj >= maxobj)
+                       {
+                               // realloc
+                               int oldmax = maxobj;
+                               CollisionModifierData **tmp;
+                               maxobj *= 2;
+                               tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
+                               memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax);
+                               MEM_freeN(objs);
+                               objs = tmp;
+                               
+                       }
+                       
+                       objs[numobj] = collmd;
+                       numobj++;
+               }
+               else
                {
                        if ( coll_ob->dup_group )
                        {
@@ -1319,8 +1345,12 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
                                for ( go= group->gobject.first; go; go= go->next )
                                {
                                        coll_ob = go->ob;
-
-                                       collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+                                       collmd = NULL;
+                                       
+                                       if(coll_ob->pd && coll_ob->pd->deflect)
+                                       {
+                                               collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+                                       }
 
                                        if ( !collmd )
                                                continue;
@@ -1347,27 +1377,6 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
                                        numobj++;
                                }
                        }
-               }
-               else
-               {
-                       if(coll_ob == self)
-                               continue;
-                       
-                       if(numobj >= maxobj)
-                       {
-                               // realloc
-                               int oldmax = maxobj;
-                               CollisionModifierData **tmp;
-                               maxobj *= 2;
-                               tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
-                               memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax);
-                               MEM_freeN(objs);
-                               objs = tmp;
-                               
-                       }
-                       
-                       objs[numobj] = collmd;
-                       numobj++;
                }       
        }
        *numcollobj = numobj;
@@ -1484,6 +1493,9 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f
                        BVHTreeOverlap *overlap = NULL;
                        int result = 0;
                        
+                       if(!collmd->bvhtree)
+                               continue;
+                       
                        /* move object to position (step) in time */
                        collision_move_object ( collmd, step + dt, step );
                        
index 7620edac126f77c1912efd6a83fb4d1ab10366b2..0842e55a0eaa51a7d829e1894f76156c61b06371 100644 (file)
@@ -59,6 +59,7 @@
 #include "BKE_armature.h"
 #include "BKE_bad_level_calls.h"
 #include "BKE_blender.h"
+#include "BKE_collision.h"
 #include "BKE_constraint.h"
 #include "BKE_deform.h"
 #include "BKE_depsgraph.h"
@@ -228,6 +229,60 @@ void pdEndEffectors(ListBase *lb)
 /*                     Effectors               */
 /************************************************/
 
+// triangle - ray callback function
+static void eff_tri_ray_hit(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{      
+       // whenever we hit a bounding box, we don't check further
+       hit->dist = -1;
+       hit->index = 1;
+}
+
+// get visibility of a wind ray
+static float eff_calc_visibility(Object *ob, float *co, float *dir)
+{
+       CollisionModifierData **collobjs = NULL;
+       int numcollobj = 0, i;
+       float norm[3], len = 0.0;
+       float visibility = 1.0;
+       
+       collobjs = get_collisionobjects(ob, &numcollobj);
+       
+       if(!collobjs)
+               return 0;
+       
+       VECCOPY(norm, dir);
+       VecMulf(norm, -1.0);
+       len = Normalize(norm);
+       
+       // check all collision objects
+       for(i = 0; i < numcollobj; i++)
+       {
+               CollisionModifierData *collmd = collobjs[i];
+               
+               if(collmd->bvhtree)
+               {
+                       BVHTreeRayHit hit;
+                       
+                       hit.index = -1;
+                       hit.dist = len + FLT_EPSILON;
+                       
+                       // check if the way is blocked
+                       if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, &hit, eff_tri_ray_hit, NULL)>=0)
+                       {
+                               // visibility is only between 0 and 1, calculated from 1-absorption
+                               visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01)));
+                               
+                               if(visibility <= 0.0f)
+                                       break;
+                       }
+               }
+       }
+       
+       MEM_freeN(collobjs);
+       
+       return visibility;
+}
+
 // noise function for wind e.g.
 static float wind_func(struct RNG *rng, float strength)
 {
@@ -277,7 +332,10 @@ float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part)
 {
        float eff_dir[3], temp[3];
        float falloff=1.0, fac, r_fac;
-       
+
+       if(pd->forcefield==PFIELD_LENNARDJ)
+               return falloff; /* Lennard-Jones field has it's own falloff built in */
+
        VecCopyf(eff_dir,eff_velocity);
        Normalize(eff_dir);
 
@@ -314,12 +372,18 @@ float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part)
        return falloff;
 }
 
-void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise)
+void do_physical_effector(Object *ob, float *opco, short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, float charge, float pa_size)
 {
        float mag_vec[3]={0,0,0};
        float temp[3], temp2[3];
        float eff_vel[3];
-       float wind = 0;
+       float noise = 0, visibility;
+       
+       // calculate visibility
+       visibility = eff_calc_visibility(ob, opco, vec_to_part);
+       if(visibility <= 0.0)
+               return;
+       falloff *= visibility;
 
        VecCopyf(eff_vel,eff_velocity);
        Normalize(eff_vel);
@@ -328,11 +392,11 @@ void do_physical_effector(short type, float force_val, float distance, float fal
                case PFIELD_WIND:
                        VECCOPY(mag_vec,eff_vel);
                        
-                       // add wind noise here
-                       if(noise> 0.0f)
-                               wind = wind_func(rng, noise);
-
-                       VecMulf(mag_vec,(force_val+wind)*falloff);
+                       // add wind noise here, only if we have wind
+                       if((noise_factor > 0.0f) && (force_val > FLT_EPSILON))
+                               noise = wind_func(rng, noise_factor);
+                       
+                       VecMulf(mag_vec,(force_val+noise)*falloff);
                        VecAddf(field,field,mag_vec);
                        break;
 
@@ -381,19 +445,46 @@ void do_physical_effector(short type, float force_val, float distance, float fal
                        VecMulf(mag_vec,damp*1.9f*(float)sqrt(force_val));
                        VecSubf(field,field,mag_vec);
                        break;
-               case PFIELD_NUCLEAR:
-                       /*pow here is root of cosine expression below*/
-                       //rad=(float)pow(2.0,-1.0/power)*distance/size;
-                       //VECCOPY(mag_vec,vec_to_part);
-                       //Normalize(mag_vec);
-                       //VecMulf(mag_vec,(float)cos(3.0*M_PI/2.0*(1.0-1.0/(pow(rad,power)+1.0)))/(rad+0.2f));
-                       //VECADDFAC(field,field,mag_vec,force_val);
+               case PFIELD_CHARGE:
+                       if(planar)
+                               Projf(mag_vec,vec_to_part,eff_vel);
+                       else
+                               VecCopyf(mag_vec,vec_to_part);
+
+                       VecMulf(mag_vec,charge*force_val*falloff);
+                       VecAddf(field,field,mag_vec);
                        break;
-       }
-}
+               case PFIELD_LENNARDJ:
+               {
+                       float fac;
+
+                       if(planar) {
+                               Projf(mag_vec,vec_to_part,eff_vel);
+                               distance = VecLength(mag_vec);
+                       }
+                       else
+                               VecCopyf(mag_vec,vec_to_part);
+
+                       /* at this distance the field is 60 times weaker than maximum */
+                       if(distance > 2.22 * (size+pa_size))
+                               break;
 
+                       fac = pow((size+pa_size)/distance,6.0);
+                       
+                       fac = - fac * (1.0 - fac) / distance;
 
+                       /* limit the repulsive term drastically to avoid huge forces */
+                       fac = ((fac>2.0) ? 2.0 : fac);
 
+                       /* 0.003715 is the fac value at 2.22 times (size+pa_size),
+                          substracted to avoid discontinuity at the border
+                       */
+                       VecMulf(mag_vec, force_val * (fac-0.0037315));
+                       VecAddf(field,field,mag_vec);
+                       break;
+               }
+       }
+}
 
 /*  -------- pdDoEffectors() --------
     generic force/speed system, now used for particles and softbodies
@@ -451,16 +542,16 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float
                VecSubf(vec_to_part, opco, ob->obmat[3]);
                distance = VecLength(vec_to_part);
 
-               falloff=effector_falloff(pd,ob->obmat[2],vec_to_part);
-
+               falloff=effector_falloff(pd,ob->obmat[2],vec_to_part);          
+               
                if(falloff<=0.0f)
                        ;       /* don't do anything */
                else {
                        float field[3]={0,0,0}, tmp[3];
                        VECCOPY(field, force);
-                       do_physical_effector(pd->forcefield,pd->f_strength,distance,
+                       do_physical_effector(ob, opco, pd->forcefield,pd->f_strength,distance,
                                                                falloff,pd->f_dist,pd->f_damp,ob->obmat[2],vec_to_part,
-                                                               speed,force,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise);
+                                                               speed,force,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise, 0.0f, 0.0f);
                        
                        // for softbody backward compatibility
                        if(flags & PE_WIND_AS_SPEED){
index 0375ab22909708cd0d6e53a1076548067a2befc8..93e35a4db061b3906ae0070f1eb553acdaa201a9 100644 (file)
@@ -1451,7 +1451,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec
                        float triunnormal[3]={0,0,0}; // not-normalized-triangle normal
                        float tmp[3]={0,0,0};
                        float factor = (mfaces[i].v4) ? 0.25 : 1.0 / 3.0;
-                       factor *= 0.05;
+                       factor *= 0.02;
                        
                        // calculate face normal
                        if(mfaces[i].v4)
index fe92edfbbd5eaeeabccb59c0749f84fbf0714f4d..4af25ee99e713d14c7796ec55cb579476a2f59ae 100644 (file)
@@ -182,7 +182,7 @@ int part_ar[PART_TOTIPO]= {
        PART_EMIT_FREQ, PART_EMIT_LIFE, PART_EMIT_VEL, PART_EMIT_AVE, PART_EMIT_SIZE,
        PART_AVE, PART_SIZE, PART_DRAG, PART_BROWN, PART_DAMP, PART_LENGTH, PART_CLUMP,
     PART_GRAV_X, PART_GRAV_Y, PART_GRAV_Z, PART_KINK_AMP, PART_KINK_FREQ, PART_KINK_SHAPE,
-       PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD
+       PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD, PART_PD2_FSTR, PART_PD2_FFALL, PART_PD2_FMAXD
 };
 
 
@@ -1614,6 +1614,12 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
                        poin= (part->pd?(&(part->pd->f_power)):NULL); break;
                case PART_PD_FMAXD:
                        poin= (part->pd?(&(part->pd->maxdist)):NULL); break;
+               case PART_PD2_FSTR:
+                       poin= (part->pd2?(&(part->pd2->f_strength)):NULL); break;
+               case PART_PD2_FFALL:
+                       poin= (part->pd2?(&(part->pd2->f_power)):NULL); break;
+               case PART_PD2_FMAXD:
+                       poin= (part->pd2?(&(part->pd2->maxdist)):NULL); break;
                }
        }
 
index d08f30ff9952ab8fedf324dd59cfc2f544048745..f33f33d9d46d8a407e3fcb9b6aa4f43cf21c4cd8 100644 (file)
@@ -5496,7 +5496,7 @@ static void collisionModifier_deformVerts(
                
                numverts = dm->getNumVerts ( dm );
                
-               if(current_time > collmd->time)
+               if((current_time > collmd->time)|| (BKE_ptcache_get_continue_physics()))
                {       
                        // check if mesh has changed
                        if(collmd->x && (numverts != collmd->numverts))
index 643f90637ad7c034d16ef5772629ecf6c702b491..2f4696fc442189c373c8d00bcdd12bc4d4680713 100644 (file)
@@ -320,8 +320,14 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
 /************************************************/
 void psys_free_settings(ParticleSettings *part)
 {
-       if(part->pd)
+       if(part->pd) {
                MEM_freeN(part->pd);
+               part->pd = NULL;
+       }
+       if(part->pd2) {
+               MEM_freeN(part->pd2);
+               part->pd2 = NULL;
+       }
 }
 
 void free_hair(ParticleSystem *psys, int softbody)
@@ -3015,6 +3021,7 @@ ParticleSettings *psys_copy_settings(ParticleSettings *part)
        
        partn= copy_libblock(part);
        if(partn->pd) partn->pd= MEM_dupallocN(part->pd);
+       if(partn->pd2) partn->pd2= MEM_dupallocN(part->pd2);
        
        return partn;
 }
index 60fdbca20219223ecb5cd1bbad69659250b8cde0..ef8373ee977f7e34f1c24e3bc37a64ebf77bed6b 100644 (file)
@@ -60,6 +60,7 @@
 #include "BKE_bad_level_calls.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_displist.h"
+#include "BKE_effect.h"
 #include "BKE_particle.h"
 #include "BKE_global.h"
 #include "BKE_utildefines.h"
@@ -2205,6 +2206,9 @@ static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra)
        return 1;
 }
 
+/************************************************/
+/*                     Effectors                                                       */
+/************************************************/
 static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, short object, float *pa_co, float obmat[4][4], float force_val, float falloff, float *field)
 {
        TexResult result[4];
@@ -2322,10 +2326,11 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy
 
                for(i=0; epsys; epsys=epsys->next,i++){
                        type=0;
-                       if(epsys!=psys){
+                       if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){
                                epart=epsys->part;
 
-                               if(epsys->part->pd && epsys->part->pd->forcefield)
+                               if((epsys->part->pd && epsys->part->pd->forcefield)
+                                       || (epsys->part->pd2 && epsys->part->pd2->forcefield))
                                        type=PSYS_EC_PARTICLE;
 
                                if(epart->type==PART_REACTOR) {
@@ -2574,35 +2579,31 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
        ListBase *lb=&psys->effectors;
        ParticleEffectorCache *ec;
        float distance, vec_to_part[3];
-       float falloff;
+       float falloff, charge = 0.0f;
        int p;
 
        /* check all effector objects for interaction */
        if(lb->first){
+               if(psys->part->pd && psys->part->pd->forcefield==PFIELD_CHARGE){
+                       /* Only the charge of the effected particle is used for 
+                          interaction, not fall-offs. If the fall-offs aren't the      
+                          same this will be unphysical, but for animation this         
+                          could be the wanted behavior. If you want physical
+                          correctness the fall-off should be spherical 2.0 anyways.
+                        */
+                       charge = psys->part->pd->f_strength;
+               }
+               if(psys->part->pd2 && psys->part->pd2->forcefield==PFIELD_CHARGE){
+                       charge += psys->part->pd2->f_strength;
+               }
                for(ec = lb->first; ec; ec= ec->next){
                        eob= ec->ob;
                        if(ec->type & PSYS_EC_EFFECTOR){
                                pd=eob->pd;
                                if(psys->part->type!=PART_HAIR && psys->part->integrator)
                                        where_is_object_time(eob,cfra);
-                               /* Get IPO force strength and fall off values here */
-                               //if (has_ipo_code(eob->ipo, OB_PD_FSTR))
-                               //      force_val = IPO_GetFloatValue(eob->ipo, OB_PD_FSTR, cfra);
-                               //else 
-                               //      force_val = pd->f_strength;
-                               
-                               //if (has_ipo_code(eob->ipo, OB_PD_FFALL)) 
-                               //      ffall_val = IPO_GetFloatValue(eob->ipo, OB_PD_FFALL, cfra);
-                               //else 
-                               //      ffall_val = pd->f_power;
-
-                               //if (has_ipo_code(eob->ipo, OB_PD_FMAXD)) 
-                               //      maxdist = IPO_GetFloatValue(eob->ipo, OB_PD_FMAXD, cfra);
-                               //else 
-                               //      maxdist = pd->maxdist;
 
                                /* use center of object for distance calculus */
-                               //obloc= eob->obmat[3];
                                VecSubf(vec_to_part, state->co, eob->obmat[3]);
                                distance = VecLength(vec_to_part);
 
@@ -2615,22 +2616,22 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                                                                        pd->flag & PFIELD_TEX_OBJECT, (pd->flag & PFIELD_TEX_ROOTCO) ? rootco : state->co, eob->obmat,
                                                                        pd->f_strength, falloff, force_field);
                                } else {
-                                       do_physical_effector(pd->forcefield,pd->f_strength,distance,
-                                                                               falloff,pd->f_dist,pd->f_damp,eob->obmat[2],vec_to_part,
-                                                                               pa->state.vel,force_field,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise);
+                                       do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance,
+                                                                               falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part,
+                                                                               pa->state.vel,force_field,pd->flag&PFIELD_PLANAR,pd->rng,pd->f_noise,charge,pa->size);
                                }
                        }
                        if(ec->type & PSYS_EC_PARTICLE){
-                               int totepart;
+                               int totepart, i;
                                epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr);
                                epart= epsys->part;
-                               pd= epart->pd;
+                               pd=epart->pd;
                                totepart= epsys->totpart;
                                
                                if(totepart <= 0)
                                        continue;
                                
-                               if(pd->forcefield==PFIELD_HARMONIC){
+                               if(pd && pd->forcefield==PFIELD_HARMONIC){
                                        /* every particle is mapped to only one harmonic effector particle */
                                        p= pa_no%epsys->totpart;
                                        totepart= p+1;
@@ -2642,31 +2643,27 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                                epsys->lattice=psys_get_lattice(ob,psys);
 
                                for(; p<totepart; p++){
+                                       /* particle skips itself as effector */
+                                       if(epsys==psys && p == pa_no) continue;
+
                                        epa = epsys->particles + p;
                                        estate.time=-1.0;
                                        if(psys_get_particle_state(eob,epsys,p,&estate,0)){
                                                VECSUB(vec_to_part, state->co, estate.co);
                                                distance = VecLength(vec_to_part);
-
-                                               //if(pd->forcefield==PFIELD_HARMONIC){
-                                               //      //if(cfra < epa->time + radius){ /* radius is fade-in in ui */
-                                               //      //      eforce*=(cfra-epa->time)/radius;
-                                               //      //}
-                                               //}
-                                               //else{
-                                               //      /* Limit minimum distance to effector particle so that */
-                                               //      /* the force is not too big */
-                                               //      if (distance < 0.001) distance = 0.001f;
-                                               //}
                                                
-                                               falloff=effector_falloff(pd,estate.vel,vec_to_part);
+                                               for(i=0, pd = epart->pd; i<2; i++,pd = epart->pd2) {
+                                                       if(pd==NULL || pd->forcefield==0) continue;
 
-                                               if(falloff<=0.0f)
-                                                       ;       /* don't do anything */
-                                               else
-                                                       do_physical_effector(pd->forcefield,pd->f_strength,distance,
-                                                       falloff,epart->size,pd->f_damp,estate.vel,vec_to_part,
-                                                       state->vel,force_field,0, pd->rng, pd->f_noise);
+                                                       falloff=effector_falloff(pd,estate.vel,vec_to_part);
+
+                                                       if(falloff<=0.0f)
+                                                               ;       /* don't do anything */
+                                                       else
+                                                               do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance,
+                                                               falloff,epart->size,pd->f_damp,estate.vel,vec_to_part,
+                                                               state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size);
+                                               }
                                        }
                                        else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){
                                                /* first step after key release */
index 9d7a0302d459a439da4899358040c87ec7c29400..35ca42a494905b3b29ff9ecc1ec90d6ae56a594b 100644 (file)
@@ -2589,6 +2589,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
 static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
 {
        part->pd= newdataadr(fd, part->pd);
+       part->pd2= newdataadr(fd, part->pd2);
 }
 
 static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles)
index b462233528aa5b10016dc9f2e4e9eb2162d6b347..d596f57990f0b1f22279776340325cf655a70387 100644 (file)
@@ -535,6 +535,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
                        writestruct(wd, ID_PA, "ParticleSettings", 1, part);
                        if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
                        writestruct(wd, DATA, "PartDeflect", 1, part->pd);
+                       writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
                }
                part= part->id.next;
        }
index df514190270acb8b7d95e9aac3ecb5fec1be0f62..0d27804dd1a6d574b5e8c93a5181151facd76a93 100644 (file)
@@ -524,6 +524,10 @@ enum {
        
        TH_EDGE_SHARP,
        TH_EDITMESH_ACTIVE,
+
+       TH_HANDLE_VERTEX,
+       TH_HANDLE_VERTEX_SELECT,
+       TH_HANDLE_VERTEX_SIZE,
 };
 /* XXX WARNING: previous is saved in file, so do not change order! */
 
index 03ffef3cd55e3e91dbd024146a39b9d0935d9eab..1e30f3f7640a2b0eaebd95b184a4064667162c10 100644 (file)
@@ -354,8 +354,8 @@ typedef short IPO_Channel;
 
 /* ******************** */
 /* particle ipos */
-#define PART_TOTIPO            22
-#define PART_TOTNAM            22
+#define PART_TOTIPO            25
+#define PART_TOTNAM            25
 
 #define PART_EMIT_FREQ 1
 #define PART_EMIT_LIFE 2
@@ -385,6 +385,10 @@ typedef short IPO_Channel;
 #define PART_PD_FFALL  21
 #define PART_PD_FMAXD  22
 
+#define PART_PD2_FSTR  23
+#define PART_PD2_FFALL 24
+#define PART_PD2_FMAXD 25
+
 
 /* these are IpoCurve specific */
 /* **************** IPO ********************* */
index 9ce04c1c27217b18a46b8bd1d633404a5c7e1283..0f820e8854120519717722f1dab86f5a6a0b6cbb 100644 (file)
@@ -392,7 +392,8 @@ typedef struct CollisionModifierData {
        
        unsigned int numverts;
        unsigned int numfaces;
-       int pad;
+       short absorption; /* used for forces, in % */
+       short pad;
        float time;             /* cfra time of modifier */
        struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
 } CollisionModifierData;
index 5f6ae7c7f06922c00f2e0030434f4cbe08f76b75..5900e16d5e804f7a3e7420f8fac9b48e719bef6c 100644 (file)
@@ -156,8 +156,8 @@ typedef struct SoftBody {
 #define PFIELD_GUIDE   5
 #define PFIELD_TEXTURE 6
 #define PFIELD_HARMONIC        7
-#define PFIELD_NUCLEAR 8
-#define PFIELD_MDIPOLE 9
+#define PFIELD_CHARGE  8
+#define PFIELD_LENNARDJ        9
 
 
 /* pd->flag: various settings */
index 4f62cd084cc9b0ca0095635d1ab4d3276ea15bb5..363f0075e23f20513446ee353d28313b418fc908 100644 (file)
@@ -166,6 +166,7 @@ typedef struct ParticleSettings {
        struct Object *bb_ob;
        struct Ipo *ipo;
        struct PartDeflect *pd;
+       struct PartDeflect *pd2;
 } ParticleSettings;
 
 typedef struct ParticleSystem{                         /* note, make sure all (runtime) are NULL's in copy_particlesystem */
@@ -264,6 +265,8 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 #define PART_CHILD_RENDER      (1<<29)
 #define PART_CHILD_GUIDE       (1<<30)
 
+#define PART_SELF_EFFECT       (1<<22)
+
 /* part->rotfrom */
 #define PART_ROT_KEYS          0       /* interpolate directly from keys */
 #define PART_ROT_ZINCR         1       /* same as zdir but done incrementally from previous position */
index cd1c047dac9a24e8b87510ea2ebe759174b6d488..856324695a9bb9cef32f825fb53ca2e06b86a011 100644 (file)
@@ -101,6 +101,11 @@ typedef struct ThemeSpace {
        char movie[4], image[4], scene[4], audio[4];            // for sequence editor
        char effect[4], plugin[4], transition[4], meta[4];
        char editmesh_active[4]; 
+
+       char handle_vertex[4];
+       char handle_vertex_select[4];
+       char handle_vertex_size;
+       char hpad[7];
 } ThemeSpace;
 
 
index ccd24a437b5e8edd801b5774ce8150a73673e2e9..20747a167e695b0722c1b932f8a5a5e6af5f2e6c 100644 (file)
@@ -554,6 +554,7 @@ static int Material_setSssTexScatter( BPy_Material * self, PyObject * value );
 static int Material_setSssFront( BPy_Material * self, PyObject * value );
 static int Material_setSssBack( BPy_Material * self, PyObject * value );
 static int Material_setSssBack( BPy_Material * self, PyObject * value );
+static int Material_setTexChannel( BPy_Material * self, PyObject * value );
 
 static PyObject *Material_getColorComponent( BPy_Material * self,
                                                        void * closure );
@@ -633,6 +634,7 @@ static PyObject *Material_getSssBack( BPy_Material * self );
 static PyObject *Material_getFilter( BPy_Material * self );
 static PyObject *Material_getTranslucency( BPy_Material * self );
 static PyObject *Material_getTextures( BPy_Material * self );
+static PyObject *Material_getTexChannel( BPy_Material * self );
 static PyObject *Material_clearIpo( BPy_Material * self );
 
 static PyObject *Material_setTexture( BPy_Material * self, PyObject * args );
@@ -1140,7 +1142,11 @@ static PyGetSetDef BPy_Material_getseters[] = {
         NULL},
        {"lightGroup",
         (getter)Material_getLightGroup, (setter)Material_setLightGroup,
-        "Set the light group for this material",
+        "The light group for this material",
+        NULL},
+       {"enabledTextures",
+        (getter)Material_getTexChannel, (setter)Material_setTexChannel,
+        "Enabled texture channels for this material",
         NULL},
        {"R",
         (getter)Material_getColorComponent, (setter)Material_setColorComponent,
@@ -1517,6 +1523,36 @@ static PyObject *Material_getLightGroup( BPy_Material * self )
        return Group_CreatePyObject( self->material->group );
 }
 
+static PyObject *Material_getTexChannel( BPy_Material * self )
+{
+       int i;
+    short mask = 1;
+       PyObject *list = PyList_New(0);
+       if( !list )
+               return EXPP_ReturnPyObjError( PyExc_MemoryError,
+                               "PyList_New() failed" );
+
+       for( i = 0, mask = 1; i < MAX_MTEX ; ++i, mask <<= 1 ) {
+               if( self->material->mtex[i] && (mask & self->material->septex) == 0 ) {
+                       PyObject * val = PyInt_FromLong(i);
+                       if( !val ) {
+                               Py_DECREF( list );
+                               return EXPP_ReturnPyObjError( PyExc_MemoryError,
+                                               "PyInt_FromLong() failed" );
+                       }
+                       if( PyList_Append( list, val ) < 0 ) {
+                               Py_DECREF( val );
+                               Py_DECREF( list );
+                               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                                               "PyList_Append() failed" );
+                       }
+                       Py_DECREF( val );
+               }
+       }
+
+       return list;
+}
+
 static PyObject *Material_getHaloSize( BPy_Material * self )
 {
        return PyFloat_FromDouble( ( double ) self->material->hasize );
@@ -1982,6 +2018,57 @@ static int Material_setLightGroup( BPy_Material * self, PyObject * value )
        return GenericLib_assignData(value, (void **) &self->material->group, NULL, 1, ID_GR, 0);
 }
 
+static int Material_setTexChannel( BPy_Material * self, PyObject * value )
+{
+       int i, mask;
+       short septex = 0;
+       int result = 1;
+
+       /* fail if input is not a standard sequence */
+       if( !PyList_Check( value ) && !PyTuple_Check( value ) )
+               return EXPP_ReturnIntError( PyExc_TypeError,
+                                               "expected tuple or list of integers" );
+
+       /* get a fast sequence; in Python 2.5, this just return the original
+        * list or tuple and INCREFs it, so we must DECREF */
+       value = PySequence_Fast( value, "" );
+
+       /* set the disable bit for each existing texture */
+       for( i= 0, mask= 1; i < MAX_MTEX; ++i, mask <<= 1 )
+               if( self->material->mtex[i] != NULL )
+                       septex |= mask;
+
+       /* check the list, and build new septex value */
+       for( i= PySequence_Size(value)-1; i >= 0; --i ) {
+               long ival;
+               PyObject *item = PySequence_Fast_GET_ITEM( value, i );
+               if( !PyInt_Check( item ) ) {
+                       PyErr_SetString ( PyExc_TypeError,
+                                       "expected tuple or list of integers" );
+                       goto exit;
+               }
+               ival= PyInt_AsLong( item );
+               if(ival < 0 || ival > MAX_MTEX) {
+                       PyErr_SetString( PyExc_ValueError,
+                                                       "channel value out of range" );
+                       goto exit;
+               }
+               ival&= (1<<MAX_MTEX)-1;
+               if( self->material->mtex[(int)ival] == NULL ) {
+                       PyErr_SetString( PyExc_ValueError,
+                                                       "channels must have a texture assigned" );
+                       goto exit;
+               }
+               septex&= ~(1<<ival);
+       }
+       self->material->septex= septex;
+       result = 0;
+
+exit:
+       Py_DECREF(value);
+       return result;
+}
+
 static int Material_setAdd( BPy_Material * self, PyObject * value )
 {
        return EXPP_setFloatClamped ( value, &self->material->add,
@@ -2313,9 +2400,6 @@ static int Material_setSssBack( BPy_Material * self, PyObject * value )
                                                                EXPP_MAT_SSS_BACK_MAX);
 }
 
-
-
-
 static PyObject *Material_setTexture( BPy_Material * self, PyObject * args )
 {
        int texnum;
index 9f68287d658d96d91224595a84bbb9c9863f6f37..b3e8fefdb7be704cf00461797df6e4abb3fab27f 100644 (file)
@@ -5381,11 +5381,11 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args )
        if( PySequence_Size( args ) != 2 ||
                        !PyArg_ParseTuple( args, "iO", &edge_also, &args ) )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
-                               "expected and int and a sequence of ints or MFaces" );
+                               "expected an int and a sequence of ints or MFaces" );
 
        if( !PyList_Check( args ) && !PyTuple_Check( args ) )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
-                               "expected and int and a sequence of ints or MFaces" );
+                               "expected an int and a sequence of ints or MFaces" );
 
        /* see how many args we need to parse */
        len = PySequence_Size( args );
index 45cce46d389688ce177117d17d7d8def42283bf0..dc70921492c73c23a886466f9acbd1a3b34234ba 100644 (file)
@@ -204,6 +204,7 @@ enum obj_consts {
        EXPP_OBJ_ATTR_SB_INSPRING,
        EXPP_OBJ_ATTR_SB_INFRICT,
 
+       EXPP_OBJ_ATTR_EMPTY_DRAWTYPE
 };
 
 #define EXPP_OBJECT_DRAWSIZEMIN         0.01f
@@ -2431,6 +2432,12 @@ static int Object_setDrawType( BPy_Object * self, PyObject * value )
                        OB_BOUNDBOX, OB_TEXTURE, 'b' );
 }
 
+static int Object_setEmptyShape( BPy_Object * self, PyObject * value )
+{
+       return EXPP_setIValueRange( value, &self->object->empty_drawtype,
+                       OB_ARROWS, OB_EMPTY_CONE, 'b' );
+}
+
 static int Object_setEuler( BPy_Object * self, PyObject * args )
 {
        float rot1, rot2, rot3;
@@ -3758,6 +3765,9 @@ static PyObject *getIntAttr( BPy_Object *self, void *type )
        case EXPP_OBJ_ATTR_DRAWTYPE:
                param = object->dt;
                break;
+       case EXPP_OBJ_ATTR_EMPTY_DRAWTYPE:
+               param = object->empty_drawtype;
+               break;
        case EXPP_OBJ_ATTR_PARENT_TYPE:
                param = object->partype;
                break;
@@ -4938,6 +4948,10 @@ static PyGetSetDef BPy_Object_getseters[] = {
         (getter)getIntAttr, (setter)Object_setDrawType,
         "The object's drawing type",
         (void *)EXPP_OBJ_ATTR_DRAWTYPE},
+       {"emptyShape",
+        (getter)getIntAttr, (setter)Object_setEmptyShape,
+        "The empty's drawing shape",
+        (void *)EXPP_OBJ_ATTR_EMPTY_DRAWTYPE},
        {"parentType",
         (getter)getIntAttr, (setter)NULL,
         "The object's parent type",
@@ -5538,6 +5552,24 @@ static PyObject *M_Object_IpoKeyTypesDict( void )
        return M;
 }
 
+static PyObject *M_Object_EmptyShapesDict( void )
+{
+       PyObject *M = PyConstant_New(  );
+
+       if( M ) {
+               BPy_constant *d = ( BPy_constant * ) M;
+               PyConstant_Insert( d, "ARROWS", PyInt_FromLong( OB_ARROWS ) );
+               PyConstant_Insert( d, "AXES", PyInt_FromLong( OB_PLAINAXES ) );
+               PyConstant_Insert( d, "CIRCLE", PyInt_FromLong( OB_CIRCLE ) );
+               PyConstant_Insert( d, "ARROW", PyInt_FromLong( OB_SINGLE_ARROW ) );
+               PyConstant_Insert( d, "CUBE", PyInt_FromLong( OB_CUBE ) );
+               PyConstant_Insert( d, "SPHERE", PyInt_FromLong( OB_EMPTY_SPHERE ) );
+               PyConstant_Insert( d, "CONE", PyInt_FromLong( OB_EMPTY_CONE ) );
+       }
+       return M;
+}
+
+
 /*****************************************************************************/
 /* Function:    initObject                                             */
 /*****************************************************************************/
@@ -5552,6 +5584,7 @@ PyObject *Object_Init( void )
        PyObject *RBFlagsDict = M_Object_RBFlagsDict( );
        PyObject *RBShapesDict = M_Object_RBShapeBoundDict( );
        PyObject *IpoKeyTypesDict = M_Object_IpoKeyTypesDict( );
+       PyObject *EmptyShapesDict = M_Object_EmptyShapesDict( );
 
        PyType_Ready( &Object_Type ) ;
 
@@ -5596,7 +5629,9 @@ PyObject *Object_Init( void )
        if( RBShapesDict )
                PyModule_AddObject( module, "RBShapes", RBShapesDict );
        if( IpoKeyTypesDict )
-               PyModule_AddObject( module, "IpoKeyTypes", IpoKeyTypesDict );   
+               PyModule_AddObject( module, "IpoKeyTypes", IpoKeyTypesDict );
+       if( EmptyShapesDict )
+               PyModule_AddObject( module, "EmptyShapes", EmptyShapesDict );
 
                /*Add SUBMODULES to the module*/
        dict = PyModule_GetDict( module ); /*borrowed*/
index a3496164cd19b9abe5fc6894a7b1e3dfdbe84c6f..02f7edd77f533d5fdb7132670e10ed763a96cfd6 100644 (file)
@@ -323,6 +323,21 @@ class Material:
        each color a list of 5 floats [0 - 1], [r,g,b,a,pos].
        The colorband can have between 1 and 31 colors.
        @type colorbandSpecular:  list
+       @type enabledTextures: list of integers
+       @ivar enabledTextures: The texture channels enabled in this material.
+               The attribute returns is list of integers in the range [0, 9], each
+               number representing the respective enabled MTex entry (see
+               L{getTextures()<getTextures>}).  Enabling is done by assigning
+               a list of ints or an empty list.  Attempting to enable a channel
+               which does not have a texture assigned to it will result in a
+               ValueError exception.
+               Example::
+                       mat.enabledTextures = []  # no texture channels are enabled
+                       mat.enabledTextures = [0, 6] # texture channels 0 and 6 are enabled
+                       ch = mat.enabledTextures
+                       ch.append(4)
+                       mat.enabledTextures = ch
+                       print mat.enabledTextures # will print: [0, 4, 6]
        
        @ivar enableSSS:  If True, subsurface scattering will be rendered on this material.
        @type enableSSS:  bool
@@ -1010,7 +1025,7 @@ class Material:
 
        def setTexture(index, texture, texco, mapto):
                """
-               Assign a Blender Texture object to slot number 'number'.
+               Assign a Blender Texture object to channel number 'number'.
                @type index: int
                @param index: material's texture index in [0, 9].
                @type texture: Blender Texture
@@ -1033,7 +1048,7 @@ class Material:
                Get this Material's Texture list.
                @rtype: list of MTex
                @return: a list of Blender MTex objects.  None is returned for each empty
-                               texture slot.
+                               texture channel.
                """
 
        def getScriptLinks (event):
index 2e4850aeb14985f88959d6c455b15de7a6fa1cd1..07942d580937c46b0954fa14fd8a2f6333160812 100644 (file)
@@ -117,6 +117,10 @@ Example::
        attribute.  Only one type can be selected at a time.  Values are
        BOX, SPHERE, CYLINDER, CONE, and POLYHEDERON
 
+@type EmptyShapes: readonly dictionary
+@var EmptyShapes: Constant dict used for with L{Object.emptyShape} attribute.
+       Only one type can be selected at a time. Values are
+       ARROW, ARROWS, AXES, CIRCLE, CONE, CUBE AND SPHERE
 """
 
 def New (type, name='type'):
@@ -347,7 +351,7 @@ class Object:
                        ob.layers = []  # object won't be visible
                        ob.layers = [1, 4] # object visible only in layers 1 and 4
                        ls = o.layers
-                       ls.append([10])
+                       ls.append(10)
                        o.layers = ls
                        print ob.layers # will print: [1, 4, 10]
                B{Note}: changes will only be visible after the screen (at least
@@ -525,6 +529,8 @@ class Object:
        @ivar drawType: The object's drawing type.
                See L{DrawTypes} constant dict for values.
        @type drawType: int
+       @ivar emptyShape: The empty drawing shape.
+               See L{EmptyShapes} constant dict for values.
        @ivar parentType: The object's parent type.  Read-only.
                See L{ParentTypes} constant dict for values.
        @type parentType: int
index 132bae8b7b873d2aba2fa6796d63956917232665..78f19ad06080d71e2c2021caa1eb38cfe65b7f7f 100644 (file)
@@ -3320,6 +3320,8 @@ static void object_panel_collision(Object *ob)
                uiDefBut(block, LABEL, 0, "",160,160,150,2, NULL, 0.0, 0, 0, 0, "");
                
                if(pd->deflect) {
+                       CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType ( ob, eModifierType_Collision );
+                       
                        uiDefBut(block, LABEL, 0, "Particle Interaction",                       10,135,310,20, NULL, 0.0, 0, 0, 0, "");
 
                        uiBlockBeginAlign(block);
@@ -3335,12 +3337,18 @@ static void object_panel_collision(Object *ob)
                        uiDefBut(block, LABEL, 0, "Soft Body and Cloth Interaction",                    10,65,310,20, NULL, 0.0, 0, 0, 0, "");
 
                        uiBlockBeginAlign(block);
-                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:",       10,45,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during collision");
-                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Inner:", 10,25,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness");
-                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Outer:", 10, 5,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness");
+                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Inner:", 10,45,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness");
+                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Outer:", 160, 45,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness");
                        uiBlockEndAlign(block);
+                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:",       10,25,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during collision");
 
-                       uiDefButBitS(block, TOG, OB_SB_COLLFINAL, B_FIELD_CHANGE, "Ev.M.Stack", 170,45,150,20, &ob->softflag, 0, 0, 0, 0, "Pick collision object from modifier stack (softbody only)");
+                       uiDefButBitS(block, TOG, OB_SB_COLLFINAL, B_FIELD_CHANGE, "Ev.M.Stack", 160,25,150,20, &ob->softflag, 0, 0, 0, 0, "Pick collision object from modifier stack (softbody only)");
+                       
+                       // collision options
+                       if(collmd)
+                       {
+                               uiDefButS(block, NUM, B_FIELD_CHANGE, "Absorption: ",   10,0,150,20, &collmd->absorption, 0.0, 100, 1, 2, "How much of effector force gets lost during collision with this object (in percent).");
+                       }
                }
        }
 }
@@ -3350,6 +3358,7 @@ static void object_panel_fields(Object *ob)
        uiBut *but;
        int particles=0;
        static short actpsys=-1;
+       static char slot=0;
 
        block= uiNewBlock(&curarea->uiblocks, "object_panel_fields", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "Fields", "Physics", 0, 0, 318, 204)==0) return;
@@ -3371,7 +3380,7 @@ static void object_panel_fields(Object *ob)
                char *tipstr="Choose field type";
 
                uiBlockBeginAlign(block);
-               
+
                if(ob->particlesystem.first) {
                        ParticleSystem *psys;
                        char *menustr2= psys_menu_string(ob,1);
@@ -3383,8 +3392,16 @@ static void object_panel_fields(Object *ob)
                                if(psys->part->pd==NULL)
                                        psys->part->pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
 
-                               pd= psys->part->pd;
+                               if(psys->part->pd2==NULL)
+                                       psys->part->pd2= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
+
+                               pd= ((slot==1) ? psys->part->pd2 : psys->part->pd);
                                particles=1;
+
+                               uiDefButC(block, ROW, B_REDR, "",       10, 163, 14, 14, &slot, 3.0, 0, 0, 0, "Edit first particle effector slot");
+                               uiDefButC(block, ROW, B_REDR, "",       24, 163, 14, 14, &slot, 3.0, 1, 0, 0, "Edit second particle effector slot");
+                               uiBlockEndAlign(block);
+                               uiBlockBeginAlign(block);
                        }
                        else
                                actpsys= -1; /* -1 = object */
@@ -3397,8 +3414,8 @@ static void object_panel_fields(Object *ob)
 
                /* setup menu button */
                if(particles){
-                       sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d", 
-                                       PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC);
+                       sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
+                                       PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_CHARGE, PFIELD_LENNARDJ);
 
                        if(pd->forcefield==PFIELD_FORCE) tipstr= "Particle attracts or repels particles (On shared object layers)";
                        else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of particle Z axis (On shared object layers)";
@@ -3406,11 +3423,11 @@ static void object_panel_fields(Object *ob)
                }
                else{
                        if(ob->type==OB_CURVE)
-                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Curve Guide%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d", 
-                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_GUIDE, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE);
+                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Curve Guide%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
+                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_GUIDE, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
                        else
-                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d", 
-                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE);
+                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
+                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
 
                        if(pd->forcefield==PFIELD_FORCE) tipstr= "Object center attracts or repels particles (On shared object layers)";
                        else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of Object Z axis (On shared object layers)";
@@ -3425,8 +3442,6 @@ static void object_panel_fields(Object *ob)
 
                uiBlockEndAlign(block);
                uiDefBut(block, LABEL, 0, "",160,180,150,2, NULL, 0.0, 0, 0, 0, "");
-
-               MEM_freeN(menustr);
                
                if(pd->forcefield) {
                        uiBlockBeginAlign(block);
@@ -3492,40 +3507,49 @@ static void object_panel_fields(Object *ob)
                                uiBlockEndAlign(block);
                        }
                        else{
-                               uiDefButS(block, MENU, B_FIELD_DEP, "Fall-off%t|Cone%x2|Tube%x1|Sphere%x0",     160,180,140,20, &pd->falloff, 0.0, 0.0, 0, 0, "Fall-off shape");
-                               if(pd->falloff==PFIELD_FALL_TUBE)
-                                       uiDefBut(block, LABEL, 0, "Longitudinal",               160,160,140,20, NULL, 0.0, 0, 0, 0, "");
-                               uiBlockBeginAlign(block);
-                               uiDefButBitS(block, TOG, PFIELD_POSZ, B_FIELD_CHANGE, "Pos",    160,140,40,20, &pd->flag, 0.0, 0, 0, 0, "Effect only in direction of positive Z axis");
-                               uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     200,140,100,20, &pd->f_power, 0, 10, 10, 0, "Falloff power (real gravitational falloff = 2)");
-                               uiDefButBitS(block, TOG, PFIELD_USEMAX, B_FIELD_CHANGE, "Use",  160,120,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
-                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      200,120,100,20, &pd->maxdist, 0, 1000.0, 10, 0, "Maximum distance for the field to work");
-                               uiDefButBitS(block, TOG, PFIELD_USEMIN, B_FIELD_CHANGE, "Use",  160,100,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum distance for the field's fall-off");
-                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ",      200,100,100,20, &pd->mindist, 0, 1000.0, 10, 0, "Minimum distance for the field's fall-off");
-                               uiBlockEndAlign(block);
-
-                               if(pd->falloff==PFIELD_FALL_TUBE){
-                                       uiDefBut(block, LABEL, 0, "Radial",             160,80,70,20, NULL, 0.0, 0, 0, 0, "");
-                                       uiBlockBeginAlign(block);
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
-                                       uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum radial distance for the field to work");
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      200,40,100,20, &pd->maxrad, 0, 1000.0, 10, 0, "Maximum radial distance for the field to work");
-                                       uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum radial distance for the field's fall-off");
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ",      200,20,100,20, &pd->minrad, 0, 1000.0, 10, 0, "Minimum radial distance for the field's fall-off");
-                                       uiBlockEndAlign(block);
+                               if(pd->forcefield==PFIELD_LENNARDJ) {
+                                       uiDefBut(block, LABEL, 0, "Fall-off determined",                160,140,140,20, NULL, 0.0, 0, 0, 0, "");
+                                       uiDefBut(block, LABEL, 0, "by particle sizes",          160,120,140,20, NULL, 0.0, 0, 0, 0, "");
                                }
-                               else if(pd->falloff==PFIELD_FALL_CONE){
-                                       uiDefBut(block, LABEL, 0, "Angular",            160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+                               else {
+                                       uiDefButS(block, MENU, B_FIELD_DEP, "Fall-off%t|Cone%x2|Tube%x1|Sphere%x0",     160,180,140,20, &pd->falloff, 0.0, 0.0, 0, 0, "Fall-off shape");
+                                       if(pd->falloff==PFIELD_FALL_TUBE)
+                                               uiDefBut(block, LABEL, 0, "Longitudinal",               160,160,140,20, NULL, 0.0, 0, 0, 0, "");
                                        uiBlockBeginAlign(block);
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
-                                       uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum angle for the field to work");
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxAngle: ",     200,40,100,20, &pd->maxrad, 0, 89.0, 10, 0, "Maximum angle for the field to work (in radians)");
-                                       uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum angle for the field's fall-off");
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MinAngle: ",     200,20,100,20, &pd->minrad, 0, 89.0, 10, 0, "Minimum angle for the field's fall-off (in radians)");
+                                       uiDefButBitS(block, TOG, PFIELD_POSZ, B_FIELD_CHANGE, "Pos",    160,140,40,20, &pd->flag, 0.0, 0, 0, 0, "Effect only in direction of positive Z axis");
+                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     200,140,100,20, &pd->f_power, 0, 10, 10, 0, "Falloff power (real gravitational falloff = 2)");
+                                       uiDefButBitS(block, TOG, PFIELD_USEMAX, B_FIELD_CHANGE, "Use",  160,120,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
+                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      200,120,100,20, &pd->maxdist, 0, 1000.0, 10, 0, "Maximum distance for the field to work");
+                                       uiDefButBitS(block, TOG, PFIELD_USEMIN, B_FIELD_CHANGE, "Use",  160,100,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum distance for the field's fall-off");
+                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ",      200,100,100,20, &pd->mindist, 0, 1000.0, 10, 0, "Minimum distance for the field's fall-off");
                                        uiBlockEndAlign(block);
+
+                                       if(pd->falloff==PFIELD_FALL_TUBE){
+                                               uiDefBut(block, LABEL, 0, "Radial",             160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+                                               uiBlockBeginAlign(block);
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
+                                               uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum radial distance for the field to work");
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      200,40,100,20, &pd->maxrad, 0, 1000.0, 10, 0, "Maximum radial distance for the field to work");
+                                               uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum radial distance for the field's fall-off");
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ",      200,20,100,20, &pd->minrad, 0, 1000.0, 10, 0, "Minimum radial distance for the field's fall-off");
+                                               uiBlockEndAlign(block);
+                                       }
+                                       else if(pd->falloff==PFIELD_FALL_CONE){
+                                               uiDefBut(block, LABEL, 0, "Angular",            160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+                                               uiBlockBeginAlign(block);
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
+                                               uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum angle for the field to work");
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxAngle: ",     200,40,100,20, &pd->maxrad, 0, 89.0, 10, 0, "Maximum angle for the field to work (in radians)");
+                                               uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum angle for the field's fall-off");
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MinAngle: ",     200,20,100,20, &pd->minrad, 0, 89.0, 10, 0, "Minimum angle for the field's fall-off (in radians)");
+                                               uiBlockEndAlign(block);
+                                       }
                                }
                        }
+
                }       
+               
+               MEM_freeN(menustr);
        }
 }
 
@@ -4372,6 +4396,8 @@ static void object_panel_particle_extra(Object *ob)
                uiDefButBitI(block, TOG, PART_CHILD_EFFECT, B_PART_RECALC, "Children", butx+(butw*3)/5,buty,(butw*2)/5,buth, &part->flag, 0, 0, 0, 0, "Apply effectors to children");
                uiBlockEndAlign(block);
        }
+       else if(part->phystype == PART_PHYS_NEWTON)
+               uiDefButBitI(block, TOG, PART_SELF_EFFECT, B_PART_RECALC, "Self Effect",         butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Particle effectors effect themselves");
        else
                buty-=buth;
 
index 0e7476bbe8223b04cbd7fddcf00409ae5ead09d3..71854570c8c0c3ab325303e73de0d13ba8ba188b 100644 (file)
@@ -1212,16 +1212,9 @@ static void draw_ipovertices(int sel)
                                        /*}*/
                                } else { /* normal non bit curves */
                                        if(ei->flag & IPO_EDIT) {
-                                               if(ei->icu->ipo==IPO_BEZ) {
-                                                       /* Draw the editmode hendels for a bezier curve */
-                                                       if( (bezt->f1 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[0][0] < G.v2d->cur.xmax)*/
-                                                               bglVertex3fv(bezt->vec[0]);
-                                                       
-                                                       if( (bezt->f3 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[2][0] < G.v2d->cur.xmax)*/
-                                                               bglVertex3fv(bezt->vec[2]);
-                                                       
-                                               }
-                                               
+                                               /* Only the vertex of the line, the
+                                                * handler are draw below.
+                                                */
                                                if( (bezt->f2 & SELECT) == sel) /* && G.v2d->cur.xmin < bezt->vec[1][0] < G.v2d->cur.xmax)*/
                                                        bglVertex3fv(bezt->vec[1]);
                                                
@@ -1237,6 +1230,45 @@ static void draw_ipovertices(int sel)
                                bezt++;
                        }
                        bglEnd();
+
+                       if (ei->flag & IPO_EDIT) {
+                               /* Now draw the two vertex of the handler,
+                                * need split it because we can't call glPointSize
+                                * in the middle of a glBegin/glEnd also the
+                                * bug comment before.
+                                */
+                               a= ei->icu->totvert;
+                               bezt= ei->icu->bezt;
+
+                               glPointSize(BIF_GetThemeValuef(TH_HANDLE_VERTEX_SIZE));
+
+                               if(sel) BIF_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+                               else BIF_ThemeColor(TH_HANDLE_VERTEX);
+
+                               bglBegin(GL_POINTS);
+
+                               while(a--) {
+                                       if (ei->disptype!=IPO_DISPBITS) {
+                                               if(ei->flag & IPO_EDIT) {
+                                                       if(ei->icu->ipo==IPO_BEZ) {
+                                                               /* Draw the editmode hendels for a bezier curve */
+                                                               if( (bezt->f1 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[0][0] < G.v2d->cur.xmax)*/
+                                                                       bglVertex3fv(bezt->vec[0]);
+                                                       
+                                                               if( (bezt->f3 & SELECT) == sel)/* && G.v2d->cur.xmin < bezt->vec[2][0] < G.v2d->cur.xmax)*/
+                                                                       bglVertex3fv(bezt->vec[2]);
+                                                       }
+                                               }
+                                       }
+                                       bezt++;
+                               }
+                               bglEnd();
+
+                               /* The color are always reset (see the while)
+                                * but the point size not so we reset now.
+                                */
+                               glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
+                       }
                }
        }
        
index 63c301658f2232e9c85db24a5a40b48f7d20434b..cd6aefdb87c72e1859b4f432bc117cd13a419364 100644 (file)
@@ -462,24 +462,7 @@ static void make_part_editipo(SpaceIpo *si)
                name = getname_part_ei(part_ar[a]);
                strcpy(ei->name, name);
                ei->adrcode= part_ar[a];
-               
-               //if(ei->adrcode & MA_MAP1) {
-               //      ei->adrcode-= MA_MAP1;
-               //      ei->adrcode |= texchannel_to_adrcode(si->channel);
-               //}
-               //else {
-               //      if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
-               //}
-               
                ei->col= ipo_rainbow(a, PART_TOTIPO);
-               
-               //len= strlen(ei->name);
-               //if(len) {
-               //      if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
-               //      else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
-               //      else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
-               //}
-               
                ei->icu= find_ipocurve(si->ipo, ei->adrcode);
                if(ei->icu) {
                        ei->flag= ei->icu->flag;
@@ -6011,4 +5994,4 @@ void move_to_frame(void)
                }
        }
        BIF_undo_push("Set frame to selected Ipo vertex");
-}
\ No newline at end of file
+}
index 7b3d439833eda033a69492bebfc63ce54a2bbfab..e1e286e10cf706f010e1b5f72c9c3dbc1ddcd82d 100644 (file)
@@ -103,7 +103,8 @@ char *ic_name_empty[1] ={ "" };
 char *fluidsim_ic_names[FLUIDSIM_TOTNAM] = { "Fac-Visc", "Fac-Time",  "GravX","GravY","GravZ",  "VelX","VelY","VelZ", "Active"  };
 char *part_ic_names[PART_TOTNAM] = { "E_Freq", "E_Life", "E_Speed", "E_Angular", "E_Size",
 "Angular", "Size", "Drag", "Brown", "Damp", "Length", "Clump",
-"GravX", "GravY", "GravZ", "KinkAmp", "KinkFreq", "KinkShape", "BBTilt", "FStreng", "FFall", "FMaxD"};
+"GravX", "GravY", "GravZ", "KinkAmp", "KinkFreq", "KinkShape", "BBTilt",
+"FStreng", "FFall", "FMaxD", "F2Streng", "F2Fall", "F2MaxD"};
 
 /* gets the appropriate icon for the given blocktype */
 int geticon_ipo_blocktype(short blocktype)
index f47f14a605cb32c300699b4a900d95bdff9bfeaf..acd14aae7a58daacf758ccfd8a75b15af96d818f 100644 (file)
@@ -313,7 +313,15 @@ char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
                                cp= ts->transition; break;
                        case TH_SEQ_META:
                                cp= ts->meta; break;
-                               
+                       case TH_HANDLE_VERTEX:
+                               cp= ts->handle_vertex;
+                               break;
+                       case TH_HANDLE_VERTEX_SELECT:
+                               cp= ts->handle_vertex_select;
+                               break;
+                       case TH_HANDLE_VERTEX_SIZE:
+                               cp= &ts->handle_vertex_size;
+                               break;
                        }
 
                }
@@ -493,6 +501,10 @@ void BIF_InitTheme(void)
        SETCOL(btheme->tipo.hilite, 0x60, 0xc0, 0x40, 255); 
        btheme->tipo.vertex_size= 3;
 
+       SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255);
+       SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255);
+       btheme->tipo.handle_vertex_size= 3;
+
        /* space file */
        /* to have something initialized */
        btheme->tfile= btheme->tv3d;
@@ -684,7 +696,10 @@ char *BIF_ThemeColorsPup(int spacetype)
                        str += sprintf(str, "Vertex %%x%d|", TH_VERTEX);
                        str += sprintf(str, "Vertex Selected %%x%d|", TH_VERTEX_SELECT);
                        str += sprintf(str, "Vertex Size %%x%d|", TH_VERTEX_SIZE);
-                       str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);
+                       str += sprintf(str, "Current Frame %%x%d|", TH_CFRAME);
+                       str += sprintf(str, "Handle Vertex %%x%d|", TH_HANDLE_VERTEX);
+                       str += sprintf(str, "Handle Vertex Selected %%x%d|", TH_HANDLE_VERTEX_SELECT);
+                       str += sprintf(str, "Handle Vertex Size %%x%d", TH_HANDLE_VERTEX_SIZE);
                        break;
                case SPACE_FILE:
                        str += sprintf(str, "Selected file %%x%d", TH_HILITE);
index fb055216f7f3c973160630df5c346fdbba432d98..8787cf9efc44e90e357028e0c25027a0772046a5 100644 (file)
@@ -3492,6 +3492,9 @@ static void info_user_themebuts(uiBlock *block, short y1, short y2, short y3, sh
                uiButSetFunc(but, set_userdef_iconfile_cb, &iconfileindex, NULL);
                                                                        
        }
+       else if(th_curcol==TH_HANDLE_VERTEX_SIZE) {
+               uiDefButC(block, NUMSLI, B_UPDATE_THEME,"Handle size ", 465,y3,200,20, col, 1.0, 10.0, 0, 0, "");
+       }
        else {
                uiBlockBeginAlign(block);
                if ELEM9(th_curcol, TH_PANEL, TH_LAMP, TH_FACE, TH_FACE_SELECT, TH_EDITMESH_ACTIVE, TH_MENU_BACK, TH_MENU_HILITE, TH_MENU_ITEM, TH_NODE) {
index 92e49ab29fad28b6afaf2749aea4dc73acc6ce6e..15c2664a9d898e4532cc94f7c187a49d14a56264 100644 (file)
@@ -477,7 +477,15 @@ static void init_userdef_file(void)
        if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 16)) {
                U.flag |= USER_ADD_VIEWALIGNED|USER_ADD_EDITMODE;
        }
-       
+       if ((G.main->versionfile < 247) || (G.main->versionfile == 247 && G.main->subversionfile < 1)) {
+               bTheme *btheme;
+               for(btheme= U.themes.first; btheme; btheme= btheme->next) {
+                       SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255);
+                       SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255);
+                       btheme->tipo.handle_vertex_size= 3;
+               }
+       }
+
        /* GL Texture Garbage Collection (variable abused above!) */
        if (U.textimeout == 0) {
                U.texcollectrate = 60;
index 7de3056e382ff16a8d328bdc8f08818ac3f5520d..16f8ae0095ad6f4abbf73740be8e8908a99797ed 100644 (file)
@@ -90,33 +90,10 @@ void update_for_newframe();
 
 static BlendFileData *load_game_data(char *filename) {
        BlendReadError error;
-       //this doesn't work anymore for relative paths, so use BLO_read_from_memory instead
-       //BlendFileData *bfd= BLO_read_from_file(filename, &error);
-       FILE* file = fopen(filename,"rb");
-       BlendFileData *bfd  = 0;
-       if (file)
-       {
-               fseek(file, 0L, SEEK_END);
-               int len= ftell(file);
-               fseek(file, 0L, SEEK_SET);      
-               char* filebuffer= new char[len];//MEM_mallocN(len, "text_buffer");
-               int sizeread = fread(filebuffer,len,1,file);
-               if (sizeread==1){
-                       bfd = BLO_read_from_memory(filebuffer, len, &error);
-               } else {
-                       error = BRE_UNABLE_TO_READ;
-               }
-               fclose(file);
-               // the memory is not released in BLO_read_from_memory, must do it here
-               delete filebuffer;
-       } else {
-               error = BRE_UNABLE_TO_OPEN;
-       }
-
+       BlendFileData *bfd= BLO_read_from_file(filename, &error);
        if (!bfd) {
                printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error));
        }
-       
        return bfd;
 }
 
@@ -139,7 +116,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
        // Acquire Python's GIL (global interpreter lock)
        // so we can safely run Python code and API calls
        PyGILState_STATE gilstate = PyGILState_Ensure();
-
+       
+       PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */
+       
        bgl::InitExtensions(true);
 
        do
@@ -333,6 +312,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
                        initRasterizer(rasterizer, canvas);
                        PyObject *gameLogic = initGameLogic(startscene);
                        PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module.
+                       PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
                        initGameKeys();
                        initPythonConstraintBinding();
                        initMathutils();
@@ -407,6 +387,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
                                // which allows the scene to safely delete them :)
                                // see: (space.c)->start_game
                                PyDict_Clear(PyModule_GetDict(gameLogic));
+                               PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict);
                                
                                ketsjiengine->StopEngine();
                                exitGamePythonScripting();
index 7be3b94d8aea5598f7b35fad879c5422c3ff801a..f859193ef7a6785176945970aaf685b643ca804c 100644 (file)
@@ -97,7 +97,7 @@ extern "C"
 #include "GHOST_IEventConsumer.h"
 #include "GHOST_IWindow.h"
 #include "GHOST_Rect.h"
-
+#include "marshal.h"
 
 static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
 
@@ -125,7 +125,9 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR
          m_networkdevice(0), 
          m_audiodevice(0),
          m_blendermat(0),
-         m_blenderglslmat(0)
+         m_blenderglslmat(0),
+         m_pyGlobalDictString(0),
+         m_pyGlobalDictString_Length(0)
 {
        fSystem = system;
 }
@@ -645,14 +647,23 @@ bool GPG_Application::startEngine(void)
                PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
                m_ketsjiengine->SetPythonDictionary(dictionaryobject);
                initRasterizer(m_rasterizer, m_canvas);
-               PyDict_SetItemString(dictionaryobject, "GameLogic", initGameLogic(startscene)); // Same as importing the module
+               PyObject *gameLogic = initGameLogic(startscene);
+               PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module
                initGameKeys();
                initPythonConstraintBinding();
                initMathutils();
 
-
-
-
+               /* Restore the dict */
+               if (m_pyGlobalDictString) {
+                       PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(m_pyGlobalDictString, m_pyGlobalDictString_Length);
+                       if (pyGlobalDict) {
+                               PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
+                       } else {
+                               PyErr_Clear();
+                               printf("Error could not marshall string\n");
+                       }
+               }
+               
                m_sceneconverter->ConvertScene(
                        startscenename,
                        startscene,
@@ -688,6 +699,32 @@ bool GPG_Application::startEngine(void)
 
 void GPG_Application::stopEngine()
 {
+       // get the python dict and convert to a string for future use
+       {
+               SetPyGlobalDictMarshal(NULL, 0);
+               
+               PyObject* gameLogic = PyImport_ImportModule("GameLogic");
+               if (gameLogic) {
+                       PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module
+                       if (pyGlobalDict) {
+                               PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString(  pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5
+                               if (pyGlobalDictMarshal) {
+                                       m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal);
+                                       PyObject_Print(pyGlobalDictMarshal, stderr, 0);
+                                       m_pyGlobalDictString = static_cast<char *> (malloc(m_pyGlobalDictString_Length));
+                                       memcpy(m_pyGlobalDictString, PyString_AsString(pyGlobalDictMarshal), m_pyGlobalDictString_Length);
+                               } else {
+                                       printf("Error, GameLogic.globalDict could not be marshal'd\n");
+                               }
+                       } else {
+                               printf("Error, GameLogic.globalDict was removed\n");
+                       }
+               } else {
+                       printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
+               }
+       }       
+       
+       
        // when exiting the mainloop
        exitGamePythonScripting();
        m_ketsjiengine->StopEngine();
index 17f5add8b192d1b803d243925fde2b7124edf528..31f5eb75e525398d8b060273d3118d1dd9e326b7 100644 (file)
@@ -72,6 +72,29 @@ public:
                        bool StartGameEngine(int stereoMode);
                        void StopGameEngine();
 
+                       char*
+               GetPyGlobalDictMarshal()
+               { 
+                       return m_pyGlobalDictString;
+               };
+               
+                       void
+               SetPyGlobalDictMarshal( char* pyGlobalDictString, int length )
+               {
+                       if (m_pyGlobalDictString && m_pyGlobalDictString != pyGlobalDictString)
+                               free(m_pyGlobalDictString);
+                       
+                       m_pyGlobalDictString = pyGlobalDictString;
+                       m_pyGlobalDictString_Length = length;
+               };
+               
+                       int
+               GetPyGlobalDictMarshalLength()
+               { 
+                       return m_pyGlobalDictString_Length;
+               };
+
+
 protected:
        bool    handleWheel(GHOST_IEvent* event);
        bool    handleButton(GHOST_IEvent* event, bool isDown);
@@ -142,6 +165,12 @@ protected:
 
        bool m_blendermat;
        bool m_blenderglslmat;
-
+       
+       /*
+        * GameLogic.globalDict as a string so that loading new blend files can use the same dict.
+        * Do this because python starts/stops when loading blend files.
+        */
+       char* m_pyGlobalDictString;
+       int m_pyGlobalDictString_Length;
 };
 
index 8222e5c8bac8da78f5c7a0b14960db8aff3f4b3f..26a85128025be852f1a9c084d88caf073b3601a1 100644 (file)
@@ -293,7 +293,9 @@ int main(int argc, char** argv)
        GHOST_TUns32 fullScreenHeight= 0;
        int fullScreenBpp = 32;
        int fullScreenFrequency = 60;
-
+       char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */
+       int pyGlobalDictString_Length = 0;
+       
 #ifdef __linux__
 #ifdef __alpha__
        signal (SIGFPE, SIG_IGN);
@@ -625,6 +627,10 @@ int main(int argc, char** argv)
                                                
                                                titlename = maggie->name;
                                                
+                                               // Set the GameLogic.globalDict from marshal'd data, so we can load new blend files
+                                               // abd keep data in GameLogic.globalDict
+                                               app.SetPyGlobalDictMarshal(pyGlobalDictString, pyGlobalDictString_Length);
+                                               
                                                // Check whether the game should be displayed full-screen
                                                if ((!fullScreenParFound) && (!windowParFound))
                                                {
@@ -750,6 +756,12 @@ int main(int argc, char** argv)
                                                        }
                                                }
                                                app.StopGameEngine();
+                                               
+                                               // GameLogic.globalDict has been converted into a buffer
+                                               // store in pyGlobalDictString so we can restore after python has stopped and started.
+                                               pyGlobalDictString = app.GetPyGlobalDictMarshal();
+                                               pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength();
+                                               
                                                BLO_blendfiledata_free(bfd);
                                                
 #ifdef __APPLE__
@@ -772,6 +784,11 @@ int main(int argc, char** argv)
                }
        }
 
+       if (pyGlobalDictString) {
+               free(pyGlobalDictString);
+               pyGlobalDictString = NULL;
+       }
+       
        return error ? -1 : 0;
 }
 
index e0cd5a3bc9e458431de5624a0a5c0e6bc465873d..d6997ee29a864f9af7b2b0634f6c79b4190ce3a7 100644 (file)
@@ -680,188 +680,6 @@ void      KX_ConvertODEEngineObject(KX_GameObject* gameobj,
 
 
 // forward declarations
-static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
-{
-       if (!meshobj)
-               return 0;
-
-       btCollisionShape* collisionMeshShape = 0;
-       btConvexHullShape* convexHullShape = 0;
-       btTriangleMeshShape* concaveShape = 0;
-
-       btTriangleMesh* collisionMeshData = 0;
-
-       //see if there is any polygons, if not, bail out.
-
-       int numPoints = 0;
-       btVector3* points = 0;
-
-       // Mesh has no polygons!
-       int numpolys = meshobj->NumPolygons();
-       if (!numpolys)
-       {
-               return NULL;
-       }
-
-       // Count the number of collision polygons and check they all come from the same 
-       // vertex array
-       int numvalidpolys = 0;
-       int vtxarray = -1;
-       RAS_IPolyMaterial *poly_material = NULL;
-       bool reinstance = true;
-
-       for (int p=0; p<numpolys; p++)
-       {
-               RAS_Polygon* poly = meshobj->GetPolygon(p);
-
-               // only add polygons that have the collisionflag set
-               if (poly->IsCollider())
-               {
-                       // check polygon is from the same vertex array
-                       if (poly->GetVertexIndexBase().m_vtxarray != vtxarray)
-                       {
-                               if (vtxarray < 0)
-                                       vtxarray = poly->GetVertexIndexBase().m_vtxarray;
-                               else
-                               {
-                                       reinstance = false;
-                                       vtxarray = -1;
-                               }
-                       }
-
-                       // check poly is from the same material
-                       if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
-                       {
-                               if (poly_material)
-                               {
-                                       reinstance = false;
-                                       poly_material = NULL;
-                               }
-                               else
-                                       poly_material = poly->GetMaterial()->GetPolyMaterial();
-                       }
-
-                       // count the number of collision polys
-                       numvalidpolys++;
-
-                       // We have one collision poly, and we can't reinstance, so we
-                       // might as well break here.
-                       if (!reinstance)
-                               break;
-               }
-       }
-
-       // No collision polygons
-       if (numvalidpolys < 1)
-               return NULL;
-
-
-       if (polytope)
-       {
-               convexHullShape = new btConvexHullShape(&points[0].getX(),numPoints);
-               collisionMeshShape = convexHullShape;
-       } else
-       {
-               collisionMeshData = new btTriangleMesh();
-//             concaveShape = new btTriangleMeshShape(collisionMeshData);
-               //collisionMeshShape = concaveShape;
-
-       }
-
-
-       numvalidpolys = 0;
-
-       for (int p2=0; p2<numpolys; p2++)
-       {
-               RAS_Polygon* poly = meshobj->GetPolygon(p2);
-
-               // only add polygons that have the collisionflag set
-               if (poly->IsCollider())
-               {   
-                       //Bullet can raycast any shape, so
-                       if (polytope)
-                       {
-                               for (int i=0;i<poly->VertexCount();i++)
-                               {
-                                       const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
-                                               poly->GetVertexIndexBase().m_indexarray[i],
-                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
-                                       btPoint3 point(vtx[0],vtx[1],vtx[2]);
-                                       convexHullShape->addPoint(point);
-                               }
-                               if (poly->VertexCount())
-                                       numvalidpolys++;
-
-                       } else
-                       {
-                               {
-                                       const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
-                                               poly->GetVertexIndexBase().m_indexarray[2],
-                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
-                                       btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
-                                       vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
-                                               poly->GetVertexIndexBase().m_indexarray[1],
-                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
-                                       btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
-                                       vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
-                                               poly->GetVertexIndexBase().m_indexarray[0],
-                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
-                                       btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
-                                       collisionMeshData->addTriangle(vertex0,vertex1,vertex2);
-                                       numvalidpolys++;
-                               }
-                               if (poly->VertexCount() == 4)
-                               {
-                                       const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
-                                               poly->GetVertexIndexBase().m_indexarray[3],
-                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
-                                       btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
-                                       vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
-                                               poly->GetVertexIndexBase().m_indexarray[2],
-                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
-                                       btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
-                                       vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
-                                               poly->GetVertexIndexBase().m_indexarray[0],
-                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
-                                       btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
-                                       collisionMeshData->addTriangle(vertex0,vertex1,vertex2);
-                                       numvalidpolys++;
-                               }
-
-                       }               
-               }
-       }
-
-
-
-       if (numvalidpolys > 0)
-       {
-               
-               if (!polytope)
-               {
-                       bool useQuantization = true;
-                       concaveShape = new btBvhTriangleMeshShape( collisionMeshData, useQuantization );
-                       //concaveShape = new btTriangleMeshShape( collisionMeshData );
-
-                       concaveShape->recalcLocalAabb();
-                       if (collisionMeshShape)
-                               delete collisionMeshShape;
-                       collisionMeshShape = concaveShape;
-
-               } 
-               
-               
-
-               return collisionMeshShape;
-       }
-       if (collisionMeshShape)
-               delete collisionMeshShape;
-       if (collisionMeshData)
-               delete collisionMeshData;
-       return NULL;
-
-}
-
 
 void   KX_ConvertBulletObject( class   KX_GameObject* gameobj,
        class   RAS_MeshObject* meshobj,
@@ -878,6 +696,7 @@ void        KX_ConvertBulletObject( class   KX_GameObject* gameobj,
        bool isbulletdyna = false;
        CcdConstructionInfo ci;
        class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+       class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo();
 
        
 
@@ -894,120 +713,80 @@ 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;
+       shapeInfo->m_radius = objprop->m_radius;
        isbulletdyna = objprop->m_dyna;
        
        ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
        
-       btTransform trans;
-       trans.setIdentity();
-       
        btCollisionShape* bm = 0;
 
        switch (objprop->m_boundclass)
        {
        case KX_BOUNDSPHERE:
                {
-                       float radius = objprop->m_radius;
-                       btVector3 inertiaHalfExtents (
-                               radius,
-                               radius,
-                               radius);
+                       //float radius = objprop->m_radius;
+                       //btVector3 inertiaHalfExtents (
+                       //      radius,
+                       //      radius,
+                       //      radius);
                        
                        //blender doesn't support multisphere, but for testing:
 
                        //bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1);
-                       bm = new btSphereShape(objprop->m_radius);
-                       bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+                       shapeInfo->m_shapeType = PHY_SHAPE_SPHERE;
+                       bm = shapeInfo->CreateBulletShape();
                        break;
                };
        case KX_BOUNDBOX:
                {
-                       MT_Vector3 halfExtents (
+                       shapeInfo->m_halfExtend.setValue(
                                objprop->m_boundobject.box.m_extends[0],
-                       objprop->m_boundobject.box.m_extends[1],
-                       objprop->m_boundobject.box.m_extends[2]);
-
-                       halfExtents /= 2.f;
-
-                       //btVector3 he (halfExtents[0]-CONVEX_DISTANCE_MARGIN ,halfExtents[1]-CONVEX_DISTANCE_MARGIN ,halfExtents[2]-CONVEX_DISTANCE_MARGIN );
-                       //he = he.absolute();
-
-                       btVector3 he (halfExtents[0],halfExtents[1],halfExtents[2]);
-                       he = he.absolute();
-
+                               objprop->m_boundobject.box.m_extends[1],
+                               objprop->m_boundobject.box.m_extends[2]);
 
-                       bm = new btBoxShape(he);
-                       bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+                       shapeInfo->m_halfExtend /= 2.0;
+                       shapeInfo->m_halfExtend = shapeInfo->m_halfExtend.absolute();
+                       shapeInfo->m_shapeType = PHY_SHAPE_BOX;
+                       bm = shapeInfo->CreateBulletShape();
                        break;
                };
        case KX_BOUNDCYLINDER:
                {
-                       btVector3 halfExtents (
+                       shapeInfo->m_halfExtend.setValue(
                                objprop->m_boundobject.c.m_radius,
                                objprop->m_boundobject.c.m_radius,
                                objprop->m_boundobject.c.m_height * 0.5f
                        );
-                       bm = new btCylinderShapeZ(halfExtents);
-                       bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
-
+                       shapeInfo->m_shapeType = PHY_SHAPE_CYLINDER;
+                       bm = shapeInfo->CreateBulletShape();
                        break;
                }
 
-               case KX_BOUNDCONE:
+       case KX_BOUNDCONE:
                {
-                               btVector3 halfExtents (objprop->m_boundobject.box.m_extends[0],
-                               objprop->m_boundobject.box.m_extends[1],
-                               objprop->m_boundobject.box.m_extends[2]);
-
-
-                               halfExtents /= 2.f;
-
-                               bm = new btConeShapeZ(objprop->m_boundobject.c.m_radius,objprop->m_boundobject.c.m_height);
-                               bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
-
+                       shapeInfo->m_radius = objprop->m_boundobject.c.m_radius;
+                       shapeInfo->m_height = objprop->m_boundobject.c.m_height;
+                       shapeInfo->m_shapeType = PHY_SHAPE_CONE;
+                       bm = shapeInfo->CreateBulletShape();
                        break;
                }
-               case KX_BOUNDPOLYTOPE:
-                       {
-                               bm = CreateBulletShapeFromMesh(meshobj,true);
-                               if (bm)
-                               {
-                                       bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
-                               }
-                               break;
-                       }
-               case KX_BOUNDMESH:
-                       {
-                               if (!ci.m_mass)
-                               {                               
-                                       bm = CreateBulletShapeFromMesh(meshobj,false);
-                                       ci.m_localInertiaTensor.setValue(0.f,0.f,0.f);
-                                       //no moving concave meshes, so don't bother calculating inertia
-                                       //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
-                               }
-
-                               break;
-                       }
-
-       default:
-               //interpret the shape as a concave triangle-mesh
+       case KX_BOUNDPOLYTOPE:
                {
-                       if (meshobj)
-                       {
-                               bm = CreateBulletShapeFromMesh(meshobj,false);
-                               ci.m_localInertiaTensor.setValue(0.f,0.f,0.f);
-
-                       //      assert(0);
-
-                                       /*
-                               meshobj->ScheduleCollisionPolygons();
-
-                               KX_DeformableMesh* gfxmesh = new KX_DeformableMesh(meshobj);
-                               gfxmesh->sendFixedMapping();
-                               //trianglemesh
-                               bm = new TriangleMeshInterface(gfxmesh,trans);
-                               */
+                       shapeInfo->SetMesh(meshobj, true);
+                       bm = shapeInfo->CreateBulletShape();
+                       break;
+               }
+       case KX_BOUNDMESH:
+               {
+                       if (!ci.m_mass)
+                       {                               
+                               shapeInfo->SetMesh(meshobj, false);
+                               bm = shapeInfo->CreateBulletShape();
+                               //no moving concave meshes, so don't bother calculating inertia
+                               //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
                        }
+
+                       break;
                }
        }
 
@@ -1017,44 +796,41 @@ void     KX_ConvertBulletObject( class   KX_GameObject* gameobj,
        if (!bm)
        {
                delete motionstate;
+               delete shapeInfo;
                return;
        }
 
        bm->setMargin(0.06);
 
 
-
                if (objprop->m_isCompoundChild)
                {
                        //find parent, compound shape and add to it
                        //take relative transform into account!
                        KX_BulletPhysicsController* parentCtrl = (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController();
                        assert(parentCtrl);
+                       CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
                        btRigidBody* rigidbody = parentCtrl->GetRigidBody();
                        btCollisionShape* colShape = rigidbody->getCollisionShape();
                        assert(colShape->isCompound());
                        btCompoundShape* compoundShape = (btCompoundShape*)colShape;
-                       btTransform childTrans;
-                       childTrans.setIdentity();
-                       NodeList& children = objprop->m_dynamic_parent->GetSGNode()->GetSGChildren();
 
                        MT_Point3 childPos = gameobj->GetSGNode()->GetLocalPosition();
                        MT_Matrix3x3 childRot = gameobj->GetSGNode()->GetLocalOrientation();
                        MT_Vector3 childScale = gameobj->GetSGNode()->GetLocalScale();
 
                        bm->setLocalScaling(btVector3(childScale.x(),childScale.y(),childScale.z()));
-                       childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z()));
+                       shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z()));
                        float rotval[12];
                        childRot.getValue(rotval);
                        btMatrix3x3 newRot;
                        newRot.setValue(rotval[0],rotval[1],rotval[2],rotval[4],rotval[5],rotval[6],rotval[8],rotval[9],rotval[10]);
                        newRot = newRot.transpose();
 
-                       childTrans.setBasis(newRot);
-                               
-
-                       compoundShape->addChildShape(childTrans,bm);
-                       kxscene->AddShape(bm);
+                       shapeInfo->m_childTrans.setBasis(newRot);
+                       parentShapeInfo->AddShape(shapeInfo);   
+                       
+                       compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
                        //do some recalc?
                        //recalc inertia for rigidbody
                        if (!rigidbody->isStaticOrKinematicObject())
@@ -1069,15 +845,16 @@ void     KX_ConvertBulletObject( class   KX_GameObject* gameobj,
 
                if (objprop->m_hasCompoundChildren)
                {
-                       //replace shape by compoundShape
+                       // create a compound shape info
+                       CcdShapeConstructionInfo *compoundShapeInfo = new CcdShapeConstructionInfo();
+                       compoundShapeInfo->m_shapeType = PHY_SHAPE_COMPOUND;
+                       compoundShapeInfo->AddShape(shapeInfo);
+                       // create the compound shape manually as we already have the child shape
                        btCompoundShape* compoundShape = new btCompoundShape();
-                       btTransform identTrans;
-                       identTrans.setIdentity();
-                       compoundShape->addChildShape(identTrans,bm);
-                       //note abount compoundShape: Bullet does not delete the child shapes when 
-                       //the compound shape is deleted, so insert also the child shapes 
-                       kxscene->AddShape(bm);
+                       compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
+                       // now replace the shape
                        bm = compoundShape;
+                       shapeInfo = compoundShapeInfo;
                }
 
 
@@ -1113,6 +890,7 @@ void       KX_ConvertBulletObject( class   KX_GameObject* gameobj,
 
 
        ci.m_collisionShape = bm;
+       ci.m_shapeInfo = shapeInfo;
        ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice
        ci.m_restitution = smmaterial->m_restitution;
        ci.m_physicsEnv = env;
@@ -1124,9 +902,12 @@ void      KX_ConvertBulletObject( class   KX_GameObject* gameobj,
        ci.m_collisionFilterGroup = (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : short(CcdConstructionInfo::StaticFilter);
        ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter);
        ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody;
+       MT_Vector3 scaling = gameobj->NodeGetWorldScaling();
+       ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]);
        KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna);
-       //remember that we created a shape so that we can delete it when the scene is removed (bullet will not delete it) 
-       kxscene->AddShape(bm);
+       // shapeInfo is reference counted, decrement now as we don't use it anymore
+       if (shapeInfo)
+               shapeInfo->Release();
 
        if (objprop->m_in_active_layer)
        {
index 868439546c3cff404f04b3fdf970e0653989da46..472ae759d65a1c4fde39e9b627bfbd47bdfdf15b 100644 (file)
@@ -733,6 +733,10 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
 
        // 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());
 
        ErrorObject = PyString_FromString("GameLogic.error");
        PyDict_SetItemString(d, "error", ErrorObject);
index 2828663c63df602a45cdd716af1c97212313776d..ab3692d2411b1402a760ea45731e3888bcac6076 100644 (file)
@@ -234,40 +234,9 @@ KX_Scene::~KX_Scene()
        {
                delete m_bucketmanager;
        }
-#ifdef USE_BULLET
-       // This is a fix for memory leaks in bullet: the collision shapes is not destroyed 
-       // when the physical controllers are destroyed. The reason is that shapes are shared
-       // between replicas of an object. There is no reference count in Bullet so the
-       // only workaround that does not involve changes in Bullet is to save in this array
-       // the list of shapes that are created when the scene is created (see KX_ConvertPhysicsObjects.cpp)
-       class btCollisionShape* shape;
-       class btTriangleMeshShape* meshShape;
-       vector<class btCollisionShape*>::iterator it = m_shapes.begin();
-       while (it != m_shapes.end()) {
-               shape = *it;
-               if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
-               {
-                       meshShape = static_cast<btTriangleMeshShape*>(shape);
-                       // shapes based on meshes use an interface that contains the vertices.
-                       // Again the idea is to be able to share the interface between shapes but
-                       // this is not used in Blender: each base object will have its own interface 
-                       btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
-                       if (meshInterface)
-                               delete meshInterface;
-               }
-               delete shape;
-               it++;
-       }
-#endif
        //Py_DECREF(m_attrlist);
 }
 
-void KX_Scene::AddShape(class btCollisionShape*shape)
-{
-       m_shapes.push_back(shape);
-}
-
-
 void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
 {
        m_projectionmat = pmat;
index 80a2abe287ad2e464ecf4a4d68fab9537273aeb2..1c56dd1ee55ef794e68b0510b311af63af06310e 100644 (file)
@@ -121,11 +121,6 @@ protected:
         * The set of cameras for this scene
         */
        list<class KX_Camera*>       m_cameras;
-       /**
-        * The set of bullet shapes that must be deleted at the end of the scene
-        * to avoid memory leak (not deleted by bullet because shape are shared between replicas)
-        */
-       vector<class btCollisionShape*> m_shapes;
        /**
         * Various SCA managers used by the scene
         */
@@ -322,7 +317,6 @@ public:
        int NewRemoveObject(CValue* gameobj);
        void ReplaceMesh(CValue* gameobj,
                                         void* meshobj);
-       void AddShape(class btCollisionShape* shape);
        /**
         * @section Logic stuff
         * Initiate an update of the logic system.
index b872fae61388750bd1cb8eeea4e3c2a7540d9621..d6a32dfd9c04587dbb3ceac7aa073847990974a4 100644 (file)
@@ -18,6 +18,7 @@ subject to the following restrictions:
 
 #include "PHY_IMotionState.h"
 #include "CcdPhysicsEnvironment.h"
+#include "RAS_MeshObject.h"
 
 
 class BP_Proxy;
@@ -44,7 +45,18 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
        m_newClientInfo = 0;
        m_registerCount = 0;
                
+       // copy pointers locally to allow smart release
        m_MotionState = ci.m_MotionState;
+       m_collisionShape = ci.m_collisionShape;
+       // apply scaling before creating rigid body
+       m_collisionShape->setLocalScaling(m_cci.m_scaling);
+       if (m_cci.m_mass)
+               m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
+       // shape info is shared, increment ref count
+       m_shapeInfo = ci.m_shapeInfo;
+       if (m_shapeInfo)
+               m_shapeInfo->AddRef();
+       
        m_bulletMotionState = 0;
        
        
@@ -116,7 +128,7 @@ void CcdPhysicsController::CreateRigidbody()
 
        m_body = new btRigidBody(m_cci.m_mass,
                m_bulletMotionState,
-               m_cci.m_collisionShape,
+               m_collisionShape,
                m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor,
                m_cci.m_linearDamping,m_cci.m_angularDamping,
                m_cci.m_friction,m_cci.m_restitution);
@@ -144,6 +156,19 @@ void CcdPhysicsController::CreateRigidbody()
        }
 }
 
+static void DeleteBulletShape(btCollisionShape* shape)
+{
+       if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+       {
+               // shapes based on meshes use an interface that contains the vertices.
+               btTriangleMeshShape* meshShape = static_cast<btTriangleMeshShape*>(shape);
+               btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
+               if (meshInterface)
+                       delete meshInterface;
+       }
+       delete shape;
+}
+
 CcdPhysicsController::~CcdPhysicsController()
 {
        //will be reference counted, due to sharing
@@ -155,6 +180,27 @@ CcdPhysicsController::~CcdPhysicsController()
        if (m_bulletMotionState)
                delete m_bulletMotionState;
        delete m_body;
+
+       if (m_collisionShape)
+       {
+               // collision shape is always unique to the controller, can delete it here
+               if (m_collisionShape->isCompound())
+               {
+                       // bullet does not delete the child shape, must do it here
+                       btCompoundShape* compoundShape = (btCompoundShape*)m_collisionShape;
+                       int numChild = compoundShape->getNumChildShapes();
+                       for (int i=numChild-1 ; i >= 0; i--)
+                       {
+                               btCollisionShape* childShape = compoundShape->getChildShape(i);
+                               DeleteBulletShape(childShape);
+                       }
+               }
+               DeleteBulletShape(m_collisionShape);
+       }
+       if (m_shapeInfo)
+       {
+               m_shapeInfo->Release();
+       }
 }
 
 
@@ -219,11 +265,33 @@ void              CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
 {
        m_MotionState = motionstate;
        m_registerCount = 0;
-       
+       m_collisionShape = NULL;
+
+       // always create a new shape to avoid scaling bug
+       if (m_shapeInfo)
+       {
+               m_shapeInfo->AddRef();
+               m_collisionShape = m_shapeInfo->CreateBulletShape();
+
+               if (m_collisionShape)
+               {
+                       // new shape has no scaling, apply initial scaling
+                       m_collisionShape->setLocalScaling(m_cci.m_scaling);
+                       if (m_cci.m_mass)
+                               m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
+               }
+       }
 
        m_body = 0;
        CreateRigidbody();
-       
+
+       if (m_body)
+       {
+               if (m_cci.m_mass)
+               {
+                       m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
+               } 
+       }                       
        m_cci.m_physicsEnv->addCcdPhysicsController(this);
 
 
@@ -597,29 +665,32 @@ bool CcdPhysicsController::wantsSleeping()
 
 PHY_IPhysicsController*        CcdPhysicsController::GetReplica()
 {
-       //very experimental, shape sharing is not implemented yet.
-       //just support btSphereShape/ConeShape for now
-
+       // This is used only to replicate Near and Radar sensor controllers
+       // The replication of object physics controller is done in KX_BulletPhysicsController::GetReplica()
        CcdConstructionInfo cinfo = m_cci;
-       if (cinfo.m_collisionShape)
+       if (m_shapeInfo)
        {
-               switch (cinfo.m_collisionShape->getShapeType())
+               // This situation does not normally happen
+               cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape();
+       } 
+       else if (m_collisionShape)
+       {
+               switch (m_collisionShape->getShapeType())
                {
                case SPHERE_SHAPE_PROXYTYPE:
                        {
-                               btSphereShape* orgShape = (btSphereShape*)cinfo.m_collisionShape;
+                               btSphereShape* orgShape = (btSphereShape*)m_collisionShape;
                                cinfo.m_collisionShape = new btSphereShape(*orgShape);
                                break;
                        }
 
-                       case CONE_SHAPE_PROXYTYPE:
+               case CONE_SHAPE_PROXYTYPE:
                        {
-                               btConeShape* orgShape = (btConeShape*)cinfo.m_collisionShape;
+                               btConeShape* orgShape = (btConeShape*)m_collisionShape;
                                cinfo.m_collisionShape = new btConeShape(*orgShape);
                                break;
                        }
 
-
                default:
                        {
                                return 0;
@@ -628,6 +699,7 @@ PHY_IPhysicsController*     CcdPhysicsController::GetReplica()
        }
 
        cinfo.m_MotionState = new DefaultMotionState();
+       cinfo.m_shapeInfo = m_shapeInfo;
 
        CcdPhysicsController* replica = new CcdPhysicsController(cinfo);
        return replica;
@@ -689,3 +761,201 @@ void      DefaultMotionState::calculateWorldTransformations()
 
 }
 
+// Shape constructor
+bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope)
+{
+       // assume no shape information
+       m_shapeType = PHY_SHAPE_NONE;
+       m_vertexArray.clear();
+
+       if (!meshobj)
+               return false;
+
+       // Mesh has no polygons!
+       int numpolys = meshobj->NumPolygons();
+       if (!numpolys)
+       {
+               return false;
+       }
+
+       // check that we have at least one colliding polygon
+       int numvalidpolys = 0;
+
+       for (int p=0; p<numpolys; p++)
+       {
+               RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+               // only add polygons that have the collisionflag set
+               if (poly->IsCollider())
+               {
+                       numvalidpolys++;
+                       break;
+               }
+       }
+
+       // No collision polygons
+       if (numvalidpolys < 1)
+               return false;
+
+       m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
+
+       numvalidpolys = 0;
+
+       for (int p2=0; p2<numpolys; p2++)
+       {
+               RAS_Polygon* poly = meshobj->GetPolygon(p2);
+
+               // only add polygons that have the collisionflag set
+               if (poly->IsCollider())
+               {   
+                       //Bullet can raycast any shape, so
+                       if (polytope)
+                       {
+                               for (int i=0;i<poly->VertexCount();i++)
+                               {
+                                       const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
+                                               poly->GetVertexIndexBase().m_indexarray[i],
+                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+                                       btPoint3 point(vtx[0],vtx[1],vtx[2]);
+                                       m_vertexArray.push_back(point);
+                                       numvalidpolys++;
+                               }
+                       } else
+                       {
+                               {
+                                       const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
+                                               poly->GetVertexIndexBase().m_indexarray[2],
+                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+                                       btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
+                                       vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
+                                               poly->GetVertexIndexBase().m_indexarray[1],
+                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+                                       btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
+                                       vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
+                                               poly->GetVertexIndexBase().m_indexarray[0],
+                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+                                       btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
+                                       m_vertexArray.push_back(vertex0);
+                                       m_vertexArray.push_back(vertex1);
+                                       m_vertexArray.push_back(vertex2);
+                                       numvalidpolys++;
+                               }
+                               if (poly->VertexCount() == 4)
+                               {
+                                       const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
+                                               poly->GetVertexIndexBase().m_indexarray[3],
+                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+                                       btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
+                                       vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
+                                               poly->GetVertexIndexBase().m_indexarray[2],
+                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+                                       btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
+                                       vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
+                                               poly->GetVertexIndexBase().m_indexarray[0],
+                                               poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
+                                       btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
+                                       m_vertexArray.push_back(vertex0);
+                                       m_vertexArray.push_back(vertex1);
+                                       m_vertexArray.push_back(vertex2);
+                                       numvalidpolys++;
+                               }
+                       }               
+               }
+       }
+
+       if (!numvalidpolys)
+       {
+               // should not happen
+               m_shapeType = PHY_SHAPE_NONE;
+               return false;
+       }
+       return true;
+}
+
+btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
+{
+       btCollisionShape* collisionShape = 0;
+       btTriangleMeshShape* concaveShape = 0;
+       btTriangleMesh* collisionMeshData = 0;
+       btCompoundShape* compoundShape = 0;
+       CcdShapeConstructionInfo* nextShapeInfo;
+
+       switch (m_shapeType) 
+       {
+       case PHY_SHAPE_NONE:
+               break;
+
+       case PHY_SHAPE_BOX:
+               collisionShape = new btBoxShape(m_halfExtend);
+               break;
+
+       case PHY_SHAPE_SPHERE:
+               collisionShape = new btSphereShape(m_radius);
+               break;
+
+       case PHY_SHAPE_CYLINDER:
+               collisionShape = new btCylinderShapeZ(m_halfExtend);
+               break;
+
+       case PHY_SHAPE_CONE:
+               collisionShape = new btConeShapeZ(m_radius, m_height);
+               break;
+
+       case PHY_SHAPE_POLYTOPE:
+               collisionShape = new btConvexHullShape(&m_vertexArray.begin()->getX(), m_vertexArray.size());
+               break;
+
+       case PHY_SHAPE_MESH:
+               collisionMeshData = new btTriangleMesh();
+               // m_vertexArray is necessarily a multiple of 3
+               for (std::vector<btPoint3>::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); )
+               {
+            collisionMeshData->addTriangle(*it++,*it++,*it++);
+               }
+               concaveShape = new btBvhTriangleMeshShape( collisionMeshData, true );
+               concaveShape->recalcLocalAabb();
+               collisionShape = concaveShape;
+               break;
+
+       case PHY_SHAPE_COMPOUND:
+               if (m_nextShape)
+               {
+                       compoundShape = new btCompoundShape();
+                       for (nextShapeInfo=m_nextShape; nextShapeInfo; nextShapeInfo = nextShapeInfo->m_nextShape)
+                       {
+                               collisionShape = nextShapeInfo->CreateBulletShape();
+                               if (collisionShape)
+                               {
+                                       compoundShape->addChildShape(nextShapeInfo->m_childTrans, collisionShape);
+                               }
+                       }
+                       collisionShape = compoundShape;
+               }
+       }
+       return collisionShape;
+}
+
+void CcdShapeConstructionInfo::AddShape(CcdShapeConstructionInfo* shapeInfo)
+{
+       CcdShapeConstructionInfo* nextShape = this;
+       while (nextShape->m_nextShape != NULL)
+               nextShape = nextShape->m_nextShape;
+       nextShape->m_nextShape = shapeInfo;
+}
+
+CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
+{
+       CcdShapeConstructionInfo* childShape = m_nextShape;
+
+       while (childShape)
+       {
+               CcdShapeConstructionInfo* nextShape = childShape->m_nextShape;
+               childShape->m_nextShape = NULL;
+               childShape->Release();
+               childShape = nextShape;
+       }
+       
+       m_vertexArray.clear();
+}
+
+
index 448e5622eff579fb0ba3f9d8142f437027cacd79..1e1a38aa2a6661bc52463866ca9e94e3abcb2739 100644 (file)
@@ -17,11 +17,14 @@ subject to the following restrictions:
 #ifndef BULLET2_PHYSICSCONTROLLER_H
 #define BULLET2_PHYSICSCONTROLLER_H
 
+#include <vector>
+
 #include "PHY_IPhysicsController.h"
 
 ///    PHY_IPhysicsController is the abstract simplified Interface to a physical object.
 ///    It contains the IMotionState and IDeformableMesh Interfaces.
 #include "btBulletDynamicsCommon.h"
+#include "LinearMath/btTransform.h"
 
 #include "PHY_IMotionState.h"
 
@@ -31,8 +34,66 @@ extern float gAngularSleepingTreshold;
 extern bool gDisableDeactivation;
 class CcdPhysicsEnvironment;
 class btMotionState;
+class RAS_MeshObject;
+class btCollisionShape;
+
+// Shape contructor
+// It contains all the information needed to create a simple bullet shape at runtime
+class CcdShapeConstructionInfo
+{
+public:
+       CcdShapeConstructionInfo() :
+               m_shapeType(PHY_SHAPE_NONE),
+               m_radius(1.0),
+               m_height(1.0),
+               m_halfExtend(0.f,0.f,0.f),
+               m_nextShape(NULL),
+               m_refCount(1)
+       {
+               m_childTrans.setIdentity();
+       }
 
+       ~CcdShapeConstructionInfo();
 
+       CcdShapeConstructionInfo* AddRef()
+       { 
+               m_refCount++;
+               return this;
+       }
+
+       int Release()
+       {
+               if (--m_refCount > 0)
+                       return m_refCount;
+               delete this;
+               return 0;
+       }
+
+       void AddShape(CcdShapeConstructionInfo* shapeInfo);
+
+       CcdShapeConstructionInfo* GetNextShape()
+       {
+               return m_nextShape;
+       }
+
+       bool SetMesh(RAS_MeshObject* mesh, bool polytope);
+
+       btCollisionShape* CreateBulletShape();
+
+       // member variables
+       PHY_ShapeType                   m_shapeType;
+       btScalar                                m_radius;
+       btScalar                                m_height;
+       btVector3                               m_halfExtend;
+       btTransform                             m_childTrans;
+       std::vector<btPoint3>   m_vertexArray;  // Contains both vertex array for polytope shape and
+                                                                                       // triangle array for concave mesh shape.
+                                                                                       // In this case a triangle is made of 3 consecutive points
+protected:
+       CcdShapeConstructionInfo* m_nextShape;  // for compound shape
+       int                                             m_refCount;             // this class is shared between replicas
+                                                                                       // keep track of users so that we can release it 
+};
 
 struct CcdConstructionInfo
 {
@@ -65,6 +126,7 @@ struct CcdConstructionInfo
                m_collisionFilterMask(AllFilter),
                m_collisionShape(0),
                m_MotionState(0),
+               m_shapeInfo(0),
                m_physicsEnv(0),
                m_inertiaFactor(1.f)
        {
@@ -89,8 +151,11 @@ struct CcdConstructionInfo
        short int       m_collisionFilterGroup;
        short int       m_collisionFilterMask;
 
+       ///these pointers are used as argument passing for the CcdPhysicsController constructor
+       ///and not anymore after that
        class btCollisionShape* m_collisionShape;
        class PHY_IMotionState* m_MotionState;
+       class CcdShapeConstructionInfo* m_shapeInfo;
        
        CcdPhysicsEnvironment*  m_physicsEnv; //needed for self-replication
        float   m_inertiaFactor;//tweak the inertia (hooked up to Blender 'formfactor'
@@ -106,6 +171,9 @@ class CcdPhysicsController : public PHY_IPhysicsController
        btRigidBody* m_body;
        class PHY_IMotionState*         m_MotionState;
        btMotionState*  m_bulletMotionState;
+       class btCollisionShape* m_collisionShape;
+       class CcdShapeConstructionInfo* m_shapeInfo;
+
        friend class CcdPhysicsEnvironment;     // needed when updating the controller
 
 
@@ -137,6 +205,7 @@ class CcdPhysicsController : public PHY_IPhysicsController
 
 
                btRigidBody* GetRigidBody() { return m_body;}
+               CcdShapeConstructionInfo* GetShapeInfo() { return m_shapeInfo; }
 
                btCollisionShape*       GetCollisionShape() { 
                        return m_body->getCollisionShape();
index dfbcf115fd7c764da0bcef63804216c1bfbba7e2..d8e05fab8390cd3cc615e03a988b52172a8b53b3 100644 (file)
@@ -1370,8 +1370,9 @@ int                       CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
 {
        CcdConstructionInfo     cinfo;
-       //This is a memory leak: Bullet does not delete the shape and it cannot be added to 
-       //the KX_Scene.m_shapes list -- too bad but that's not a lot of data
+
+       // 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);
        cinfo.m_MotionState = 0;
        cinfo.m_physicsEnv = this;
index dd6eab0f0182a3f2397d885f104f5baa76f1d680..0936d45197afa8da67a9206dbcee504a39d0b49f 100644 (file)
@@ -3,7 +3,7 @@ Import ('env')
 
 sources = 'CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp'
 
-incs = '. ../common'
+incs = '. ../common #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer'
 
 incs += ' ' + env['BF_BULLET_INC']
 
index c289b9d8bcb7c57bd0c11c91e39fe4d62db7f8cd..3b3e42c38d241e5be44936f441865247af08878c 100644 (file)
@@ -87,6 +87,18 @@ typedef enum PHY_ConstraintType {
 
 } PHY_ConstraintType;
 
+typedef enum PHY_ShapeType {
+       PHY_SHAPE_NONE,
+       PHY_SHAPE_BOX,
+       PHY_SHAPE_SPHERE,
+       PHY_SHAPE_CYLINDER,
+       PHY_SHAPE_CONE,
+       PHY_SHAPE_MESH,
+       PHY_SHAPE_POLYTOPE,
+       PHY_SHAPE_COMPOUND
+} PHY_ShapeType;
+
+
 typedef float  PHY_Vector3[3];
 
 #endif //__PHY_DYNAMIC_TYPES