svn merge -r 16222:16320 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Sun, 31 Aug 2008 21:00:20 +0000 (21:00 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Sun, 31 Aug 2008 21:00:20 +0000 (21:00 +0000)
111 files changed:
CMake/macros.cmake
CMakeLists.txt
extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj
projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj
release/text/copyright.txt
source/Makefile
source/blender/blenkernel/BKE_deform.h
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/shrinkwrap.c
source/blender/blenlib/BLI_winstuff.h
source/blender/blenlib/intern/BLI_kdopbvh.c
source/blender/include/BDR_gpencil.h
source/blender/include/BIF_editarmature.h
source/blender/include/BIF_editview.h
source/blender/include/BSE_drawipo.h
source/blender/include/transform.h
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesdna/DNA_gpencil_types.h
source/blender/makesdna/DNA_sensor_types.h
source/blender/python/api2_2x/Particle.c
source/blender/render/intern/source/convertblender.c
source/blender/src/buttons_logic.c
source/blender/src/drawgpencil.c
source/blender/src/drawipo.c
source/blender/src/editarmature.c
source/blender/src/editmesh_tools.c
source/blender/src/editnode.c
source/blender/src/editobject.c
source/blender/src/editview.c
source/blender/src/gpencil.c
source/blender/src/header_view3d.c
source/blender/src/space.c
source/blender/src/transform_conversions.c
source/blender/src/transform_generics.c
source/blender/src/transform_numinput.c
source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Converter/KX_ConvertSensors.cpp
source/gameengine/Expressions/PyObjectPlus.h
source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
source/gameengine/GameLogic/Joystick/SCA_Joystick.h
source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
source/gameengine/GameLogic/SCA_IController.cpp
source/gameengine/GameLogic/SCA_ISensor.cpp
source/gameengine/GameLogic/SCA_ISensor.h
source/gameengine/GameLogic/SCA_JoystickManager.cpp
source/gameengine/GameLogic/SCA_JoystickManager.h
source/gameengine/GameLogic/SCA_JoystickSensor.cpp
source/gameengine/GameLogic/SCA_JoystickSensor.h
source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
source/gameengine/GameLogic/SCA_LogicManager.cpp
source/gameengine/GameLogic/SCA_LogicManager.h
source/gameengine/GameLogic/SCA_PythonController.cpp
source/gameengine/GameLogic/SCA_PythonController.h
source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
source/gameengine/GamePlayer/common/GPC_RenderTools.h
source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/Ketsji/KX_ConstraintActuator.cpp
source/gameengine/Ketsji/KX_ConstraintActuator.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_IPO_SGController.cpp
source/gameengine/Ketsji/KX_MeshProxy.cpp
source/gameengine/Ketsji/KX_MeshProxy.h
source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
source/gameengine/Ketsji/KX_MouseFocusSensor.h
source/gameengine/Ketsji/KX_PolyProxy.cpp [new file with mode: 0644]
source/gameengine/Ketsji/KX_PolyProxy.h [new file with mode: 0644]
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_RayCast.cpp
source/gameengine/Ketsji/KX_RayCast.h
source/gameengine/Ketsji/KX_RaySensor.cpp
source/gameengine/Ketsji/KX_RaySensor.h
source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_SoundActuator.cpp
source/gameengine/Ketsji/Makefile
source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
source/gameengine/Physics/Bullet/Makefile
source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
source/gameengine/PyDoc/GameKeys.py
source/gameengine/PyDoc/KX_GameObject.py
source/gameengine/PyDoc/KX_MeshProxy.py
source/gameengine/PyDoc/KX_ObjectActuator.py
source/gameengine/PyDoc/KX_PolyProxy.py [new file with mode: 0644]
source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py
source/gameengine/PyDoc/KX_TrackToActuator.py
source/gameengine/PyDoc/Rasterizer.py
source/gameengine/PyDoc/SCA_DelaySensor.py
source/gameengine/PyDoc/SCA_ISensor.py
source/gameengine/Rasterizer/RAS_MeshObject.cpp
source/gameengine/Rasterizer/RAS_MeshObject.h
source/nan_definitions.mk

index 6b6837d25f0526667e29a74f7552f814335cdd95..e3dd46eb5ea11a8daf77ca045c7c98a0702db37a 100644 (file)
@@ -38,6 +38,8 @@ MACRO(BLENDERLIB
 ENDMACRO(BLENDERLIB)
 
 MACRO(SETUP_LIBDIRS)
+  # see "cmake --help-policy CMP0003"
+  CMAKE_POLICY(SET CMP0003 NEW)
   LINK_DIRECTORIES(${PYTHON_LIBPATH} ${SDL_LIBPATH} ${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${ICONV_LIBPATH} ${OPENEXR_LIBPATH} ${QUICKTIME_LIBPATH} ${FFMPEG_LIBPATH})
   IF(WITH_INTERNATIONAL)
     LINK_DIRECTORIES(${GETTEXT_LIBPATH})
index 5b86ca8f21e5a81e2f52d4f9ded2f9eb74a55bcb..97113c22f980e61e050c5b2f3b0352d0788dd7a2 100644 (file)
@@ -248,7 +248,11 @@ IF(WIN32)
   
   SET(GETTEXT ${LIBDIR}/gettext)
   SET(GETTEXT_INC ${GETTEXT}/include)
-  SET(GETTEXT_LIB gnu_gettext)
+  IF(CMAKE_CL_64)
+       SET(GETTEXT_LIB gettextlib)
+  ELSE(CMAKE_CL_64)
+       SET(GETTEXT_LIB gnu_gettext)
+  ENDIF(CMAKE_CL_64)
   SET(GETTEXT_LIBPATH ${GETTEXT}/lib)
 
   SET(FREETYPE ${LIBDIR}/freetype)
@@ -279,7 +283,12 @@ IF(WIN32)
   SET(FFMPEG_LIB avcodec-51 avformat-52 avdevice-52 avutil-49 swscale-0)
   SET(FFMPEG_LIBPATH ${FFMPEG}/lib)
 
+  IF(CMAKE_CL_64)
+  SET(LLIBS kernel32 user32 vfw32 winmm ws2_32 )
+  ELSE(CMAKE_CL_64)
   SET(LLIBS kernel32 user32 gdi32 comdlg32 advapi32 shell32 ole32 oleaut32 uuid ws2_32 vfw32 winmm)
+  ENDIF(CMAKE_CL_64)
+  
   IF(WITH_OPENAL)
     SET(LLIBS ${LLIBS} dxguid)
   ENDIF(WITH_OPENAL)
@@ -317,7 +326,7 @@ IF(WIN32)
   SET(WINTAB_INC ${LIBDIR}/wintab/include) 
 
   IF(CMAKE_CL_64)
-  SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib;MSVCRT.lib ")
+  SET(PLATFORM_LINKFLAGS "/MACHINE:X64 /NODEFAULTLIB:libc.lib;MSVCRT.lib ")
   ELSE(CMAKE_CL_64)
   SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib ")
   ENDIF(CMAKE_CL_64)
index b49036a5b50322b12b27e726b9024ebb0241d3b7..7dc7d8d2f68e1483707fa1e278983e24eb87d2ab 100644 (file)
@@ -181,7 +181,9 @@ void        btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
                                          btCollisionObject* collisionObject,
                                          const btCollisionShape* collisionShape,
                                          const btTransform& colObjWorldTransform,
-                                         RayResultCallback& resultCallback,short int collisionFilterMask)
+                                         RayResultCallback& resultCallback,
+                                         short int collisionFilterMask,
+                                         bool faceNormal)
 {
        
        btSphereShape pointShape(btScalar(0.0));
@@ -191,14 +193,16 @@ void      btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
                                          collisionObject,
                                          collisionShape,
                                          colObjWorldTransform,
-                                         resultCallback,collisionFilterMask);
+                                         resultCallback,collisionFilterMask,faceNormal);
 }
 
 void   btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans,
                                          btCollisionObject* collisionObject,
                                          const btCollisionShape* collisionShape,
                                          const btTransform& colObjWorldTransform,
-                                         RayResultCallback& resultCallback,short int collisionFilterMask)
+                                         RayResultCallback& resultCallback,
+                                         short int collisionFilterMask,
+                                         bool faceNormal)
 {
        
 
@@ -257,9 +261,9 @@ void        btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
                                                        btCollisionObject*      m_collisionObject;
                                                        btTriangleMeshShape*    m_triangleMesh;
 
-                                                       BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
-                                                               btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape*    triangleMesh):
-                                                               btTriangleRaycastCallback(from,to),
+                                                       BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,bool faceNormal,
+                                                               btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
+                                                               btTriangleRaycastCallback(from,to,faceNormal),
                                                                        m_resultCallback(resultCallback),
                                                                        m_collisionObject(collisionObject),
                                                                        m_triangleMesh(triangleMesh)
@@ -272,6 +276,7 @@ void        btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
                                                                btCollisionWorld::LocalShapeInfo        shapeInfo;
                                                                shapeInfo.m_shapePart = partId;
                                                                shapeInfo.m_triangleIndex = triangleIndex;
+                                                               shapeInfo.m_triangleShape = m_triangleMesh;
                                                                
                                                                btCollisionWorld::LocalRayResult rayResult
                                                                (m_collisionObject, 
@@ -287,7 +292,7 @@ void        btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
                                                };
 
 
-                                               BridgeTriangleRaycastCallback   rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
+                                               BridgeTriangleRaycastCallback   rcb(rayFromLocal,rayToLocal,faceNormal,&resultCallback,collisionObject,triangleMesh);
                                                rcb.m_hitFraction = resultCallback.m_closestHitFraction;
 
                                                btVector3 rayAabbMinLocal = rayFromLocal;
@@ -313,7 +318,7 @@ void        btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
                                                                        collisionObject,
                                                                        childCollisionShape,
                                                                        childWorldTrans,
-                                                                       resultCallback, collisionFilterMask);
+                                                                       resultCallback, collisionFilterMask, faceNormal);
 
                                                        }
 
@@ -323,7 +328,7 @@ void        btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
                        }
 }
 
-void   btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask)
+void   btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask, bool faceNormal)
 {
 
        
@@ -350,11 +355,17 @@ void      btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r
                        btVector3 hitNormal;
                        if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
                        {
-                               rayTestSingle(rayFromTrans,rayToTrans,
-                                       collisionObject,
-                                               collisionObject->getCollisionShape(),
-                                               collisionObject->getWorldTransform(),
-                                               resultCallback);
+                               // before testing this object, verify that it is not filtered out
+                               if (resultCallback.NeedRayCast(collisionObject))
+                               {
+                                       rayTestSingle(rayFromTrans,rayToTrans,
+                                               collisionObject,
+                                                       collisionObject->getCollisionShape(),
+                                                       collisionObject->getWorldTransform(),
+                                                       resultCallback,
+                                                       collisionFilterMask,
+                                                       faceNormal);
+                               }
                        }       
                }
        }
index b6d80233ab7acbd927774aed8dc188e5e90f5e92..ed41232ece3fe091158e658bcb55ff2c5f9629ac 100644 (file)
@@ -125,8 +125,8 @@ public:
        {
                int     m_shapePart;
                int     m_triangleIndex;
-               
-               //const btCollisionShape*       m_shapeTemp;
+               // needed in case of compound shape
+               const btCollisionShape* m_triangleShape;
                //const btTransform*    m_shapeLocalTransform;
        };
 
@@ -166,6 +166,10 @@ public:
                        :m_closestHitFraction(btScalar(1.))
                {
                }
+               virtual bool        NeedRayCast(btCollisionObject* object)
+               {
+                       return true;
+               }
                virtual btScalar        AddSingleResult(LocalRayResult& rayResult) = 0;
        };
 
@@ -209,7 +213,7 @@ public:
 
        /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
        /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
-       void    rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1);
+       void    rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1, bool faceNormal=false);
 
        /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
        /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
@@ -218,14 +222,18 @@ public:
                                          btCollisionObject* collisionObject,
                                          const btCollisionShape* collisionShape,
                                          const btTransform& colObjWorldTransform,
-                                         RayResultCallback& resultCallback, short int collisionFilterMask=-1);
+                                         RayResultCallback& resultCallback, 
+                                         short int collisionFilterMask=-1,
+                                         bool faceNormal=false);
 
        /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
        static void     objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
                                          btCollisionObject* collisionObject,
                                          const btCollisionShape* collisionShape,
                                          const btTransform& colObjWorldTransform,
-                                         RayResultCallback& resultCallback, short int collisionFilterMask=-1);
+                                         RayResultCallback& resultCallback, 
+                                         short int collisionFilterMask=-1,
+                                         bool faceNormal=false);
 
        void    addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1);
 
index 31b914677777ed643da4ff85a41f93080b2c4c52..68ac93ec3cca5e204550ab344441927ac5e63508 100644 (file)
@@ -16,10 +16,11 @@ subject to the following restrictions:
 
 #include "btRaycastCallback.h"
 
-btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to)
+btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to,bool faceNormal)
        :
        m_from(from),
        m_to(to),
+       m_faceNormal(faceNormal),
        m_hitFraction(btScalar(1.))
 {
 
@@ -84,8 +85,7 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
                                        
                                        if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) 
                                        {
-
-                                               if ( dist_a > 0 )
+                                               if (m_faceNormal || dist_a > 0)
                                                {
                                                        m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
                                                }
index a0bbc9f8fe95f45f7dc128a8f14d7f88e9fc7675..71ed9fead49fd3c3cd1a2da849b5d31f80ab4f53 100644 (file)
@@ -27,10 +27,11 @@ public:
                //input
        btVector3 m_from;
        btVector3 m_to;
+       bool m_faceNormal;
 
        btScalar        m_hitFraction;
 
-       btTriangleRaycastCallback(const btVector3& from,const btVector3& to);
+       btTriangleRaycastCallback(const btVector3& from,const btVector3& to,bool faceNormal);
        
        virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
 
index 0ea3503a289f2cd6a2ac849dd40b91dea88faf81..42dcc843091592263c3db2e00ec4e6974d388159 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\intern\script.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\intern\shrinkwrap.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\intern\softbody.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_script.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\BKE_shrinkwrap.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_softbody.h">
                        </File>
index c046d434cb34c14a93134a7e54ad05f1dfb8fad8..4e362faed69edcf3631ec2314e1a80dd92b07fb6 100644 (file)
                        <File
                                RelativePath="..\..\..\source\gameengine\Ketsji\KX_PolygonMaterial.cpp">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\gameengine\Ketsji\KX_PolyProxy.cpp">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\gameengine\Ketsji\KX_PyConstraintBinding.cpp">
                        </File>
                        <File
                                RelativePath="..\..\..\source\gameengine\Ketsji\KX_PolygonMaterial.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\gameengine\Ketsji\KX_PolyProxy.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\gameengine\Ketsji\KX_PyConstraintBinding.h">
                        </File>
index 6082af3033fb2312859b6294d9f7bb8d9feabd6a..9f49dd4587a436a35a74d6ec5d842fa6e359793e 100644 (file)
@@ -56,7 +56,7 @@
   information, claims of third parties, damages as a result of injury to
   any person, or any other loss) arising out of or in connection with the
   license granted under this License Agreement or the use of or inability
-  to use the Software, even if VF has been advised of the possibility of
+  to use the Software, even if BF has been advised of the possibility of
   such damages. 
    
   5. User warning and indemnification
index d06962cbe3f5e0f339d79ef132e08b49b0641d5f..91dd17d73dd49d211789e65b8e62dc6b26fe674e 100644 (file)
@@ -250,6 +250,7 @@ SPLIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
 # but somehow it consistently fails to resolve these symbols... or 
 # can I just not check them? nm claims they aren't...
 SPLIB += $(OCGDIR)/blender/blenkernel/blenkernel_blc/$(DEBUG_DIR)libblenkernel_blc.a
+SPLIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a
 
 # These three need to be explicitly mentioned on the cl, because 
 # if they are offered as a lib, they are optimized away. (nzc)
index 73a9b2b5d4eb7565f7cdc2c12b85cf1b15fc9a98..e982806a6cc60958e27cec47581d8e9522cc149d 100644 (file)
@@ -38,6 +38,7 @@
 struct Object;
 struct ListBase;
 struct bDeformGroup;
+struct MDeformVert;
 
 void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2);
 struct bDeformGroup *copy_defgroup (struct bDeformGroup *ingroup);
index 0842e55a0eaa51a7d829e1894f76156c61b06371..72f70cf17ff520ca5b69b95d8b38840f6d11c1db 100644 (file)
@@ -406,12 +406,15 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
                        else
                                VecCopyf(mag_vec,vec_to_part);
 
+                       Normalize(mag_vec);
+
                        VecMulf(mag_vec,force_val*falloff);
                        VecAddf(field,field,mag_vec);
                        break;
 
                case PFIELD_VORTEX:
                        Crossf(mag_vec,eff_vel,vec_to_part);
+
                        Normalize(mag_vec);
 
                        VecMulf(mag_vec,force_val*distance*falloff);
@@ -425,6 +428,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
                                /* magnetic field of a moving charge */
                                Crossf(temp,eff_vel,vec_to_part);
 
+                       Normalize(temp);
+
                        Crossf(temp2,velocity,temp);
                        VecAddf(mag_vec,mag_vec,temp2);
 
@@ -437,6 +442,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
                        else
                                VecCopyf(mag_vec,vec_to_part);
 
+                       Normalize(mag_vec);
+
                        VecMulf(mag_vec,force_val*falloff);
                        VecSubf(field,field,mag_vec);
 
@@ -451,6 +458,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
                        else
                                VecCopyf(mag_vec,vec_to_part);
 
+                       Normalize(mag_vec);
+
                        VecMulf(mag_vec,charge*force_val*falloff);
                        VecAddf(field,field,mag_vec);
                        break;
@@ -535,10 +544,6 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float
                where_is_object_time(ob,cur_time);
                        
                /* use center of object for distance calculus */
-               obloc= ob->obmat[3];
-               VECSUB(vect_to_vert, obloc, opco);
-               distance = VecLength(vect_to_vert);
-               
                VecSubf(vec_to_part, opco, ob->obmat[3]);
                distance = VecLength(vec_to_part);
 
index 4ba4f6b02f92b4e139d3260934d561be088131ea..800775eb2b3ce4db0f3c997bc89b1884b81b94ef 100644 (file)
@@ -1674,6 +1674,8 @@ void set_icu_vars(IpoCurve *icu)
                                icu->ymax= 5.0; break;
                        case MA_ADD:
                                icu->ymax= 1.0; break;
+                       case MA_EMIT:
+                               icu->ymax= 2.0; break;
                        default:
                                icu->ymax= 1.0; break;
                        }
index 2f4696fc442189c373c8d00bcdd12bc4d4680713..15d6f71073f25272eca2359d2dacf2e84decedab 100644 (file)
@@ -379,8 +379,11 @@ void psys_free_children(ParticleSystem *psys)
 }
 /* free everything */
 void psys_free(Object *ob, ParticleSystem * psys)
-{
+{      
        if(psys){
+               int nr = 0;
+               ParticleSystem * tpsys;
+               
                if(ob->particlesystem.first == NULL && G.f & G_PARTICLEEDIT)
                        G.f &= ~G_PARTICLEEDIT;
 
@@ -406,6 +409,21 @@ void psys_free(Object *ob, ParticleSystem * psys)
 
                if(psys->effectors.first)
                        psys_end_effectors(psys);
+               
+               // check if we are last non-visible particle system
+               for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){
+                       if(tpsys->part)
+                       {
+                               if(ELEM(tpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR))
+                               {
+                                       nr++;
+                                       break;
+                               }
+                       }
+               }
+               // clear do-not-draw-flag
+               if(!nr)
+                       ob->transflag &= ~OB_DUPLIPARTS;
 
                if(psys->part){
                        psys->part->id.us--;            
@@ -417,7 +435,7 @@ void psys_free(Object *ob, ParticleSystem * psys)
 
                if(psys->pointcache)
                        BKE_ptcache_free(psys->pointcache);
-
+               
                MEM_freeN(psys);
        }
 }
index 98bf817381904401d7fdff4e752c2c55a47405bc..4ec9f7a95de13177dc324ec58a9aec9e33db7ae9 100644 (file)
@@ -2301,7 +2301,15 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy
                        }
                }
                else if(pd->forcefield)
+               {
                        type |= PSYS_EC_EFFECTOR;
+                       
+                       if(pd->forcefield == PFIELD_WIND)
+                       {
+                               pd->rng = rng_new(1);
+                               rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed
+                       }
+               }
        }
        
        if(pd && pd->deflect)
@@ -2413,6 +2421,9 @@ void psys_end_effectors(ParticleSystem *psys)
 
                        if(ec->tree)
                                BLI_kdtree_free(ec->tree);
+                       
+                       if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND))
+                               rng_free(ec->ob->pd->rng);
                }
 
                BLI_freelistN(lb);
index 292a800e9cd677b843b53bf4576353135740923a..c60535cade2511e0bf03dac736b349037023b3fc 100644 (file)
@@ -113,23 +113,23 @@ void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float
 
 void space_transform_apply(const SpaceTransform *data, float *co)
 {
-       VecMat4MulVecfl(co, data->local2target, co);
+       VecMat4MulVecfl(co, ((SpaceTransform*)data)->local2target, co);
 }
 
 void space_transform_invert(const SpaceTransform *data, float *co)
 {
-       VecMat4MulVecfl(co, data->target2local, co);
+       VecMat4MulVecfl(co, ((SpaceTransform*)data)->target2local, co);
 }
 
 void space_transform_apply_normal(const SpaceTransform *data, float *no)
 {
-       Mat4Mul3Vecfl(data->local2target, no);
+       Mat4Mul3Vecfl( ((SpaceTransform*)data)->local2target, no);
        Normalize(no); // TODO: could we just determine de scale value from the matrix?
 }
 
 void space_transform_invert_normal(const SpaceTransform *data, float *no)
 {
-       Mat4Mul3Vecfl(data->target2local, no);
+       Mat4Mul3Vecfl(((SpaceTransform*)data)->target2local, no);
        Normalize(no); // TODO: could we just determine de scale value from the matrix?
 }
 
@@ -291,7 +291,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
                space_transform_apply_normal( transf, tmp_no );
                no = tmp_no;
 
-               hit_tmp.dist *= Mat4ToScalef( transf->local2target );
+               hit_tmp.dist *= Mat4ToScalef( ((SpaceTransform*)transf)->local2target );
        }
        else
        {
@@ -318,7 +318,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
                        space_transform_invert( transf, hit_tmp.co );
                        space_transform_invert_normal( transf, hit_tmp.no );
 
-                       hit_tmp.dist = VecLenf( vert, hit_tmp.co );
+                       hit_tmp.dist = VecLenf( (float*)vert, hit_tmp.co );
                }
 
                memcpy(hit, &hit_tmp, sizeof(hit_tmp) );
index 11150075bac763f33cf821ae51e1c96f79645212..3bb63506c9551313702292116c5c3c3cbb133cca 100644 (file)
 
        // These definitions are also in arithb for simplicity
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifndef M_PI
 #define M_PI           3.14159265358979323846
 #endif
@@ -116,5 +120,9 @@ int closedir (DIR *dp);
 void get_default_root(char *root);
 int check_file_chars(char *filename);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __WINSTUFF_H__ */
 
index c41c3d8c3ab67d16cde2b830b5751485a4ca1f12..989e516d161f6d164d25baf4df996b9f9a25ae5d 100644 (file)
@@ -82,7 +82,7 @@ typedef struct BVHOverlapData
 typedef struct BVHNearestData
 {
        BVHTree *tree;
-       float   *co;
+       const float     *co;
        BVHTree_NearestPointCallback callback;
        void    *userdata;
        float proj[13];                 //coordinates projection over axis
@@ -1248,7 +1248,6 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
 
 static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node)
 {
-       int i;
        float nearest[3], sdist;
        sdist = calc_nearest_point(data, node, nearest);
        if(sdist >= data->nearest.dist) return;
index 7340a2e44e0d43bf23790e4859727b41fb20efe6..9b9294b0343fab9c34db32b5cf04c0fe4661b7a7 100644 (file)
@@ -76,6 +76,9 @@ void gpencil_delete_laststroke(struct bGPdata *gpd);
 void gpencil_delete_operation(short mode);
 void gpencil_delete_menu(void);
 
+void gpencil_convert_operation(short mode);
+void gpencil_convert_menu(void);
+
 //short gpencil_paint(short mousebutton);
 short gpencil_do_paint(struct ScrArea *sa, short mousebutton);
 
index 07fc8f08b4a0a7be2e51fb366e15be1f4f10dc85..fdd00a674659f075721752681a0b664a0dad75e3 100644 (file)
@@ -91,6 +91,7 @@ void  free_editArmature(void);
 
 int            join_armature(void);
 void   separate_armature(void);
+void   apply_armature_pose2bones(void);
 void   load_editArmature(void);
 
 void   make_bone_parent(void);
@@ -99,13 +100,14 @@ struct Bone        *get_indexed_bone (struct Object *ob, int index);
 
 void   make_editArmature(void);
 void   make_trans_bones (char mode);
+void   remake_editArmature(void);
+void   editbones_to_armature(struct ListBase *list, struct Object *ob);
 
 int            do_pose_selectbuffer(struct Base *base, unsigned int *buffer, short hits);
 
 void generateSkeleton(void);
 
 void   mouse_armature(void);
-void   remake_editArmature(void);
 void   selectconnected_armature(void);
 void   selectconnected_posearmature(void);
 void   armature_select_hierarchy(short direction, short add_to_sel);
index d2c6c56d01a2da3258b2c4fbfc82e9a33d317ebd..204733a19d68d160fff82dab1dc5af47fd730320 100644 (file)
@@ -40,6 +40,7 @@ void  arrows_move_cursor(unsigned short event);
 void   lasso_select_boundbox(struct rcti *rect, short mcords[][2], short moves);
 int            lasso_inside(short mcords[][2], short moves, short sx, short sy);
 int    lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1);
+int    edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2);
 void   borderselect(void);
 void   circle_select(void);
 void   deselectall(void);
index 932f103a579b755c7ac67e967bbd99030a2682c5..b8388b2172af960bb27f2a2cb47c78a457132d0e 100644 (file)
@@ -42,6 +42,7 @@ struct ScrArea;
 struct EditIpo;
 struct View2D;
 struct rctf;
+struct SpaceLink;
 
 void calc_ipogrid(void);
 void draw_ipogrid(void);
@@ -50,6 +51,8 @@ void areamouseco_to_ipoco     (struct View2D *v2d, short *mval, float *x, float *y);
 void ipoco_to_areaco           (struct View2D *v2d, float *vec, short *mval);
 void ipoco_to_areaco_noclip    (struct View2D *v2d, float *vec, short *mval);
 
+struct View2D *spacelink_get_view2d(struct SpaceLink *sl);
+
 void view2d_do_locks           (struct ScrArea *cursa, int flag);
 void view2d_zoom                       (struct View2D *v2d, float factor, int winx, int winy);
 void view2d_getscale           (struct View2D *v2d, float *x, float *y);
index 720b856a14941e9c31a5ab7911f1960631d88c0d..51fa39ff9d6bd702c459c1d6ad32ee5cd094f241 100644 (file)
@@ -466,7 +466,6 @@ int validSnappingNormal(TransInfo *t);
 /*********************** Generics ********************************/
 
 void initTrans(TransInfo *t);
-void initTransModeFlags(TransInfo *t, int mode);
 void postTrans (TransInfo *t);
 
 void drawLine(float *center, float *dir, char axis, short options);
@@ -498,6 +497,7 @@ TransInfo * BIF_GetTransInfo(void);
 
 /*********************** NumInput ********************************/
 
+void initNumInput(NumInput *n);
 void outputNumInput(NumInput *n, char *str);
 short hasNumInput(NumInput *n);
 void applyNumInput(NumInput *n, float *vec);
index 7444ce95f56a47de24e3e868b6290d48bfc805ba..59d0555b4523072e4b9389229b3698a8e2e8428a 100644 (file)
@@ -81,7 +81,9 @@ typedef struct bEditObjectActuator {
        struct Mesh *me;
        char name[32];
        float linVelocity[3]; /* initial lin. velocity on creation */
-       short localflag; /* flag for the lin. vel: apply locally   */
+       float angVelocity[3]; /* initial ang. velocity on creation */
+       float pad;
+       short localflag; /* flag for the lin & ang. vel: apply locally   */
        short dyn_operation;
 } bEditObjectActuator;
 
@@ -384,6 +386,9 @@ typedef struct FreeCamera {
 #define ACT_EDOB_TRACK_TO              3
 #define ACT_EDOB_DYNAMICS              4
 
+/* editObjectActuator->localflag */
+#define ACT_EDOB_LOCAL_LINV            2
+#define ACT_EDOB_LOCAL_ANGV            4
 
 
 /* editObjectActuator->flag */
index 13d412c2c42899803d3c950e6ee431a63304e50d..cc0c99120572ca33ce3d6539e99d61537e59a82a 100644 (file)
@@ -61,7 +61,7 @@ typedef struct bGPDstroke {
 #define GP_STROKE_2DSPACE              (1<<1)
        /* stroke is in 2d-space (but with special 'image' scaling) */
 #define GP_STROKE_2DIMAGE              (1<<2)
-       /* stroke is an "eraser" stroke */
+       /* only for use with stroke-buffer (while drawing eraser) */
 #define GP_STROKE_ERASER               (1<<15)
 
 
index b5d8511c6981e94979d4228ba3338749c360ddcd..3e0075c00bde7a7c5b49c2a812dff27a519b56ff 100644 (file)
@@ -164,7 +164,7 @@ typedef struct bSensor {
 typedef struct bJoystickSensor {
        char name[32];
        short type;
-       short pad;
+       short joyindex;
        int axis;
        int axisf;
        int button;
@@ -237,6 +237,9 @@ typedef struct bJoystickSensor {
  * */
 /*  #define SENS_COLLISION_PROPERTY 0  */
 #define SENS_COLLISION_MATERIAL 1
+/* ray specific mode */
+/* X-Ray means that the ray will traverse objects that don't have the property/material */
+#define SENS_RAY_XRAY                  2
 
 /* Some stuff for the mouse sensor Type: */
 #define BL_SENS_MOUSE_LEFT_BUTTON    1
@@ -263,6 +266,7 @@ typedef struct bJoystickSensor {
 #define SENS_JOY_HAT_DIR               0
 
 #define SENS_DELAY_REPEAT              1
-
+// should match JOYINDEX_MAX in SCA_JoystickDefines.h */
+#define SENS_JOY_MAXINDEX              8
 #endif
 
index 2c2e724129ed7a63b048e6d4e78c6a297a5eaaa9..bc65426e16c1e332fde279c4e896e7568bda2db1 100644 (file)
@@ -804,7 +804,7 @@ static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args )
 {
        ParticleSystem *psys = 0L;
        Object *ob = 0L;
-       PyObject *partlist,*seglist;
+       PyObject *partlist,*seglist=0L;
        ParticleCacheKey **cache,*path;
        PyObject* loc = 0L;
        ParticleKey state;
@@ -1107,7 +1107,7 @@ static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args )
        ParticleSystem *psys = 0L;
        ParticleData *data;
        Object *ob = 0L;
-       PyObject *partlist,*tuple;
+       PyObject *partlist,*tuple=0L;
        DerivedMesh* dm;
        float vm[4][4],wm[4][4];
        float size;
@@ -1217,7 +1217,7 @@ static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args )
        ParticleSystem *psys = 0L;
        ParticleData *data;
        Object *ob = 0L;
-       PyObject *partlist,*tuple;
+       PyObject *partlist,*tuple=0L;
        DerivedMesh* dm;
        float vm[4][4],wm[4][4];
        float life;
index 551006ffcc3bfec2acff33e072ac89a474d37bc4..0cf962052a36b19291d28d40ebb859b1d59c34cd 100644 (file)
@@ -1477,7 +1477,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0);
        float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2];
        int i, a, k, max_k=0, totpart, totuv=0, totcol=0, override_uv=-1, dosimplify = 0, dosurfacecache = 0;
-       int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild;
+       int path_possible=0, keys_possible=0, baked_keys=0, totchild=0;
        int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num;
        int totface, *origindex = 0;
        char **uv_name=0;
@@ -1485,6 +1485,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 /* 1. check that everything is ok & updated */
        if(psys==NULL)
                return 0;
+       
+       totchild=psys->totchild;
 
        part=psys->part;
        pars=psys->particles;
index 2dd6d705a9edf05a33d09ac1f03ede41a9dc3231..0b6986c2c8ef7d1f5dbc6b7e921c1fb20cba36a6 100644 (file)
@@ -1390,9 +1390,14 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short
                                        &raySens->propname, 0, 31, 0, 0,
                                        "Only look for Objects with this property");
                        }
-                       
+
+                       /* X-Ray option */
+                       uiDefButBitS(block, TOG, SENS_RAY_XRAY, 1, "X",
+                               xco + 10,yco - 68, 0.10 * (width-20), 19,
+                               &raySens->mode, 0.0, 0.0, 0, 0,
+                               "Toggle X-Ray option (see through objects that don't have the property)");
                        /* 2. sensing range */
-                       uiDefButF(block, NUM, 1, "Range", xco+10, yco-68, 0.6 * (width-20), 19,
+                       uiDefButF(block, NUM, 1, "Range", xco+10 + 0.10 * (width-20), yco-68, 0.5 * (width-20), 19,
                                &raySens->range, 0.01, 10000.0, 100, 0,
                                "Sense objects no farther than this distance");
                        
@@ -1439,10 +1444,13 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short
                        draw_default_sensor_header(sens, block, xco, yco, width);
 
                        joy= sens->data;
-                       
+
+                       uiDefButS(block, NUM, 1, "Index:", xco+10, yco-44, 0.6 * (width-120), 19,
+                       &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0,
+                       "Spesify which joystick to use");                       
 
                        str= "Type %t|Button %x0|Axis %x1|Hat%x2"; 
-                       uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, 0.6 * (width-20), 19,
+                       uiDefButS(block, MENU, B_REDR, str, xco+87, yco-44, 0.6 * (width-150), 19,
                                &joy->type, 0, 31, 0, 0,
                                "The type of event this joystick sensor is triggered on.");
                        
@@ -1857,7 +1865,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE, 
                                "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19, 
                                &ia->flag, 0, 0, 0, 0, 
-                               "Convert Ipo to force. Force is applied in global or local coordinate according to Local flag"); 
+                               "Apply Ipo as a global or local force depending on the local option (dynamic objects only)"); 
                        uiButSetFunc(but, change_ipo_actuator, but, ia);
 
                        but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD, 
@@ -2022,7 +2030,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
 
                if(eoa->type==ACT_EDOB_ADD_OBJECT) {
                        int wval; /* just a temp width */
-                       ysize = 72;
+                       ysize = 92;
                        glRects(xco, yco-ysize, xco+width, yco);
                        uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
         
@@ -2042,9 +2050,27 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-68, wval, 19,
                                         eoa->linVelocity+2, -100.0, 100.0, 10, 0,
                                         "Velocity upon creation, z component.");
-                       uiDefButBitS(block, TOG, 2, 0, "L", xco+45+3*wval, yco-68, 15, 19,
+                       uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_LINV, 0, "L", xco+45+3*wval, yco-68, 15, 19,
                                         &eoa->localflag, 0.0, 0.0, 0, 0,
                                         "Apply the transformation locally");
+                       
+                       
+                       uiDefBut(block, LABEL, 0, "AngV",       xco,           yco-90,   45, 19,
+                                        NULL, 0, 0, 0, 0,
+                                        "Angular velocity upon creation.");
+                       uiDefButF(block, NUM, 0, "",            xco+45,        yco-90, wval, 19,
+                                        eoa->angVelocity, -10000.0, 10000.0, 10, 0,
+                                        "Angular velocity upon creation, x component.");
+                       uiDefButF(block, NUM, 0, "",            xco+45+wval,   yco-90, wval, 19,
+                                        eoa->angVelocity+1, -10000.0, 10000.0, 10, 0,
+                                        "Angular velocity upon creation, y component.");
+                       uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-90, wval, 19,
+                                        eoa->angVelocity+2, -10000.0, 10000.0, 10, 0,
+                                        "Angular velocity upon creation, z component.");
+                       uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_ANGV, 0, "L", xco+45+3*wval, yco-90, 15, 19,
+                                        &eoa->localflag, 0.0, 0.0, 0, 0,
+                                        "Apply the rotation locally");
+                                        
 
                }
                else if(eoa->type==ACT_EDOB_END_OBJECT) {
index 22f7fdc32f0d020d77cdd901a55a8a59b90f0a40..15f65bfe3cf120143a05f3272c76143955119216 100644 (file)
@@ -145,6 +145,13 @@ void gp_ui_delframe_cb (void *gpd, void *gpl)
        allqueue(REDRAWACTION, 0);
 }
 
+/* convert the active layer to geometry */
+void gp_ui_convertlayer_cb (void *gpd, void *gpl)
+{
+       gpencil_layer_setactive(gpd, gpl);
+       gpencil_convert_menu();
+}
+
 /* ------- Drawing Code ------- */
 
 /* draw the controls for a given layer */
@@ -166,7 +173,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
                /* rounded header */
                if (active) uiBlockSetCol(block, TH_BUT_ACTION);
                        rb_col= (active)?-20:20;
-                       uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); 
+                       uiDefBut(block, ROUNDBOX, B_REDR, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); 
                if (active) uiBlockSetCol(block, TH_AUTO);
                
                /* lock toggle */
@@ -177,7 +184,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
        if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
                char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
                
-               height= 26;
+               height= 0;
                
                /* visibility button (only if hidden but not locked!) */
                if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
@@ -249,8 +256,14 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
                        
                        /* options */
                        uiBlockBeginAlign(block);
-                               but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)");
-                               uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
+                               if (curarea->spacetype == SPACE_VIEW3D) {
+                                       but= uiDefBut(block, BUT, B_REDR, "Convert to...", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Converts this layer's strokes to geometry (Hotkey = Alt-Shift-C)");
+                                       uiButSetFunc(but, gp_ui_convertlayer_cb, gpd, gpl);
+                               }
+                               else {
+                                       but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)");
+                                       uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
+                               }
                                
                                but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)");
                                uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
@@ -323,6 +336,9 @@ enum {
        GP_DRAWDATA_ONLYI2D             = (1<<3),       /* only draw 'image' strokes */
 };
 
+/* thickness above which we should use special drawing */
+#define GP_DRAWTHICKNESS_SPECIAL       3
+
 /* ----- Tool Buffer Drawing ------ */
 
 /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
@@ -347,23 +363,13 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick
                glEnd();
        }
        else if (sflag & GP_STROKE_ERASER) {
-               /* draw stroke curve - just standard thickness */
-               setlinestyle(4);
-               glLineWidth(1.0f);
-               
-               glBegin(GL_LINE_STRIP);
-               for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
-                       glVertex2f(pt->x, pt->y);
-               }
-               glEnd();
-               
-               setlinestyle(0);
+               /* don't draw stroke at all! */
        }
        else {
                float oldpressure = 0.0f;
                
                /* draw stroke curve */
-               setlinestyle(2);
+               if (G.f & G_DEBUG) setlinestyle(2);
                
                glBegin(GL_LINE_STRIP);
                for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
@@ -381,14 +387,14 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick
                }
                glEnd();
                
-               setlinestyle(0);
+               if (G.f & G_DEBUG) setlinestyle(0);
        }
 }
 
 /* ----- Existing Strokes Drawing (3D and Point) ------ */
 
 /* draw a given stroke - just a single dot (only one point) */
-static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, int winy)
+static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short sflag, int winx, int winy)
 {
        /* draw point */
        if (sflag & GP_STROKE_3DSPACE) {
@@ -396,18 +402,38 @@ static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, int
                        glVertex3f(points->x, points->y, points->z);
                glEnd();
        }
-       else if (sflag & GP_STROKE_2DSPACE) {
-               glBegin(GL_POINTS);
-                       glVertex2f(points->x, points->y);
-               glEnd();
-       }
        else {
-               const float x= (points->x / 1000 * winx);
-               const float y= (points->y / 1000 * winy);
+               float co[2];
                
-               glBegin(GL_POINTS);
-                       glVertex2f(x, y);
-               glEnd();
+               /* get coordinates of point */
+               if (sflag & GP_STROKE_2DSPACE) {
+                       co[0]= points->x;
+                       co[1]= points->y;
+               }
+               else {
+                       co[0]= (points->x / 1000 * winx);
+                       co[1]= (points->y / 1000 * winy);
+               }
+               
+               /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple opengl point will do */
+               if (thickness < GP_DRAWTHICKNESS_SPECIAL) {
+                       glBegin(GL_POINTS);
+                               glVertex2fv(co);
+                       glEnd();
+               }
+               else {
+                       /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */
+                       GLUquadricObj *qobj = gluNewQuadric(); 
+                       
+                       gluQuadricDrawStyle(qobj, GLU_FILL); 
+                       
+                       /* need to translate drawing position, but must reset after too! */
+                       glTranslatef(co[0],  co[1], 0.); 
+                       gluDisk( qobj, 0.0,  thickness, 32, 1); 
+                       glTranslatef(-co[0],  -co[1], 0.);
+                       
+                       gluDeleteQuadric(qobj);
+               }
        }
 }
 
@@ -449,8 +475,8 @@ static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thicknes
 /* draw a given stroke in 2d */
 static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy)
 {      
-       /* if thickness is less than 3, 'smooth' opengl lines look better */
-       if ((thickness < 3) || (G.rt==0)) {
+       /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better */
+       if (thickness < GP_DRAWTHICKNESS_SPECIAL) {
                bGPDspoint *pt;
                int i;
                
@@ -472,19 +498,15 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
                bGPDspoint *pt1, *pt2;
                float pm[2];
                int i;
-               short n;
                
                glShadeModel(GL_FLAT);
-               
-               glPointSize(3.0f); // temp
-               
-               for (n= 0; n < 2; n++) { // temp
-               glBegin((n)?GL_POINTS:GL_QUADS);
+               glBegin(GL_QUADS);
                
                for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) {
                        float s0[2], s1[2];             /* segment 'center' points */
                        float t0[2], t1[2];             /* tesselated coordinates */
                        float m1[2], m2[2];             /* gradient and normal */
+                       float mt[2], sc[2];             /* gradient for thickness, point for end-cap */
                        float pthick;                   /* thickness at segment point */
                        
                        /* get x and y coordinates from points */
@@ -502,42 +524,75 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
                        /* calculate gradient and normal - 'angle'=(ny/nx) */
                        m1[1]= s1[1] - s0[1];           
                        m1[0]= s1[0] - s0[0];
+                       Normalize2(m1);
                        m2[1]= -m1[0];
                        m2[0]= m1[1];
-                       Normalize2(m2);
                        
                        /* always use pressure from first point here */
                        pthick= (pt1->pressure * thickness);
                        
                        /* if the first segment, start of segment is segment's normal */
                        if (i == 0) {
-                               // TODO: also draw/do a round end-cap first
+                               /* draw start cap first 
+                                *      - make points slightly closer to center (about halfway across) 
+                                */                             
+                               mt[0]= m2[0] * pthick * 0.5;
+                               mt[1]= m2[1] * pthick * 0.5;
+                               sc[0]= s0[0] - (m1[0] * pthick * 0.75);
+                               sc[1]= s0[1] - (m1[1] * pthick * 0.75);
+                               
+                               t0[0]= sc[0] - mt[0];
+                               t0[1]= sc[1] - mt[1];
+                               t1[0]= sc[0] + mt[0];
+                               t1[1]= sc[1] + mt[1];
+                               
+                               glVertex2fv(t0);
+                               glVertex2fv(t1);
                                
                                /* calculate points for start of segment */
-                               t0[0]= s0[0] - (pthick * m2[0]);
-                               t0[1]= s0[1] - (pthick * m2[1]);
-                               t1[0]= s0[0] + (pthick * m2[0]);
-                               t1[1]= s0[1] + (pthick * m2[1]);
+                               mt[0]= m2[0] * pthick;
+                               mt[1]= m2[1] * pthick;
+                               
+                               t0[0]= s0[0] - mt[0];
+                               t0[1]= s0[1] - mt[1];
+                               t1[0]= s0[0] + mt[0];
+                               t1[1]= s0[1] + mt[1];
                                
-                               /* draw this line only once */
+                               /* draw this line twice (first to finish off start cap, then for stroke) */
+                               glVertex2fv(t1);
+                               glVertex2fv(t0);
                                glVertex2fv(t0);
                                glVertex2fv(t1);
                        }
                        /* if not the first segment, use bisector of angle between segments */
                        else {
-                               float mb[2];    /* bisector normal */
+                               float mb[2];            /* bisector normal */
+                               float athick, dfac;             /* actual thickness, difference between thicknesses */
                                
                                /* calculate gradient of bisector (as average of normals) */
                                mb[0]= (pm[0] + m2[0]) / 2;
                                mb[1]= (pm[1] + m2[1]) / 2;
                                Normalize2(mb);
                                
+                               /* calculate gradient to apply 
+                                *      - as basis, use just pthick * bisector gradient
+                                *      - if cross-section not as thick as it should be, add extra padding to fix it
+                                */
+                               mt[0]= mb[0] * pthick;
+                               mt[1]= mb[1] * pthick;
+                               athick= Vec2Length(mt);
+                               dfac= pthick - (athick * 2);
+                               if ( ((athick * 2) < pthick) && (IS_EQ(athick, pthick)==0) ) 
+                               {
+                                       mt[0] += (mb[0] * dfac);
+                                       mt[1] += (mb[1] * dfac);
+                               }       
+                               
                                /* calculate points for start of segment */
-                               // FIXME: do we need extra padding for acute angles?
-                               t0[0]= s0[0] - (pthick * mb[0]);
-                               t0[1]= s0[1] - (pthick * mb[1]);
-                               t1[0]= s0[0] + (pthick * mb[0]);
-                               t1[1]= s0[1] + (pthick * mb[1]);
+                               t0[0]= s0[0] - mt[0];
+                               t0[1]= s0[1] - mt[1];
+                               t1[0]= s0[0] + mt[0];
+                               t1[1]= s0[1] + mt[1];
                                
                                /* draw this line twice (once for end of current segment, and once for start of next) */
                                glVertex2fv(t1);
@@ -552,16 +607,36 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
                                pthick= (pt2->pressure * thickness);
                                
                                /* calculate points for end of segment */
-                               t0[0]= s1[0] - (pthick * m2[0]);
-                               t0[1]= s1[1] - (pthick * m2[1]);
-                               t1[0]= s1[0] + (pthick * m2[0]);
-                               t1[1]= s1[1] + (pthick * m2[1]);
+                               mt[0]= m2[0] * pthick;
+                               mt[1]= m2[1] * pthick;
                                
-                               /* draw this line only once */
+                               t0[0]= s1[0] - mt[0];
+                               t0[1]= s1[1] - mt[1];
+                               t1[0]= s1[0] + mt[0];
+                               t1[1]= s1[1] + mt[1];
+                               
+                               /* draw this line twice (once for end of stroke, and once for endcap)*/
                                glVertex2fv(t1);
                                glVertex2fv(t0);
+                               glVertex2fv(t0);
+                               glVertex2fv(t1);
                                
-                               // TODO: draw end cap as last step 
+                               
+                               /* draw end cap as last step 
+                                *      - make points slightly closer to center (about halfway across) 
+                                */                             
+                               mt[0]= m2[0] * pthick * 0.5;
+                               mt[1]= m2[1] * pthick * 0.5;
+                               sc[0]= s1[0] + (m1[0] * pthick * 0.75);
+                               sc[1]= s1[1] + (m1[1] * pthick * 0.75);
+                               
+                               t0[0]= sc[0] - mt[0];
+                               t0[1]= sc[1] - mt[1];
+                               t1[0]= sc[0] + mt[0];
+                               t1[1]= sc[1] + mt[1];
+                               
+                               glVertex2fv(t1);
+                               glVertex2fv(t0);
                        }
                        
                        /* store stroke's 'natural' normal for next stroke to use */
@@ -569,7 +644,6 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
                }
                
                glEnd();
-               }
        }
        
        /* draw debug points of curve on top? (original stroke points) */
@@ -623,7 +697,7 @@ static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, shor
                
                /* check which stroke-drawer to use */
                if (gps->totpoints == 1)
-                       gp_draw_stroke_point(gps->points, gps->flag, winx, winy);
+                       gp_draw_stroke_point(gps->points, lthick, gps->flag, winx, winy);
                else if (dflag & GP_DRAWDATA_ONLY3D)
                        gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
                else if (gps->totpoints > 1)    
index 71854570c8c0c3ab325303e73de0d13ba8ba188b..9b5be04eac114d11da2ea3872e57be33b7ce2e62 100644 (file)
@@ -442,7 +442,7 @@ int in_ipo_buttons(void)
        else return 1;
 }
 
-static View2D *spacelink_get_view2d(SpaceLink *sl)
+View2D *spacelink_get_view2d(SpaceLink *sl)
 {
        if(sl->spacetype==SPACE_IPO) 
                return &((SpaceIpo *)sl)->v2d;
index 35986fcff4aa392ea3699a4dbad5946abd0c73b4..5e50c8117cc860ce2abcde7084539f00401ea50f 100644 (file)
@@ -439,6 +439,109 @@ void docenter_armature (Object *ob, int centermode)
        }
 }
 
+/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
+static void applyarmature_fix_boneparents (Object *armob)
+{
+       Object *ob;
+       
+       /* go through all objects in database */
+       for (ob= G.main->object.first; ob; ob= ob->id.next) {
+               /* if parent is bone in this armature, apply corrections */
+               if ((ob->parent == armob) && (ob->partype == PARBONE)) {
+                       /* apply current transform from parent (not yet destroyed), 
+                        * then calculate new parent inverse matrix
+                        */
+                       apply_obmat(ob);
+                       
+                       what_does_parent(ob);
+                       Mat4Invert(ob->parentinv, workob.obmat);
+               }
+       }
+}
+
+/* set the current pose as the restpose */
+void apply_armature_pose2bones(void)
+{
+       Object  *ob;
+       bArmature *arm;
+       bPose *pose;
+       bPoseChannel *pchan;
+       EditBone *curbone;
+       
+       /* don't check if editmode (should be done by caller) */
+       ob= OBACT;
+       if (ob->type!=OB_ARMATURE) return;
+       if (object_data_is_libdata(ob)) {
+               error_libdata();
+               return;
+       }
+       arm= get_armature(ob); 
+       
+       /* helpful warnings... */
+       // TODO: add warnings to be careful about actions, applying deforms first, etc.
+       
+       /* Get editbones of active armature to alter */
+       if (G.edbo.first) BLI_freelistN(&G.edbo);
+       make_boneList(&G.edbo, &arm->bonebase, NULL);
+       
+       /* get pose of active object and move it out of posemode */
+       pose= ob->pose;
+       
+       for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
+               curbone= editbone_name_exists(&G.edbo, pchan->name);
+               
+               /* simply copy the head/tail values from pchan over to curbone */
+               VECCOPY(curbone->head, pchan->pose_head);
+               VECCOPY(curbone->tail, pchan->pose_tail);
+               
+               /* fix roll:
+                *      1. find auto-calculated roll value for this bone now
+                *      2. remove this from the 'visual' y-rotation
+                */
+               {
+                       float premat[3][3], imat[3][3],pmat[3][3], tmat[3][3];
+                       float delta[3], eul[3];
+                       
+                       /* obtain new auto y-rotation */
+                       VecSubf(delta, curbone->tail, curbone->head);
+                       vec_roll_to_mat3(delta, 0.0, premat);
+                       Mat3Inv(imat, premat);
+                       
+                       /* get pchan 'visual' matrix */
+                       Mat3CpyMat4(pmat, pchan->pose_mat);
+                       
+                       /* remove auto from visual and get euler rotation */
+                       Mat3MulMat3(tmat, imat, pmat);
+                       Mat3ToEul(tmat, eul);
+                       
+                       /* just use this euler-y as new roll value */
+                       curbone->roll= eul[1];
+               }
+               
+               /* clear transform values for pchan */
+               pchan->loc[0]= pchan->loc[1]= pchan->loc[2]= 0;
+               pchan->quat[1]= pchan->quat[2]= pchan->quat[3]= 0;
+               pchan->quat[0]= pchan->size[0]= pchan->size[1]= pchan->size[2]= 1;
+               
+               /* set anim lock */
+               curbone->flag |= BONE_UNKEYED;
+       }
+       
+       /* convert editbones back to bones */
+       editbones_to_armature(&G.edbo, ob);
+       if (G.edbo.first) BLI_freelistN(&G.edbo);
+       
+       /* flush positions of posebones */
+       where_is_pose(ob);
+       
+       /* fix parenting of objects which are bone-parented */
+       applyarmature_fix_boneparents(ob);
+       
+       BIF_undo_push("Apply new restpose");
+       allqueue(REDRAWVIEW3D, 0);
+}
+
+
 /* Helper function for armature joining - link fixing */
 static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
 {
index 3615a4ad851729b6aa21d3aa302e30973f957aeb..2b25253dc95d18fc3e27c347bc736e30433a5f86 100644 (file)
@@ -4667,6 +4667,7 @@ int EdgeLoopDelete(void) {
 
 int EdgeSlide(short immediate, float imperc)
 {
+       NumInput num;
        EditMesh *em = G.editMesh;
        EditFace *efa;
        EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
@@ -4683,6 +4684,8 @@ int EdgeSlide(short immediate, float imperc)
        char str[128]; 
        float labda = 0.0f;
        
+       initNumInput(&num);
+               
        view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat);
        
        mvalo[0] = -1; mvalo[1] = -1; 
@@ -4994,17 +4997,84 @@ int EdgeSlide(short immediate, float imperc)
                float v2[2], v3[2];
                EditVert *centerVert, *upVert, *downVert;
                
-               
-
                getmouseco_areawin(mval);  
                
                if (!immediate && (mval[0] == mvalo[0] && mval[1] ==  mvalo[1])) {
                        PIL_sleep_ms(10);
                } else {
+                       char *p = str;;
 
                        mvalo[0] = mval[0];
                        mvalo[1] = mval[1];
                        
+
+                       tempsv = BLI_ghash_lookup(vertgh,nearest);
+
+                       centerVert = editedge_getSharedVert(tempsv->up, tempsv->down);
+                       upVert = editedge_getOtherVert(tempsv->up, centerVert);
+                       downVert = editedge_getOtherVert(tempsv->down, centerVert);
+
+                       view3d_project_float(curarea, upVert->co, v2, projectMat);
+                       view3d_project_float(curarea, downVert->co, v3, projectMat);
+
+                       /* Determine the % on which the loop should be cut */   
+
+                       rc[0]= v3[0]-v2[0];   
+                       rc[1]= v3[1]-v2[1];   
+                       len= rc[0]*rc[0]+ rc[1]*rc[1];
+                       if (len==0) {len = 0.0001;}
+
+                       if ((G.qual & LR_SHIFTKEY)==0) {
+                               wasshift = 0;
+                               labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len;   
+                       }
+                       else {
+                               if (wasshift==0) {
+                                       wasshift = 1;
+                                       shiftlabda = labda;
+                               }                                                       
+                               labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len / 10.0 + shiftlabda;                           
+                       }
+                       
+
+                       if(labda<=0.0) labda=0.0;   
+                       else if(labda>=1.0)labda=1.0;   
+
+                       perc=((1-labda)*2)-1;             
+                       
+                       if(G.qual == 0) {
+                               perc *= 100;
+                               perc = floor(perc);
+                               perc /= 100;
+                       } else if (G.qual == LR_CTRLKEY) {
+                               perc *= 10;
+                               perc = floor(perc);
+                               perc /= 10;                                
+                       }                       
+                       
+                       if(prop == 0) {
+                               len = VecLenf(upVert->co,downVert->co)*((perc+1)/2);
+                               if(flip == 1) {
+                                       len = VecLenf(upVert->co,downVert->co) - len;
+                               } 
+                       }
+                       
+                       if (hasNumInput(&num))
+                       {
+                               applyNumInput(&num, &perc);
+                               
+                               if (prop)
+                               {
+                                       perc = MIN2(perc, 1);
+                                       perc = MAX2(perc, -1);
+                               }
+                               else
+                               {
+                                       len = MIN2(perc, VecLenf(upVert->co,downVert->co));
+                                       len = MAX2(len, 0);
+                               }
+                       }
+
                        //Adjust Edgeloop
                        if(immediate) {
                                perc = imperc;   
@@ -5043,13 +5113,7 @@ int EdgeSlide(short immediate, float imperc)
 
                        }
                        
-                       tempsv = BLI_ghash_lookup(vertgh,nearest);
-
-                       centerVert = editedge_getSharedVert(tempsv->up, tempsv->down);
-                       upVert = editedge_getOtherVert(tempsv->up, centerVert);
-                       downVert = editedge_getOtherVert(tempsv->down, centerVert);
                         // Highlight the Control Edges
-       
                        scrarea_do_windraw(curarea);   
                        persp(PERSP_VIEW);   
                        glPushMatrix();   
@@ -5077,55 +5141,36 @@ int EdgeSlide(short immediate, float imperc)
                        
                        glPopMatrix();           
 
-                       view3d_project_float(curarea, upVert->co, v2, projectMat);
-                       view3d_project_float(curarea, downVert->co, v3, projectMat);
-
-                       /* Determine the % on which the loop should be cut */   
-
-                       rc[0]= v3[0]-v2[0];   
-                       rc[1]= v3[1]-v2[1];   
-                       len= rc[0]*rc[0]+ rc[1]*rc[1];
-                       if (len==0) {len = 0.0001;}
-
-                       if ((G.qual & LR_SHIFTKEY)==0) {
-                               wasshift = 0;
-                               labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len;   
+                       if(prop) {
+                               p += sprintf(str, "(P)ercentage: ");
+                       } else {
+                               p += sprintf(str, "Non (P)rop Length: ");
                        }
-                       else {
-                               if (wasshift==0) {
-                                       wasshift = 1;
-                                       shiftlabda = labda;
-                               }                                                       
-                               labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len / 10.0 + shiftlabda;                           
+                       
+                       if (hasNumInput(&num))
+                       {
+                               char num_str[20];
+                               
+                               outputNumInput(&num, num_str);
+                               p += sprintf(p, "%s", num_str);
+                       }
+                       else
+                       {
+                               if (prop)
+                               {
+                                       p += sprintf(p, "%f", perc);
+                               }
+                               else
+                               {
+                                       p += sprintf(p, "%f", len);
+                               }
                        }
                        
-
-                       if(labda<=0.0) labda=0.0;   
-                       else if(labda>=1.0)labda=1.0;   
-
-                       perc=((1-labda)*2)-1;             
                        
-                       if(G.qual == 0) {
-                               perc *= 100;
-                               perc = floor(perc);
-                               perc /= 100;
-                       } else if (G.qual == LR_CTRLKEY) {
-                               perc *= 10;
-                               perc = floor(perc);
-                               perc /= 10;                                
-                       }                       
-                       if(prop) {
-                               sprintf(str, "(P)ercentage: %f", perc);
-                       } else {
-                               len = VecLenf(upVert->co,downVert->co)*((perc+1)/2);
-                               if(flip == 1) {
-                                       len = VecLenf(upVert->co,downVert->co) - len;
-                               } 
-                               sprintf(str, "Non (P)rop Length: %f, Press (F) to flip control side", len);
+                       if (prop == 0) {
+                               p += sprintf(p, ", Press (F) to flip control side");
                        }
 
-                       
-                       
                        headerprint(str);
                        screen_swapbuffers();                   
                }
@@ -5148,7 +5193,14 @@ int EdgeSlide(short immediate, float imperc)
                                                        perc = 0;  
                                                        immediate = 1;
                                        } else if(event==PKEY) {
-                                                       (prop == 1) ? (prop = 0):(prop = 1);
+                                                       initNumInput(&num); /* reset num input */
+                                                       if (prop) {
+                                                               prop = 0;
+                                                               num.flag |= NUM_NO_NEGATIVE;
+                                                       }
+                                                       else {
+                                                               prop = 1;
+                                                       }
                                                        mvalo[0] = -1;  
                                        } else if(event==FKEY) {
                                                        (flip == 1) ? (flip = 0):(flip = 1); 
@@ -5186,7 +5238,13 @@ int EdgeSlide(short immediate, float imperc)
                                                        look = look->next;   
                                                }         
                                        }
+                                       
+                                       if (handleNumInput(&num, event))
+                                       {
+                                               mvalo[0] = -1; /* NEED A BETTER WAY TO TRIGGER REDRAW */
+                                       }
                                }
+                               
                        } 
                } else {
                        draw = 0;
index 98f4f1bb46f8e4c60c96375cedce37741c0c8366..eba6c5b448890526d33154630ff8171cece183c2 100644 (file)
@@ -2110,6 +2110,7 @@ static void node_border_link_delete(SpaceNode *snode)
                        mval[1]= rect.ymax;
                        areamouseco_to_ipoco(&snode->v2d, mval, &rectf.xmax, &rectf.ymax);
                        
+                       glLoadIdentity();
                        myortho2(rectf.xmin, rectf.xmax, rectf.ymin, rectf.ymax);
                        
                        glSelectBuffer(256, buffer); 
index fee967bcd9ad5faf45c85c1dc8807a75d15382f9..2094074e3f3297084478d1d8111ec629447486d1 100644 (file)
 #include "BDR_drawobject.h"
 #include "BDR_editcurve.h"
 #include "BDR_unwrapper.h"
+#include "BDR_gpencil.h"
 
 #include <time.h>
 #include "mydevice.h"
@@ -2827,7 +2828,7 @@ void convertmenu(void)
        if(G.scene->id.lib) return;
 
        obact= OBACT;
-       if(obact==0) return;
+       if (obact == NULL) return;
        if(!obact->flag & SELECT) return;
        if(G.obedit) return;
        
@@ -4130,15 +4131,26 @@ void apply_object( void )
                }
                allqueue(REDRAWVIEW3D, 0);
                
-       } else {
+       } 
+       else {
+               ob= OBACT;
                
-               evt = pupmenu("Apply Object%t|Scale and Rotation to ObData|Visual Transform to Objects Loc/Scale/Rot");
+               if ((ob->pose) && (ob->flag & OB_POSEMODE))
+                       evt = pupmenu("Apply Object%t|Current Pose as RestPose%x3");
+               else
+                       evt = pupmenu("Apply Object%t|Scale and Rotation to ObData%x1|Visual Transform to Objects Loc/Scale/Rot%x2");
                if (evt==-1) return;
                
-               if (evt==1) {
-                       apply_objects_locrot();
-               } else if (evt==2) {
-                       apply_objects_visual_tx();
+               switch (evt) {
+                       case 1:
+                               apply_objects_locrot();
+                               break;
+                       case 2:
+                               apply_objects_visual_tx();
+                               break;
+                       case 3:
+                               apply_armature_pose2bones();
+                               break;
                }
        }
 }
index a3fcad7885c2869386302afa93f96a53914107b1..d2e59ae676dd19ac0933737e2337b05aa6e55c82 100644 (file)
@@ -1631,7 +1631,7 @@ void mouse_select(void)
 
 /* ------------------------------------------------------------------------- */
 
-static int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2)
+int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2)
 {
        int radsq= rad*rad;
        float v1[2], v2[2], v3[2];
index 0132c46526c4cc00a6854f78a4fb5e5da2c69766..6bbaecc2956a681a023f0eb5280e8223f6e995b6 100644 (file)
 #include "BLI_blenlib.h"
 
 #include "DNA_listBase.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
 #include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
 #include "BKE_global.h"
 #include "BKE_utildefines.h"
 #include "BKE_blender.h"
+#include "BKE_armature.h"
+#include "BKE_curve.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 #include "BIF_butspace.h"
+#include "BIF_editarmature.h"
 #include "BIF_editview.h"
 #include "BIF_graphics.h"
 #include "BIF_interface.h"
@@ -74,6 +80,8 @@
 #include "BDR_gpencil.h"
 #include "BIF_drawgpencil.h"
 
+#include "BDR_editobject.h"
+
 #include "BSE_drawipo.h"
 #include "BSE_headerbuttons.h"
 #include "BSE_view.h"
@@ -678,6 +686,303 @@ void gpencil_delete_menu (void)
        gpencil_delete_operation(mode);
 }
 
+/* --------- Data Conversion ---------- */
+
+/* convert the coordinates from the given stroke point into 3d-coordinates */
+static void gp_strokepoint_convertcoords (bGPDstroke *gps, bGPDspoint *pt, float p3d[3])
+{
+       if (gps->flag & GP_STROKE_3DSPACE) {
+               /* directly use 3d-coordinates */
+               // FIXME: maybe we need to counterotate this for object rotation?
+               VecCopyf(p3d, &pt->x);
+       }
+       else {
+               short mval[2], mx, my;
+               float *fp= give_cursor();
+               float dvec[3];
+               
+               /* get screen coordinate */
+               if (gps->flag & GP_STROKE_2DSPACE) {
+                       View2D *v2d= spacelink_get_view2d(curarea->spacedata.first);
+                       ipoco_to_areaco_noclip(v2d, &pt->x, mval);
+               }
+               else {
+                       mval[0]= (pt->x / 1000 * curarea->winx);
+                       mval[1]= (pt->y / 1000 * curarea->winy);
+               }
+               mx= mval[0]; 
+               my= mval[1];
+               
+               /* convert screen coordinate to 3d coordinates 
+                *      - method taken from editview.c - mouse_cursor() 
+                */
+               project_short_noclip(fp, mval);
+               window_to_3d(dvec, mval[0]-mx, mval[1]-my);
+               VecSubf(p3d, fp, dvec);
+       }
+}
+
+/* --- */
+
+/* convert stroke to 3d path */
+static void gp_stroke_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
+{
+       bGPDspoint *pt;
+       Nurb *nu;
+       BPoint *bp;
+       int i;
+       
+       /* create new 'nurb' within the curve */
+       nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
+       
+       nu->pntsu= gps->totpoints;
+       nu->pntsv= 1;
+       nu->orderu= gps->totpoints;
+       nu->flagu= 2;   /* endpoint */
+       nu->resolu= 32;
+       
+       nu->bp= (BPoint *)MEM_callocN(sizeof(BPoint)*gps->totpoints, "bpoints");
+       
+       /* add points */
+       for (i=0, pt=gps->points, bp=nu->bp; i < gps->totpoints; i++, pt++, bp++) {
+               float p3d[3];
+               
+               /* get coordinates to add at */
+               gp_strokepoint_convertcoords(gps, pt, p3d);
+               VecCopyf(bp->vec, p3d);
+               
+               /* set settings */
+               bp->f1= SELECT;
+               bp->radius = bp->weight = pt->pressure * gpl->thickness;
+       }
+       
+       /* add nurb to curve */
+       BLI_addtail(&cu->nurb, nu);
+}
+
+/* convert stroke to 3d bezier */
+static void gp_stroke_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
+{
+       bGPDspoint *pt;
+       Nurb *nu;
+       BezTriple *bezt;
+       int i;
+       
+       /* create new 'nurb' within the curve */
+       nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
+       
+       nu->pntsu= gps->totpoints;
+       nu->resolu= 12;
+       nu->resolv= 12;
+       nu->type= CU_BEZIER;
+       nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints*sizeof(BezTriple), "bezts");
+       
+       /* add points */
+       for (i=0, pt=gps->points, bezt=nu->bezt; i < gps->totpoints; i++, pt++, bezt++) {
+               float p3d[3];
+               
+               /* get coordinates to add at */
+               gp_strokepoint_convertcoords(gps, pt, p3d);
+               
+               /* TODO: maybe in future the handles shouldn't be in same place */
+               VecCopyf(bezt->vec[0], p3d);
+               VecCopyf(bezt->vec[1], p3d);
+               VecCopyf(bezt->vec[2], p3d);
+               
+               /* set settings */
+               bezt->h1= bezt->h2= HD_FREE;
+               bezt->f1= bezt->f2= bezt->f3= SELECT;
+               bezt->radius = bezt->weight = pt->pressure * gpl->thickness;
+       }
+       
+       /* must calculate handles or else we crash */
+       calchandlesNurb(nu);
+       
+       /* add nurb to curve */
+       BLI_addtail(&cu->nurb, nu);
+}
+
+/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
+static void gp_layer_to_curve (bGPdata *gpd, bGPDlayer *gpl, short mode)
+{
+       bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+       bGPDstroke *gps;
+       Object *ob;
+       Curve *cu;
+       
+       /* error checking */
+       if (ELEM3(NULL, gpd, gpl, gpf))
+               return;
+               
+       /* only convert if there are any strokes on this layer's frame to convert */
+       if (gpf->strokes.first == NULL)
+               return;
+               
+       /* initialise the curve */      
+       cu= add_curve(gpl->info, 1);
+       cu->flag |= CU_3D;
+       
+       /* init the curve object (remove rotation and assign curve data to it) */
+       add_object_draw(OB_CURVE);
+       ob= OBACT;
+       ob->loc[0]= ob->loc[1]= ob->loc[2]= 0;
+       ob->rot[0]= ob->rot[1]= ob->rot[2]= 0;
+       ob->data= cu;
+       
+       /* add points to curve */
+       for (gps= gpf->strokes.first; gps; gps= gps->next) {
+               switch (mode) {
+                       case 1: 
+                               gp_stroke_to_path(gpl, gps, cu);
+                               break;
+                       case 2:
+                               gp_stroke_to_bezier(gpl, gps, cu);
+                               break;
+               }
+       }
+}
+
+/* --- */
+
+/* convert a stroke to a bone chain */
+static void gp_stroke_to_bonechain (bGPDlayer *gpl, bGPDstroke *gps, bArmature *arm, ListBase *bones)
+{
+       EditBone *ebo, *prev=NULL;
+       bGPDspoint *pt, *ptn;
+       int i;
+       
+       /* add each segment separately */
+       for (i=0, pt=gps->points, ptn=gps->points+1; i < (gps->totpoints-1); prev=ebo, i++, pt++, ptn++) {
+               float p3da[3], p3db[3];
+               
+               /* get coordinates to add at */
+               gp_strokepoint_convertcoords(gps, pt, p3da);
+               gp_strokepoint_convertcoords(gps, ptn, p3db);
+               
+               /* allocate new bone */
+               ebo= MEM_callocN(sizeof(EditBone), "eBone");
+               
+               VecCopyf(ebo->head, p3da);
+               VecCopyf(ebo->tail, p3db);
+               
+               /* add new bone - note: sync with editarmature.c::add_editbone() */
+               BLI_strncpy(ebo->name, "Stroke", 32);
+               unique_editbone_name(bones, ebo->name);
+               
+               BLI_addtail(bones, ebo);
+               
+               ebo->flag |= BONE_CONNECTED;
+               ebo->weight= 1.0F;
+               ebo->dist= 0.25F;
+               ebo->xwidth= 0.1;
+               ebo->zwidth= 0.1;
+               ebo->ease1= 1.0;
+               ebo->ease2= 1.0;
+               ebo->rad_head= pt->pressure * gpl->thickness * 0.1;
+               ebo->rad_tail= ptn->pressure * gpl->thickness * 0.1;
+               ebo->segments= 1;
+               ebo->layer= arm->layer;
+               
+               /* set parenting */
+               // TODO: also adjust roll....
+               ebo->parent= prev;
+       }
+}
+
+/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
+static void gp_layer_to_armature (bGPdata *gpd, bGPDlayer *gpl, short mode)
+{
+       bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+       bGPDstroke *gps;
+       Object *ob;
+       bArmature *arm;
+       ListBase bones = {0,0};
+       
+       /* error checking */
+       if (ELEM3(NULL, gpd, gpl, gpf))
+               return;
+               
+       /* only convert if there are any strokes on this layer's frame to convert */
+       if (gpf->strokes.first == NULL)
+               return;
+               
+       /* initialise the armature */   
+       arm= add_armature(gpl->info);
+       
+       /* init the armature object (remove rotation and assign armature data to it) */
+       add_object_draw(OB_ARMATURE);
+       ob= OBACT;
+       ob->loc[0]= ob->loc[1]= ob->loc[2]= 0;
+       ob->rot[0]= ob->rot[1]= ob->rot[2]= 0;
+       ob->data= arm;
+       
+       /* convert segments to bones, strokes to bone chains */
+       for (gps= gpf->strokes.first; gps; gps= gps->next) {
+               gp_stroke_to_bonechain(gpl, gps, arm, &bones);
+       }
+       
+       /* flush editbones to armature */
+       editbones_to_armature(&bones, ob);
+       if (bones.first) BLI_freelistN(&bones);
+}
+
+/* --- */
+
+/* convert grease-pencil strokes to another representation 
+ *     mode:   1 - Active layer to path
+ *                     2 - Active layer to bezier
+ *                     3 - Active layer to armature
+ */
+void gpencil_convert_operation (short mode)
+{
+       bGPdata *gpd;   
+       float *fp= give_cursor();
+       
+       /* get datablock to work on */
+       gpd= gpencil_data_getactive(NULL);
+       if (gpd == NULL) return;
+       
+       /* initialise 3d-cursor correction globals */
+       initgrabz(fp[0], fp[1], fp[2]);
+       
+       /* handle selection modes */
+       switch (mode) {
+               case 1: /* active layer only (to path) */
+               case 2: /* active layer only (to bezier) */
+               {
+                       bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+                       gp_layer_to_curve(gpd, gpl, mode);
+               }
+                       break;
+               case 3: /* active layer only (to armature) */
+               {
+                       bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+                       gp_layer_to_armature(gpd, gpl, mode);
+               }
+                       break;
+       }
+       
+       /* redraw and undo-push */
+       BIF_undo_push("GPencil Convert");
+       allqueue(REDRAWVIEW3D, 0);
+       allqueue(REDRAWOOPS, 0);
+}
+
+/* display a menu for converting grease-pencil strokes */
+void gpencil_convert_menu (void)
+{
+       bGPdata *gpd= gpencil_data_getactive(NULL);
+       short mode;
+       
+       /* only show menu if it will be relevant */
+       if (gpd == NULL) return;
+       
+       mode= pupmenu("Grease Pencil Convert %t|Active Layer To Path%x1|Active Layer to Bezier%x2|Active Layer to Armature%x3");
+       if (mode <= 0) return;
+       
+       gpencil_convert_operation(mode);
+}
+
 /* ************************************************** */
 /* GREASE-PENCIL EDITING MODE - Painting */
 
@@ -707,6 +1012,10 @@ typedef struct tGPsdata {
        
        short status;           /* current status of painting */
        short paintmode;        /* mode for painting */
+       
+       short mval[2];          /* current mouse-position */
+       short mvalo[2];         /* previous recorded mouse-position */
+       short radius;           /* radius of influence for eraser */
 } tGPsdata;
 
 /* values for tGPsdata->status */
@@ -821,14 +1130,14 @@ static void gp_session_initpaint (tGPsdata *p)
                        }
                }
                        break;  
-               case SPACE_SIMA:
+               case SPACE_IMAGE:
                {
                        SpaceImage *sima= curarea->spacedata.first;
                        
                        /* set the current area */
                        p->sa= curarea;
                        p->v2d= &sima->v2d;
-                       p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
+                       //p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
                }
                        break;
                /* unsupported views */
@@ -999,9 +1308,18 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
        bGPDspoint *pt;
        tGPspoint *ptc;
        int i, totelem;
+
+       /* macro to test if only converting endpoints  */       
+       #define GP_BUFFER2STROKE_ENDPOINTS ((gpd->flag & GP_DATA_EDITPAINT) && (G.qual & LR_CTRLKEY))
        
-       /* get total number of points to allocate space for */
-       totelem = gpd->sbuffer_size;
+       /* get total number of points to allocate space for:
+        *      - in 'Draw Mode', holding the Ctrl-Modifier will only take endpoints
+        *      - otherwise, do whole stroke
+        */
+       if (GP_BUFFER2STROKE_ENDPOINTS)
+               totelem = (gpd->sbuffer_size >= 2) ? 2: gpd->sbuffer_size;
+       else
+               totelem = gpd->sbuffer_size;
        
        /* exit with error if no valid points from this stroke */
        if (totelem == 0) {
@@ -1022,45 +1340,53 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
        gps->flag= gpd->sbuffer_sflag;
        
        /* copy points from the buffer to the stroke */
-       for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) {
-               /* convert screen-coordinates to appropriate coordinates (and store them) */
-               gp_stroke_convertcoords(p, &ptc->x, &pt->x);
-               
-               /* copy pressure */
-               pt->pressure= ptc->pressure;
-               
-               pt++;
+       if (GP_BUFFER2STROKE_ENDPOINTS) {
+               /* 'Draw Mode' + Ctrl-Modifier - only endpoints */
+               {
+                       /* first point */
+                       ptc= gpd->sbuffer;
+                       
+                       /* convert screen-coordinates to appropriate coordinates (and store them) */
+                       gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+                       
+                       /* copy pressure */
+                       pt->pressure= ptc->pressure;
+                       
+                       pt++;
+               }
+                       
+               if (totelem == 2) {
+                       /* last point if applicable */
+                       ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1);
+                       
+                       /* convert screen-coordinates to appropriate coordinates (and store them) */
+                       gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+                       
+                       /* copy pressure */
+                       pt->pressure= ptc->pressure;
+               }
+       }
+       else {
+               /* convert all points (normal behaviour) */
+               for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) {
+                       /* convert screen-coordinates to appropriate coordinates (and store them) */
+                       gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+                       
+                       /* copy pressure */
+                       pt->pressure= ptc->pressure;
+                       
+                       pt++;
+               }
        }
        
        /* add stroke to frame */
        BLI_addtail(&p->gpf->strokes, gps);
+       
+       /* undefine macro to test if only converting endpoints  */      
+       #undef GP_BUFFER2STROKE_ENDPOINTS
 }
 
 /* --- 'Eraser' for 'Paint' Tool ------ */
-/* User should draw 'circles' around the parts of the sketches they wish to 
- * delete instead of drawing squiggles over existing lines. This should be 
- * easier to manage than if it was done otherwise.
- */
-
-/* convert gp-buffer stroke into mouse-coordinates array */
-static short (*gp_stroke_eraser_2mco (bGPdata *gpd))[2]
-{
-       tGPspoint *pt;
-       short (*mcoords)[2]; 
-       int i;
-       
-       /* allocate memory for coordinates array */
-       mcoords= MEM_mallocN(sizeof(*mcoords)*gpd->sbuffer_size,"gp_buf_mcords");
-       
-       /* copy coordinates */
-       for (pt=gpd->sbuffer, i=0; i < gpd->sbuffer_size; i++, pt++) {
-               mcoords[i][0]= pt->x;
-               mcoords[i][1]= pt->y;
-       }
-       
-       /* return */
-       return mcoords;
-}
 
 /* eraser tool - remove segment from stroke/split stroke (after lasso inside) */
 static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i)
@@ -1130,8 +1456,19 @@ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i)
        }
 }
 
+/* eraser tool - check if part of stroke occurs within last segment drawn by eraser */
+static short gp_stroke_eraser_strokeinside (short mval[], short mvalo[], short rad, short x0, short y0, short x1, short y1)
+{
+       /* simple within-radius check for now */
+       if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1))
+               return 1;
+       
+       /* not inside */
+       return 0;
+} 
+
 /* eraser tool - evaluation per stroke */
-static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short moves, rcti *rect, bGPDframe *gpf, bGPDstroke *gps)
+static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], short rad, rcti *rect, bGPDframe *gpf, bGPDstroke *gps)
 {
        bGPDspoint *pt1, *pt2;
        short x0=0, y0=0, x1=0, y1=0;
@@ -1147,10 +1484,9 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo
        else if (gps->totpoints == 1) {
                /* get coordinates */
                if (gps->flag & GP_STROKE_3DSPACE) {
-                       // FIXME: this may not be the correct correction
                        project_short(&gps->points->x, xyval);
                        x0= xyval[0];
-                       x1= xyval[1];
+                       y0= xyval[1];
                }
                else if (gps->flag & GP_STROKE_2DSPACE) {                       
                        ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval);
@@ -1165,7 +1501,7 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo
                /* do boundbox check first */
                if (BLI_in_rcti(rect, x0, y0)) {
                        /* only check if point is inside */
-                       if (lasso_inside(mcoords, moves, x0, y0)) {
+                       if ( ((x0-mval[0])*(x0-mval[0]) + (y0-mval[1])*(y0-mval[1])) <= rad*rad ) {
                                /* free stroke */
                                MEM_freeN(gps->points);
                                BLI_freelinkN(&gpf->strokes, gps);
@@ -1183,10 +1519,13 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo
                        
                        /* get coordinates */
                        if (gps->flag & GP_STROKE_3DSPACE) {
-                               // FIXME: may not be correct correction
-                               project_short(&gps->points->x, xyval);
+                               project_short(&pt1->x, xyval);
                                x0= xyval[0];
-                               x1= xyval[1];
+                               y0= xyval[1];
+                               
+                               project_short(&pt2->x, xyval);
+                               x1= xyval[0];
+                               y1= xyval[1];
                        }
                        else if (gps->flag & GP_STROKE_2DSPACE) {
                                ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval);
@@ -1209,9 +1548,8 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo
                                /* check if point segment of stroke had anything to do with
                                 * eraser region  (either within stroke painted, or on its lines)
                                 *      - this assumes that linewidth is irrelevant
-                                *      - handled using the lasso-select checking code
                                 */
-                               if (lasso_inside_edge(mcoords, moves, x0, y0, x1, x1)) {
+                               if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) {
                                        /* if function returns true, break this loop (as no more point to check) */
                                        if (gp_stroke_eraser_splitdel(gpf, gps, i))
                                                break;
@@ -1226,24 +1564,21 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo
 /* erase strokes which fall under the eraser strokes */
 static void gp_stroke_doeraser (tGPsdata *p)
 {
-       bGPdata *gpd= p->gpd;
        bGPDframe *gpf= p->gpf;
        bGPDstroke *gps, *gpn;
-       short (*mcoords)[2];
        rcti rect;
        
-       /* get buffer-stroke coordinates as shorts array, and then get bounding box */
-       mcoords= gp_stroke_eraser_2mco(gpd);
-       lasso_select_boundbox(&rect, mcoords, gpd->sbuffer_size);
+       /* rect is rectangle of eraser */
+       rect.xmin= p->mval[0] - p->radius;
+       rect.ymin= p->mval[1] - p->radius;
+       rect.xmax= p->mval[0] + p->radius;
+       rect.ymax= p->mval[1] + p->radius;
        
        /* loop over strokes, checking segments for intersections */
        for (gps= gpf->strokes.first; gps; gps= gpn) {
                gpn= gps->next;
-               gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, &rect, gpf, gps);
+               gp_stroke_eraser_dostroke(p, p->mval, p->mvalo, p->radius, &rect, gpf, gps);
        }
-       
-       /* free mcoords array */
-       MEM_freeN(mcoords);
 }
 
 /* ---------- 'Paint' Tool ------------ */
@@ -1297,6 +1632,12 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode)
                        case SPACE_SEQ:
                        {
                                /* for now, this is not applicable here... */
+                               //p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE;
+                       }
+                               break;
+                       case SPACE_IMAGE:
+                       {
+                               p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE;
                        }
                                break;
                }
@@ -1307,11 +1648,7 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode)
 static void gp_paint_strokeend (tGPsdata *p)
 {
        /* check if doing eraser or not */
-       if (p->gpd->sbuffer_sflag & GP_STROKE_ERASER) {
-               /* get rid of relevant sections of strokes */
-               gp_stroke_doeraser(p);
-       }
-       else {
+       if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
                /* transfer stroke to frame */
                gp_stroke_newfrombuffer(p);
        }
@@ -1345,7 +1682,6 @@ static void gp_paint_cleanup (tGPsdata *p)
 short gpencil_paint (short mousebutton, short paintmode)
 {
        tGPsdata p;
-       short prevmval[2], mval[2];
        float opressure, pressure;
        short ok = GP_STROKEADD_NORMAL;
        
@@ -1365,31 +1701,51 @@ short gpencil_paint (short mousebutton, short paintmode)
        setcursor_space(p.sa->spacetype, CURSOR_VPAINT);
        
        /* init drawing-device settings */
-       getmouseco_areawin(mval);
+       getmouseco_areawin(p.mval);
        pressure = get_pressure();
        
-       prevmval[0]= mval[0];
-       prevmval[1]= mval[1];
+       p.mvalo[0]= p.mval[0];
+       p.mvalo[1]= p.mval[1];
        opressure= pressure;
        
+       /* radius for eraser circle is thickness^2 */
+       p.radius= p.gpl->thickness * p.gpl->thickness;
+       
+       /* start drawing eraser-circle (if applicable) */
+       if (paintmode == GP_PAINTMODE_ERASER)
+               draw_sel_circle(p.mval, NULL, p.radius, p.radius, 0); // draws frontbuffer, but sets backbuf again
+       
        /* only allow painting of single 'dots' if: 
         *      - pressure is not excessive (as it can be on some windows tablets)
         *      - draw-mode for active datablock is turned on
+        *      - not erasing
         */
-       if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { 
-               gp_stroke_addpoint(&p, mval, pressure);
+       if (paintmode != GP_PAINTMODE_ERASER) {
+               if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { 
+                       gp_stroke_addpoint(&p, p.mval, pressure);
+               }
        }
        
        /* paint loop */
        do {
                /* get current user input */
-               getmouseco_areawin(mval);
+               getmouseco_areawin(p.mval);
                pressure = get_pressure();
                
                /* only add current point to buffer if mouse moved (otherwise wait until it does) */
-               if (gp_stroke_filtermval(&p, mval, prevmval)) {
+               if (paintmode == GP_PAINTMODE_ERASER) {
+                       /* do 'live' erasing now */
+                       gp_stroke_doeraser(&p);
+                       
+                       draw_sel_circle(p.mval, p.mvalo, p.radius, p.radius, 0);
+                       force_draw(0);
+                       
+                       p.mvalo[0]= p.mval[0];
+                       p.mvalo[1]= p.mval[1];
+               }
+               else if (gp_stroke_filtermval(&p, p.mval, p.mvalo)) {
                        /* try to add point */
-                       ok= gp_stroke_addpoint(&p, mval, pressure);
+                       ok= gp_stroke_addpoint(&p, p.mval, pressure);
                        
                        /* handle errors while adding point */
                        if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
@@ -1397,8 +1753,8 @@ short gpencil_paint (short mousebutton, short paintmode)
                                gp_paint_strokeend(&p);
                                
                                /* start a new stroke, starting from previous point */
-                               gp_stroke_addpoint(&p, prevmval, opressure);
-                               ok= gp_stroke_addpoint(&p, mval, pressure);
+                               gp_stroke_addpoint(&p, p.mvalo, opressure);
+                               ok= gp_stroke_addpoint(&p, p.mval, pressure);
                        }
                        else if (ok == GP_STROKEADD_INVALID) {
                                /* the painting operation cannot continue... */
@@ -1411,8 +1767,8 @@ short gpencil_paint (short mousebutton, short paintmode)
                        }
                        force_draw(0);
                        
-                       prevmval[0]= mval[0];
-                       prevmval[1]= mval[1];
+                       p.mvalo[0]= p.mval[0];
+                       p.mvalo[1]= p.mval[1];
                        opressure= pressure;
                }
                else
@@ -1430,8 +1786,10 @@ short gpencil_paint (short mousebutton, short paintmode)
        setcursor_space(p.sa->spacetype, CURSOR_STD);
        
        /* check size of buffer before cleanup, to determine if anything happened here */
-       if (paintmode == GP_PAINTMODE_ERASER)
-               ok= (p.gpd->sbuffer_size > 1);
+       if (paintmode == GP_PAINTMODE_ERASER) {
+               ok= 1; // fixme
+               draw_sel_circle(NULL, p.mvalo, 0, p.radius, 0);
+       }
        else
                ok= p.gpd->sbuffer_size;
        
@@ -1458,7 +1816,8 @@ short gpencil_do_paint (ScrArea *sa, short mbut)
        
        /* currently, we will only 'paint' if:
         *      1. draw-mode on gpd is set (for accessibility reasons)
-        *              (single 'dots' are only available via this method)
+        *              a) single dots are only available by this method if a single click is made
+        *              b) a straight line is drawn if ctrl-modifier is held (check is done when stroke is converted!)
         *      2. if shift-modifier is held + lmb -> 'quick paint'
         *
         *      OR
index fcf4caf45225c6490b104bbbe022afed40a2086a..e57a3480b524b20cae0ba39351fee9845900cb83 100644 (file)
@@ -4370,6 +4370,9 @@ static void do_view3d_pose_armaturemenu(void *arg, int event)
        case 18:
                pose_autoside_names(event-16);
                break;
+       case 19: /* assign pose as restpose */
+               apply_armature_pose2bones();
+               break;
        }
                
        allqueue(REDRAWVIEW3D, 0);
@@ -4395,6 +4398,7 @@ static uiBlock *view3d_pose_armaturemenu(void *arg_unused)
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Relax Pose|W",                           0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Pose as Restpose|Ctrl A",          0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, "");
        
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
index 8787cf9efc44e90e357028e0c25027a0772046a5..b19d20e1be52097e394a938cb2bb05f13f44e97c 100644 (file)
@@ -1906,6 +1906,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        else
                                                copy_attr_menu();
                                }
+                               else if(G.qual==(LR_ALTKEY|LR_SHIFTKEY)) 
+                                       gpencil_convert_menu(); /* gpencil.c */
                                else if(G.qual==LR_ALTKEY) {
                                        if(ob && (ob->flag & OB_POSEMODE))
                                                pose_clear_constraints();       /* poseobject.c */
@@ -1964,7 +1966,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                                G.vd->drawtype= pupval;
                                                doredraw= 1;
                                        }
-                                }
+                }
                                
                                break;
                        case EKEY:
index efb86b59ed14e98d1022f1545b873d15d1034ae3..0b43dac07cff4dc0fc2d9dcbe8bb573606a87e14 100644 (file)
@@ -3751,6 +3751,35 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik)
                                                insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
                                        }
                                }
+                               else if (IS_AUTOKEY_FLAG(AUTOMATKEY)) {
+                                       int matok=0; 
+                                       
+                                       /* check one to make sure we're not trying to set visual loc keys on
+                                               bones inside of a chain, which only leads to tears. */
+                                       matok=  insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X);
+                                                       insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y);
+                                                       insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z);
+                                       
+                                       if (matok == 0) {
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0);
+                                       }
+                                       
+                                       /* check one to make sure we're not trying to set visual rot keys on
+                                               bones inside of a chain, which only leads to tears. */
+                                       matok=  insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W);
+                                                       insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X);
+                                                       insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
+                                                       insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
+                                       
+                                       if (matok == 0) {
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0);
+                                       }
+                               }
                                /* insert keyframe in any channel that's appropriate */
                                else {
                                        insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0);
index 656fca3cad8cccd4fb1621552e7ca636e0de0d30..a1440b8cbce2a2395eae9e593c87ee9dde00b885 100644 (file)
@@ -583,39 +583,6 @@ void recalcData(TransInfo *t)
                reshadeall_displist();
 }
 
-void initTransModeFlags(TransInfo *t, int mode) 
-{
-       t->mode = mode;
-       t->num.flag = 0;
-
-       /* REMOVING RESTRICTIONS FLAGS */
-       t->flag &= ~T_ALL_RESTRICTIONS;
-       
-       switch (mode) {
-       case TFM_RESIZE:
-               t->flag |= T_NULL_ONE;
-               t->num.flag |= NUM_NULL_ONE;
-               t->num.flag |= NUM_AFFECT_ALL;
-               if (!G.obedit) {
-                       t->flag |= T_NO_ZERO;
-                       t->num.flag |= NUM_NO_ZERO;
-               }
-               break;
-       case TFM_TOSPHERE:
-               t->num.flag |= NUM_NULL_ONE;
-               t->num.flag |= NUM_NO_NEGATIVE;
-               t->flag |= T_NO_CONSTRAINT;
-               break;
-       case TFM_SHEAR:
-       case TFM_CREASE:
-       case TFM_BONE_ENVELOPE:
-       case TFM_CURVE_SHRINKFATTEN:
-       case TFM_BONE_ROLL:
-               t->flag |= T_NO_CONSTRAINT;
-               break;
-       }
-}
-
 void drawLine(float *center, float *dir, char axis, short options)
 {
        extern void make_axis_color(char *col, char *col2, char axis);  // drawview.c
@@ -674,19 +641,10 @@ void initTrans (TransInfo *t)
        t->transform            = NULL;
        t->handleEvent          = NULL;
 
-       t->total                        =
-               t->num.idx              =
-               t->num.idx_max  =
-               t->num.ctrl[0]  = 
-               t->num.ctrl[1]  = 
-               t->num.ctrl[2]  = 0;
+       t->total                        = 0;
 
        t->val = 0.0f;
 
-       t->num.val[0]           = 
-               t->num.val[1]   = 
-               t->num.val[2]   = 0.0f;
-
        t->vec[0]                       =
                t->vec[1]               =
                t->vec[2]               = 0.0f;
@@ -708,7 +666,8 @@ void initTrans (TransInfo *t)
                t->around = V3D_CENTER;
 
        setTransformViewMatrices(t);
-       initNDofInput(&(t->ndof));
+       initNumInput(&t->num);
+       initNDofInput(&t->ndof);
 }
 
 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
index 9b811595a9add4b6926a3f547fd32ba5b9112926..89a76c097e0eadbc1999c62241cda88d5cf703bd 100644 (file)
 
 /* ************************** NUMINPUT **************************** */
 
+void initNumInput(NumInput *n)
+{
+       n->flag         =
+       n->idx          =
+       n->idx_max      =
+       n->ctrl[0]      = 
+       n->ctrl[1]      = 
+       n->ctrl[2]      = 0;
+
+       n->val[0]               = 
+       n->val[1]       = 
+       n->val[2]       = 0.0f;
+}
+
 void outputNumInput(NumInput *n, char *str)
 {
        char cur;
index e4eff163d5b61f8dd50c4b8488024ba2fd03691b..dafc259985030e55fe13b760ad42e80dfd3fd5ac 100644 (file)
@@ -131,11 +131,11 @@ void KX_BlenderRenderTools::SetClientObject(void* obj)
        }
 }
 
-bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
 {
        double* const oglmatrix = (double* const) data;
-       MT_Point3 resultpoint(hit_point);
-       MT_Vector3 resultnormal(hit_normal);
+       MT_Point3 resultpoint(result->m_hitPoint);
+       MT_Vector3 resultnormal(result->m_hitNormal);
        MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
        MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
        left = (dir.cross(resultnormal)).safe_normalized();
@@ -236,9 +236,8 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
                        if (parent)
                                parent->Release();
                                
-                       MT_Point3 resultpoint;
-                       MT_Vector3 resultnormal;
-                       if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback<KX_BlenderRenderTools>(this, oglmatrix)))
+                       KX_RayCast::Callback<KX_BlenderRenderTools> callback(this, physics_controller, oglmatrix);
+                       if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback))
                        {
                                // couldn't find something to cast the shadow on...
                                glMultMatrixd(oglmatrix);
index 8abce1b8c3ec36117fe43910371760a69c9470e0..8027136aa52e7ab81cdb682b5615c95f42bfe0e4 100644 (file)
@@ -37,6 +37,7 @@
 #include "RAS_IRenderTools.h"
 
 struct KX_ClientObjectInfo;
+class KX_RayCast;
 
 /**
 BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which are not
@@ -97,7 +98,8 @@ public:
                                                                        void* clientobject,
                                                                        void* tface);
        
-       bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+       bool RayHit(KX_ClientObjectInfo* client, class KX_RayCast* result, void * const data);
+       bool NeedRayCast(KX_ClientObjectInfo*) { return true; }
 
        virtual void MotionBlur(RAS_IRasterizer* rasterizer);
 
index cb2521de9a4301950f2d76319c2ef4378a5df62f..7e976beaf441cdd79699b5889e48577a3659d922 100644 (file)
@@ -355,22 +355,26 @@ void BL_ConvertActuators(char* maggiename,
                                
                                if (soundActuatorType != KX_SoundActuator::KX_SOUNDACT_NODEF) 
                                {
-                                       SND_SoundObject* sndobj = NULL;
+                                       SND_Scene* soundscene = scene->GetSoundScene();
+                                       STR_String samplename = "";
+                                       bool sampleisloaded = false;
                                        
-                                       if (soundact->sound)
-                                       {
-                                               SND_Scene* soundscene = scene->GetSoundScene();
-                                               STR_String samplename = soundact->sound->name;
+                                       if (soundact->sound) {
+                                               /* Need to convert the samplename into absolute path
+                                                * before checking if its loaded */
+                                               char fullpath[sizeof(soundact->sound->name)];
                                                
-                                               bool sampleisloaded = false;
+                                               /* dont modify soundact->sound->name, only change a copy */
+                                               BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath));
+                                               BLI_convertstringcode(fullpath, maggiename);
+                                               samplename = fullpath;
                                                
                                                /* let's see if the sample was already loaded */
                                                if (soundscene->IsSampleLoaded(samplename))
                                                {
                                                        sampleisloaded = true;
                                                }
-                                               else
-                                               {
+                                               else {
                                                        /* if not, make it so */
                                                        PackedFile* pf = soundact->sound->newpackedfile;
                                                        
@@ -383,21 +387,33 @@ void BL_ConvertActuators(char* maggiename,
                                                        /* or else load it from disk */
                                                        else
                                                        {
-                                                               /* but we need to convert the samplename into absolute pathname first */
-                                                               BLI_convertstringcode(soundact->sound->name, maggiename);
-                                                               samplename = soundact->sound->name;
-                                                               
-                                                               /* and now we can load it */
-                                                               if (soundscene->LoadSample(samplename, NULL, 0) > -1)
+                                                               if (soundscene->LoadSample(samplename, NULL, 0) > -1) {
                                                                        sampleisloaded = true;
+                                                               }
+                                                               else {
+                                                                       std::cout <<    "WARNING: Sound actuator \"" << bact->name <<
+                                                                                                       "\" from object \"" <<  blenderobject->id.name+2 <<
+                                                                                                       "\" failed to load sample." << std::endl;
+                                                               }
                                                        }
                                                }
-                                               
-                                               if (sampleisloaded)
-                                               {
-                                                       sndobj = new SND_SoundObject();
-                                                       sndobj->SetSampleName(samplename.Ptr());
-                                                       sndobj->SetObjectName(bact->name);
+                                       } else {
+                                               std::cout <<    "WARNING: Sound actuator \"" << bact->name <<
+                                                                               "\" from object \"" <<  blenderobject->id.name+2 <<
+                                                                               "\" has no sound datablock." << std::endl;
+                                       }
+                                       
+                                       /* Note, allowing actuators for sounds that are not there was added since 2.47
+                                        * This is because python may expect the actuator and raise an exception if it dosnt find it
+                                        * better just to add a dummy sound actuator. */
+                                       SND_SoundObject* sndobj = NULL;
+                                       if (sampleisloaded)
+                                       {
+                                               /* setup the SND_SoundObject */
+                                               sndobj = new SND_SoundObject();
+                                               sndobj->SetSampleName(samplename.Ptr());
+                                               sndobj->SetObjectName(bact->name);
+                                               if (soundact->sound) {
                                                        sndobj->SetRollOffFactor(soundact->sound->attenuation);
                                                        sndobj->SetGain(soundact->sound->volume);
                                                        sndobj->SetPitch(exp((soundact->sound->pitch / 12.0) * log(2.0)));
@@ -410,8 +426,9 @@ void BL_ConvertActuators(char* maggiename,
                                                                else
                                                                        sndobj->SetLoopMode(SND_LOOP_NORMAL);
                                                        }
-                                                       else
+                                                       else {
                                                                sndobj->SetLoopMode(SND_LOOP_OFF);
+                                                       }
                                                        
                                                        if (soundact->sound->flags & SOUND_FLAGS_PRIORITY)
                                                                sndobj->SetHighPriority(true);
@@ -422,22 +439,30 @@ void BL_ConvertActuators(char* maggiename,
                                                                sndobj->Set3D(true);
                                                        else
                                                                sndobj->Set3D(false);
-                                                       
-                                                       KX_SoundActuator* tmpsoundact = 
-                                                               new KX_SoundActuator(gameobj, 
-                                                               sndobj,
-                                                               scene->GetSoundScene(), // needed for replication!
-                                                               soundActuatorType,
-                                                               startFrame,
-                                                               stopFrame);
-                                                       
-                                                       tmpsoundact->SetName(bact->name);
-                                                       baseact = tmpsoundact;
-                                                       soundscene->AddObject(sndobj);
-                                               } else {
-                                                       std::cout << "WARNING: Sound actuator " << bact->name << " failed to load sample." << std::endl;
+                                               }
+                                               else {
+                                                       /* dummy values for a NULL sound
+                                                       * see editsound.c - defaults are unlikely to change soon */
+                                                       sndobj->SetRollOffFactor(1.0);
+                                                       sndobj->SetGain(1.0);
+                                                       sndobj->SetPitch(1.0);
+                                                       sndobj->SetLoopMode(SND_LOOP_OFF);
+                                                       sndobj->SetHighPriority(false);
+                                                       sndobj->Set3D(false);
                                                }
                                        }
+                                       KX_SoundActuator* tmpsoundact = 
+                                               new KX_SoundActuator(gameobj, 
+                                               sndobj,
+                                               scene->GetSoundScene(), // needed for replication!
+                                               soundActuatorType,
+                                               startFrame,
+                                               stopFrame);
+                                       
+                                       tmpsoundact->SetName(bact->name);
+                                       baseact = tmpsoundact;
+                                       if (sndobj)
+                                               soundscene->AddObject(sndobj);
                                }
                                break;
                        }
@@ -550,10 +575,16 @@ void BL_ConvertActuators(char* maggiename,
                                                                originalval = converter->FindGameObject(editobact->ob);
                                                        }
                                                }
-                                               MT_Vector3 linvelvec ( KX_BLENDERTRUNC(editobact->linVelocity[0]),
+                                               MT_Vector3 linvelvec (
+                                                       KX_BLENDERTRUNC(editobact->linVelocity[0]),
                                                        KX_BLENDERTRUNC(editobact->linVelocity[1]),
                                                        KX_BLENDERTRUNC(editobact->linVelocity[2]));
-                                                       
+                                               
+                                               MT_Vector3 angvelvec (
+                                                       KX_BLENDERTRUNC(editobact->angVelocity[0]),
+                                                       KX_BLENDERTRUNC(editobact->angVelocity[1]),
+                                                       KX_BLENDERTRUNC(editobact->angVelocity[2]));
+                                               
                                                KX_SCA_AddObjectActuator* tmpaddact = 
                                                        new KX_SCA_AddObjectActuator(
                                                                gameobj, 
@@ -561,7 +592,9 @@ void BL_ConvertActuators(char* maggiename,
                                                                editobact->time,
                                                                scene,
                                                                linvelvec.getValue(),
-                                                               editobact->localflag!=0
+                                                               (editobact->localflag & ACT_EDOB_LOCAL_LINV)!=0,
+                                                               angvelvec.getValue(),
+                                                               (editobact->localflag & ACT_EDOB_LOCAL_ANGV)!=0
                                                                );
                                                                
                                                                //editobact->ob to gameobj
index 4806df3609048794b39b0565590c39f8b9a1bb37..74819431858a3c03ab9a80ad1aacc0a1071f586a 100644 (file)
@@ -633,6 +633,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
                                if (eventmgr)
                                {
                                        bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL);
+                                       bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY);
                                        
                                        STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname);
 
@@ -645,6 +646,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
                                                                                                  gameobj,
                                                                                                  checkname,
                                                                                                  bFindMaterial,
+                                                                                                 bXRay,
                                                                                                  distance,
                                                                                                  axis,
                                                                                                  kxscene);
@@ -711,6 +713,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
                                        gamesensor = new SCA_JoystickSensor(
                                                eventmgr,
                                                gameobj,
+                                               bjoy->joyindex,
                                                joysticktype,
                                                axis,axisf,
                                                prec,
@@ -765,17 +768,17 @@ void BL_ConvertSensors(struct Object* blenderobject,
                                                logicmgr->RegisterToSensor(gamecont,gamesensor);
                                        } else {
                                                printf(
-                                                       "Warning, sensor \"%s\" could not find its controller"
-                                                       "(link %d of %d)\n"
+                                                       "Warning, sensor \"%s\" could not find its controller "
+                                                       "(link %d of %d) from object \"%s\"\n"
                                                        "\tthere has been an error converting the blender controller for the game engine,"
-                                                       "logic may be incorrect\n", sens->name, i+1, sens->totlinks);
+                                                       "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2);
                                        }
                                } else {
                                        printf(
-                                               "Warning, sensor \"%s\" has lost a link to a controller"
-                                               "(link %d of %d)\n"
+                                               "Warning, sensor \"%s\" has lost a link to a controller "
+                                               "(link %d of %d) from object \"%s\"\n"
                                                "\tpossible causes are partially appended objects or an error reading the file,"
-                                               "logic may be incorrect\n", sens->name, i+1, sens->totlinks);
+                                               "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2);
                                }
                        }
                        // done with gamesensor
index f433a08fabafe694176a7451991cb9bfc3417374..65cd4e890f73302099a7b23276513be981629976 100644 (file)
@@ -102,6 +102,12 @@ static inline void Py_Fatal(char *M) {
                return ((class_name*) self)->Py##method_name(self, args, kwds);         \
        }; \
 
+#define KX_PYMETHOD_VARARGS(class_name, method_name)                   \
+       PyObject* Py##method_name(PyObject* self, PyObject* args); \
+       static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
+               return ((class_name*) self)->Py##method_name(self, args);               \
+       }; \
+
 #define KX_PYMETHOD_NOARGS(class_name, method_name)                    \
        PyObject* Py##method_name(PyObject* self); \
        static PyObject* sPy##method_name( PyObject* self) { \
@@ -150,6 +156,9 @@ static inline void Py_Fatal(char *M) {
 #define KX_PYMETHODTABLE(class_name, method_name) \
        {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, class_name::method_name##_doc}
 
+#define KX_PYMETHODTABLE_NOARG(class_name, method_name) \
+       {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, class_name::method_name##_doc}
+
 /**
  * Function implementation macro
  */
@@ -157,6 +166,9 @@ static inline void Py_Fatal(char *M) {
 char class_name::method_name##_doc[] = doc_string; \
 PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*)
 
+#define KX_PYMETHODDEF_DOC_NOARG(class_name, method_name, doc_string) \
+char class_name::method_name##_doc[] = doc_string; \
+PyObject* class_name::Py##method_name(PyObject*)
 
 /*------------------------------
  * PyObjectPlus
index 18d7b6ffcd055a536c46bce27237f4ae57a74a0e..b244bddcacd1ec1baf6133320f256ed99187dd43 100644 (file)
@@ -29,9 +29,9 @@
 #include "SCA_Joystick.h"
 #include "SCA_JoystickPrivate.h"
 
-
-SCA_Joystick::SCA_Joystick()
+SCA_Joystick::SCA_Joystick(short int index)
        :
+       m_joyindex(index),
        m_axis10(0),
        m_axis11(0),
        m_axis20(0),
@@ -52,50 +52,53 @@ SCA_Joystick::~SCA_Joystick()
        delete m_private;
 }
 
-SCA_Joystick *SCA_Joystick::m_instance = NULL;
+SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX];
 int SCA_Joystick::m_refCount = 0;
 
-SCA_Joystick *SCA_Joystick::GetInstance()
+SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
 {
-       if (m_instance == 0) 
+       if (joyindex < 0 || joyindex >= JOYINDEX_MAX) {
+               echo("Error-invalid joystick index: " << joyindex);
+               return NULL;
+       }
+
+       if (m_refCount == 0) 
        {
-               m_instance = new SCA_Joystick();
-               m_instance->CreateJoystickDevice();
+               int i;
+               // do this once only
+               if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){
+                       echo("Error-Initializing-SDL: " << SDL_GetError());
+                       return NULL;
+               }
+               for (i=0; i<JOYINDEX_MAX; i++) {
+                       m_instance[i] = new SCA_Joystick(i);
+                       m_instance[i]->CreateJoystickDevice();
+               }
                m_refCount = 1;
        }
        else
        {
                m_refCount++;
        }
-       return m_instance;
+       return m_instance[joyindex];
 }
 
 void SCA_Joystick::ReleaseInstance()
 {
        if (--m_refCount == 0)
        {
-               DestroyJoystickDevice();
-               delete m_instance;
-               m_instance = NULL;
+               int i;
+               for (i=0; i<JOYINDEX_MAX; i++) {
+                       if (m_instance[i]) {
+                               m_instance[i]->DestroyJoystickDevice();
+                               delete m_instance[i];
+                       }
+                       m_instance[i]= NULL;
+               }
+               SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO );
        }
 }
 
-
-bool SCA_Joystick::CreateJoystickDevice()
-{
-       bool init = false;
-       init = pCreateJoystickDevice();
-       return init;
-}
-
-
-void SCA_Joystick::DestroyJoystickDevice()
-{
-       if(m_isinit)
-               pDestroyJoystickDevice();
-}
-
-
 void SCA_Joystick::HandleEvents()
 {
        if(m_isinit)
@@ -334,40 +337,34 @@ int SCA_Joystick::GetNumberOfHats()
        return -1;
 }
 
-bool SCA_Joystick::pCreateJoystickDevice()
+bool SCA_Joystick::CreateJoystickDevice(void)
 {
        if(m_isinit == false){
-               if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){
-                       echo("Error-Initializing-SDL: " << SDL_GetError());
-                       return false;
-               }
-               if(SDL_NumJoysticks() > 0){
-                       for(int i=0; i<SDL_NumJoysticks();i++){
-                               m_private->m_joystick = SDL_JoystickOpen(i);
-                               SDL_JoystickEventState(SDL_ENABLE);
-                               m_numjoys = i;
-                       }
-                       echo("Joystick-initialized");
-                       m_isinit = true;
-                       return true;
-               }else{
-                       echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
+               if (m_joyindex>=SDL_NumJoysticks()) {
+                       // don't print a message, because this is done anyway
+                       //echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
                        return false;
                }
+
+               m_private->m_joystick = SDL_JoystickOpen(m_joyindex);
+               SDL_JoystickEventState(SDL_ENABLE);
+       
+               echo("Joystick " << m_joyindex << " initialized");
+               m_isinit = true;
        }
-       return false;
+       return true;
 }
 
 
-void SCA_Joystick::pDestroyJoystickDevice()
+void SCA_Joystick::DestroyJoystickDevice(void)
 {
-       echo("Closing-");
-       for(int i=0; i<SDL_NumJoysticks(); i++){
-               if(SDL_JoystickOpened(i)){
+       if (m_isinit){
+               if(SDL_JoystickOpened(m_joyindex)){
+                       echo("Closing-joystick " << m_joyindex);
                        SDL_JoystickClose(m_private->m_joystick);
                }
+               m_isinit = false;
        }
-       SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO );
 }
 
 
index 1e853070b099362d05a43de25e091d9a7f9b3e20..689efc72975d820416377e7b658d369919d30ea0 100644 (file)
@@ -76,7 +76,7 @@
 class SCA_Joystick
 
 {
-       static SCA_Joystick *m_instance;
+       static SCA_Joystick *m_instance[JOYINDEX_MAX];
        static int m_refCount;
 
        class PrivateData;
@@ -85,14 +85,6 @@ class SCA_Joystick
 
        int                             m_joyindex;
 
-       /*!
-
-        * the number of avail joysticks 
-
-        */
-
-       int                     m_numjoys;
-
        /* 
 
         *support for 2 axes 
@@ -185,7 +177,7 @@ class SCA_Joystick
 
         */
 
-       bool pCreateJoystickDevice(void);
+       bool CreateJoystickDevice(void);
 
        /*
 
@@ -193,7 +185,7 @@ class SCA_Joystick
 
         */
 
-       void pDestroyJoystickDevice(void);
+       void DestroyJoystickDevice(void);
 
        
 
@@ -259,18 +251,13 @@ class SCA_Joystick
 
        int pGetHat(int direction);
 
-       SCA_Joystick();
+       SCA_Joystick(short int index);
 
        ~SCA_Joystick();
        
-       bool CreateJoystickDevice(void);
-
-       void DestroyJoystickDevice(void);
-
-
 public:
 
-       static SCA_Joystick *GetInstance();
+       static SCA_Joystick *GetInstance( short int joyindex );
 
        void ReleaseInstance();
        
index 15a421188b90ce1cd2332ced1d650e250016f9f6..8d8f88ecaf237455f15358c1da7f5a9390c93812 100644 (file)
@@ -38,6 +38,8 @@
 #define echo(x) std::cout << x << std::endl;
 #endif
 
+#define JOYINDEX_MAX                   8
+
 /* function callbacks */
 #define HANDLE_AXISMOTION(fn)  ((fn)(), 0L)
 #define HANDLE_HATMOTION(fn)   ((fn)(), 0L)
index 8f156cc63e7e6d42137dfee016412f809fd8b90c..0bd20117f316e0342ade13115d7687a6a4595b1c 100644 (file)
@@ -188,6 +188,8 @@ void SCA_IController::ApplyState(unsigned int state)
                        for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
                        {
                                (*sensit)->IncLink();
+                               // remember that this controller just activated that sensor
+                               (*sensit)->AddNewController(this);
                        }
                        SetActive(true);
                }
index f99b9b789d70f25071c891a29fd039ffbcf1a846..c96eb82e29ea95412ec02d82048b4f7ba7bce98a 100644 (file)
@@ -32,6 +32,8 @@
 #include "SCA_ISensor.h"
 #include "SCA_EventManager.h"
 #include "SCA_LogicManager.h"
+// needed for IsTriggered()
+#include "SCA_PythonController.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -132,10 +134,8 @@ void SCA_ISensor::DecLink() {
        }
        if (!m_links)
        {
-               // sensor is detached from all controllers, initialize it so that it
-               // is fresh as at startup when it is reattached again.
+               // sensor is detached from all controllers, remove it from manager
                UnregisterToManager();
-               Init();
        }
 }
 
@@ -168,7 +168,9 @@ PyParentObject SCA_ISensor::Parents[] = {
 };
 PyMethodDef SCA_ISensor::Methods[] = {
        {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, 
-        METH_VARARGS, IsPositive_doc},
+        METH_NOARGS, IsPositive_doc},
+       {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered, 
+        METH_VARARGS, IsTriggered_doc},
        {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, 
         METH_NOARGS, GetUsePosPulseMode_doc},
        {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, 
@@ -204,6 +206,9 @@ SCA_ISensor::_getattr(const STR_String& attr)
 
 void SCA_ISensor::RegisterToManager()
 {
+       // sensor is just activated, initialize it
+       Init();
+       m_newControllers.erase(m_newControllers.begin(), m_newControllers.end());
        m_eventmgr->RegisterSensor(this);
 }
 
@@ -249,19 +254,47 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr,        CValue* event)
                                }
                        }
                }
+               if (!m_newControllers.empty())
+               {
+                       if (!IsActive() && m_level)
+                       {
+                               // This level sensor is connected to at least one controller that was just made 
+                               // active but it did not generate an event yet, do it now to those controllers only 
+                               for (std::vector<SCA_IController*>::iterator ci=m_newControllers.begin();
+                                        ci != m_newControllers.end(); ci++)
+                               {
+                                       logicmgr->AddTriggeredController(*ci, this);
+                               }
+                       }
+                       // clear the list. Instead of using clear, which also release the memory,
+                       // use erase, which keeps the memory available for next time.
+                       m_newControllers.erase(m_newControllers.begin(), m_newControllers.end());
+               }
        } 
 }
 
 /* Python functions: */
 char SCA_ISensor::IsPositive_doc[] = 
 "isPositive()\n"
-"\tReturns whether the sensor is registered a positive event.\n";
-PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kwds)
+"\tReturns whether the sensor is in an active state.\n";
+PyObject* SCA_ISensor::PyIsPositive(PyObject* self)
 {
        int retval = IsPositiveTrigger();
        return PyInt_FromLong(retval);
 }
 
+char SCA_ISensor::IsTriggered_doc[] = 
+"isTriggered()\n"
+"\tReturns whether the sensor has triggered the current controller.\n";
+PyObject* SCA_ISensor::PyIsTriggered(PyObject* self)
+{
+       // check with the current controller
+       int retval = 0;
+       if (SCA_PythonController::m_sCurrentController)
+               retval = SCA_PythonController::m_sCurrentController->IsTriggered(this);
+       return PyInt_FromLong(retval);
+}
+
 /**
  * getUsePulseMode: getter for the pulse mode (KX_TRUE = on)
  */
index fc8f0bd001107ed3097c8296dd488f00a3a3651e..0d65270dc7b290e75b656a4ad10e08ffcd535c19 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "SCA_ILogicBrick.h"
 
+#include <vector>
+
 /**
  * Interface Class for all logic Sensors. Implements
  * pulsemode,pulsefrequency */
@@ -73,9 +75,9 @@ class SCA_ISensor : public SCA_ILogicBrick
        /** number of connections to controller */
        int m_links;
 
-       /** Pass the activation on to the logic manager.*/
-       void SignalActivation(class SCA_LogicManager* logicmgr);
-       
+       /** list of controllers that have just activated this sensor because of a state change */
+       std::vector<class SCA_IController*> m_newControllers;
+
 public:
        SCA_ISensor(SCA_IObject* gameobj,
                                class SCA_EventManager* eventmgr,
@@ -128,6 +130,8 @@ public:
        /** Resume sensing. */
        void Resume();
 
+       void AddNewController(class SCA_IController* controller)
+               { m_newControllers.push_back(controller); }
        void ClrLink()
                { m_links = 0; }
        void IncLink()
@@ -137,7 +141,8 @@ public:
                { return !m_links; }
 
        /* Python functions: */
-       KX_PYMETHOD_DOC(SCA_ISensor,IsPositive);
+       KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive);
+       KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered);
        KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode);
        KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode);
        KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency);
index 8ff28ba0b519247925ebd5cf27cf4fcac570a31a..08c36326712a54c37415bc8209715b7875afda25 100644 (file)
@@ -40,13 +40,20 @@ SCA_JoystickManager::SCA_JoystickManager(class SCA_LogicManager* logicmgr)
        : SCA_EventManager(JOY_EVENTMGR),
        m_logicmgr(logicmgr)
 {
-       m_joystick = SCA_Joystick::GetInstance();
+       int i;
+       for (i=0; i<JOYINDEX_MAX; i++) {
+               m_joystick[i] = SCA_Joystick::GetInstance( i );
+       }
+       //m_joystick = NULL;
 }
 
 
 SCA_JoystickManager::~SCA_JoystickManager()
 {
-       m_joystick->ReleaseInstance();
+       int i;
+       for (i=0; i<JOYINDEX_MAX; i++) {
+               m_joystick[i]->ReleaseInstance();
+       }
 }
 
 
@@ -58,17 +65,17 @@ void SCA_JoystickManager::NextFrame(double curtime,double deltatime)
                SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it);
                if(!joysensor->IsSuspended())
                {
-                       m_joystick->HandleEvents();
+                       m_joystick[joysensor->GetJoyIndex()]->HandleEvents();
                        joysensor->Activate(m_logicmgr, NULL);
                }
        }
 }
 
 
-SCA_Joystick *SCA_JoystickManager::GetJoystickDevice()
+SCA_Joystick *SCA_JoystickManager::GetJoystickDevice( short int joyindex)
 {
        /* 
         *Return the instance of SCA_Joystick for use 
         */
-       return m_joystick;
+       return m_joystick[joyindex];
 }
index f2bb27965fa660ff825ca621a8a0e49e2b93c4f9..d3a7ac95bea62da4340d944ae5c544a15cf012fc 100644 (file)
@@ -40,12 +40,12 @@ class SCA_JoystickManager : public SCA_EventManager
        /**
         * SDL Joystick Class Instance
         */
-       SCA_Joystick *m_joystick;
+       SCA_Joystick *m_joystick[JOYINDEX_MAX];
 public:
        SCA_JoystickManager(class SCA_LogicManager* logicmgr);
        virtual ~SCA_JoystickManager();
        virtual void NextFrame(double curtime,double deltatime);
-       SCA_Joystick* GetJoystickDevice(void);
+       SCA_Joystick* GetJoystickDevice(short int joyindex);
 
 };
 
index 3fb439eb25bf91ae201e7f069ea0f871a66fb3dd..4362a896f616efc38098e7256cdc8b475ea4b39f 100644 (file)
@@ -39,6 +39,7 @@
 
 SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
                                                                           SCA_IObject* gameobj,
+                                                                          short int joyindex,
                                                                           short int joymode,
                                                                           int axis, int axisf,int prec,
                                                                           int button, int buttonf,
@@ -53,7 +54,8 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
                                                                           m_hat(hat),
                                                                           m_hatf(hatf),
                                                                           m_precision(prec),
-                                                                          m_joymode(joymode)
+                                                                          m_joymode(joymode),
+                                                                          m_joyindex(joyindex)
 {      
 /*
 std::cout << " axis "          << m_axis               << std::endl;
@@ -99,7 +101,7 @@ bool SCA_JoystickSensor::IsPositiveTrigger()
 
 bool SCA_JoystickSensor::Evaluate(CValue* event)
 {
-       SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice();
+       SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
        bool result = false;
        bool reset = m_reset && m_level;
        
@@ -351,7 +353,7 @@ PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self,
                                                                                        PyObject* args, 
                                                                                        PyObject* kwds) {
        int a,b,c,d;
-       SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice();
+       SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
        a = joy->GetAxis10();
        b = joy->GetAxis11();
        c = joy->GetAxis20();
@@ -451,7 +453,7 @@ PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self,
                                                                                        PyObject* args, 
                                                                                        PyObject* kwds) {
        int num;
-       SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice();
+       SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
        num = joy->GetNumberOfAxes();
        return Py_BuildValue("i",num);
 }
@@ -464,7 +466,7 @@ PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self,
                                                                                        PyObject* args, 
                                                                                        PyObject* kwds) {
        int num;
-       SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice();
+       SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
        num = joy->GetNumberOfButtons();
        return Py_BuildValue("i",num);
 }
@@ -477,7 +479,7 @@ PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self,
                                                                                        PyObject* args, 
                                                                                        PyObject* kwds) {
        int num;
-       SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice();
+       SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
        num = joy->GetNumberOfHats();
        return Py_BuildValue("i",num);
 }
index 69068da6494762adbb7c76fcd03df055041d1bc4..e499d8cd0dc977cfa9344b16b8e0b0fc4d80bffe 100644 (file)
@@ -72,6 +72,10 @@ class SCA_JoystickSensor :public SCA_ISensor
         * The mode to determine axis,button or hat
         */
        short int m_joymode;
+       /**
+        * Select which joystick to use
+        */
+       short int m_joyindex;
 
        enum KX_JOYSENSORMODE {
                KX_JOYSENSORMODE_NODEF = 0,
@@ -85,6 +89,7 @@ class SCA_JoystickSensor :public SCA_ISensor
 public:
        SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
                                           SCA_IObject* gameobj,
+                                          short int joyindex,
                                           short int joymode,
                                           int axis, int axisf,int prec,
                                           int button, int buttonf,
@@ -97,6 +102,10 @@ public:
        virtual bool IsPositiveTrigger();
        virtual void Init();
        
+       short int GetJoyIndex(void){
+               return m_joyindex;
+       }
+
        /* --------------------------------------------------------------------- */
        /* Python interface ---------------------------------------------------- */
        /* --------------------------------------------------------------------- */
index a7a6fa93db46f3c778f9bb7e2dff450760b805eb..fba1162993d3c1a3916701bdc4e6faa3d08d75cc 100644 (file)
@@ -505,7 +505,7 @@ PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self,
                                       PyObject* kwds)
 {
 //     printf("sPyIsPositive\n");
-    return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds);
+    return ((SCA_KeyboardSensor*) self)->PyIsPositive(self);
 }
 
 
index 91e66aea35941e29977fa2fb6ccd9172f533c9c6..b584b37180ff53f9f6dbb25c2756cfbb43e7aed8 100644 (file)
@@ -33,6 +33,7 @@
 #include "SCA_IController.h"
 #include "SCA_IActuator.h"
 #include "SCA_EventManager.h"
+#include "SCA_PythonController.h"
 #include <set>
 
 #ifdef HAVE_CONFIG_H
@@ -232,8 +233,6 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime)
        // for this frame, look up for activated sensors, and build the collection of triggered controllers
        // int numsensors = this->m_activatedsensors.size(); /*unused*/
 
-       set<SmartControllerPtr> triggeredControllerSet;
-
        for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin();
        !(is==m_activatedsensors.end());is++)
        {
@@ -244,19 +243,28 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime)
                {
                                SCA_IController* contr = *c;//controllerarray->at(c);
                                if (contr->IsActive())
-                                       triggeredControllerSet.insert(SmartControllerPtr(contr,0));
+                               {
+                                       m_triggeredControllerSet.insert(SmartControllerPtr(contr,0));
+                                       // So that the controller knows which sensor has activited it.
+                                       // Only needed for the python controller though.
+                                       if (contr->GetType() == &SCA_PythonController::Type)
+                                       {
+                                               SCA_PythonController* pythonController = (SCA_PythonController*)contr;
+                                               pythonController->AddTriggeredSensor(sensor);
+                                       }
+                               }
                }
                //sensor->SetActive(false);
        }
 
        
        // int numtriggered = triggeredControllerSet.size(); /*unused*/
-       for (set<SmartControllerPtr>::iterator tit=triggeredControllerSet.begin();
-       !(tit==triggeredControllerSet.end());tit++)
+       for (set<SmartControllerPtr>::iterator tit=m_triggeredControllerSet.begin();
+       !(tit==m_triggeredControllerSet.end());tit++)
        {
                (*tit)->Trigger(this);
        }
-       triggeredControllerSet.clear();
+       m_triggeredControllerSet.clear();
 }
 
 
@@ -382,6 +390,17 @@ void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor)
        }
 }
 
+void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor)
+{
+       m_triggeredControllerSet.insert(SmartControllerPtr(controller,0));
+       // so that the controller knows which sensor has activited it
+       // only needed for python controller
+       if (controller->GetType() == &SCA_PythonController::Type)
+       {
+               SCA_PythonController* pythonController = (SCA_PythonController*)controller;
+               pythonController->AddTriggeredSensor(sensor);
+       }
+}
 
 
 void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event)
index e0d3d50670253d501fbf5dad8e026ccc767a859b..50383879d8f0f4ed8f79009f20b239f9b339a0e6 100644 (file)
@@ -99,6 +99,7 @@ class SCA_LogicManager
        
        vector<class SCA_ISensor*>                      m_activatedsensors;
        set<class SmartActuatorPtr>                     m_activeActuators;
+       set<class SmartControllerPtr>           m_triggeredControllerSet;
 
        map<SCA_ISensor*,controllerlist >       m_sensorcontrollermapje;
 
@@ -127,6 +128,7 @@ public:
        void    EndFrame();
        void    AddActivatedSensor(SCA_ISensor* sensor);
        void    AddActiveActuator(SCA_IActuator* sensor,class CValue* event);
+       void    AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor);
        SCA_EventManager*       FindEventManager(int eventmgrtype);
        
        void    RemoveGameObject(const STR_String& gameobjname);
index f9081c90288ccc54736e9e72ecef87e3027eda48..e6f7b1dd143ac9fab349e8dcd41ad0b85d87dba6 100644 (file)
@@ -35,6 +35,7 @@
 #include "SCA_IActuator.h"
 #include "compile.h"
 #include "eval.h"
+#include <algorithm>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -139,6 +140,14 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary)
        m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */
 }
 
+int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor)
+{
+       if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) != 
+               m_triggeredSensors.end())
+               return 1;
+       return 0;
+}
+
 #if 0
 static char* sPyGetCurrentController__doc__;
 #endif
@@ -294,7 +303,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
        // something in this dictionary and crash?
        PyDict_Clear(excdict);
        Py_DECREF(excdict);
-
+       m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end());
        m_sCurrentController = NULL;
 }
 
index 39b6c68c359b8102c07cd8c761d6e95f471e0be3..1b62e7ecb5325279f4ab24d46d8b390e81f84bfc 100644 (file)
@@ -36,6 +36,8 @@
 #include "SCA_LogicManager.h"
 #include "BoolValue.h"
 
+#include <vector>
+
 class SCA_IObject;
 class SCA_PythonController : public SCA_IController
 {
@@ -47,6 +49,7 @@ class SCA_PythonController : public SCA_IController
        STR_String                              m_scriptText;
        STR_String                              m_scriptName;
        PyObject*                               m_pythondictionary;
+       std::vector<class SCA_ISensor*>         m_triggeredSensors;
 
  public: 
        static SCA_PythonController* m_sCurrentController; // protected !!!
@@ -64,6 +67,9 @@ class SCA_PythonController : public SCA_IController
        void    SetScriptText(const STR_String& text);
        void    SetScriptName(const STR_String& name);
        void    SetDictionary(PyObject* pythondictionary);
+       void    AddTriggeredSensor(class SCA_ISensor* sensor)
+               { m_triggeredSensors.push_back(sensor); }
+       int             IsTriggered(class SCA_ISensor* sensor);
 
        static char* sPyGetCurrentController__doc__;
        static PyObject* sPyGetCurrentController(PyObject* self);
index 8b828393c67e0ea13478306f080ee8eccc003d37..a64c85f6c17d17d008194ffb39ee4515b7d1dfa4 100644 (file)
@@ -470,11 +470,11 @@ void GPC_RenderTools::SetClientObject(void* obj)
        }
 }
 
-bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
 {
        double* const oglmatrix = (double* const) data;
-       MT_Point3 resultpoint(hit_point);
-       MT_Vector3 resultnormal(hit_normal);
+       MT_Point3 resultpoint(result->m_hitPoint);
+       MT_Vector3 resultnormal(result->m_hitNormal);
        MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
        MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
        left = (dir.cross(resultnormal)).safe_normalized();
@@ -563,9 +563,8 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
                        if (parent)
                                parent->Release();
                                
-                       MT_Point3 resultpoint;
-                       MT_Vector3 resultnormal;
-                       if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback<GPC_RenderTools>(this, oglmatrix)))
+                       KX_RayCast::Callback<GPC_RenderTools> callback(this, physics_controller, oglmatrix);
+                       if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback))
                        {
                                // couldn't find something to cast the shadow on...
                                glMultMatrixd(oglmatrix);
index 8fae3d2b305880cd3268dae5cd8f9ee5964f4adb..9f70f67caf2b32ab5422d1b43f75f7356cb82518 100644 (file)
@@ -41,7 +41,7 @@
 #include "BMF_Api.h"
 
 struct KX_ClientObjectInfo;
-
+class KX_RayCast;
 
 class GPC_RenderTools : public RAS_IRenderTools
 {
@@ -138,7 +138,8 @@ public:
 
        int applyLights(int objectlayer);
 
-       bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+       bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+       bool NeedRayCast(KX_ClientObjectInfo* client) { return true; }
 
        virtual void MotionBlur(RAS_IRasterizer* rasterizer);
 
index f859193ef7a6785176945970aaf685b643ca804c..c56a6d0da237f7b7f20474e543283b472e4398de 100644 (file)
@@ -716,6 +716,7 @@ void GPG_Application::stopEngine()
                                } else {
                                        printf("Error, GameLogic.globalDict could not be marshal'd\n");
                                }
+                               Py_DECREF(gameLogic);
                        } else {
                                printf("Error, GameLogic.globalDict was removed\n");
                        }
index e00ec68ad331575dba14689d85168e0665a2d7aa..4b57b0e8c54ce0ca8eaf7ac0281e738deef6ba58 100644 (file)
@@ -109,16 +109,11 @@ KX_ConstraintActuator::~KX_ConstraintActuator()
        // there's nothing to be done here, really....
 } /* end of destructor */
 
-bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
 {
 
        KX_GameObject* hitKXObj = client->m_gameobject;
        
-       if (client->m_type > KX_ClientObjectInfo::ACTOR)
-       {
-               // false hit
-               return false;
-       }
        bool bFound = false;
 
        if (m_property[0] == 0)
@@ -139,8 +134,26 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_p
                        bFound = hitKXObj->GetProperty(m_property) != NULL;
                }
        }
+       // update the hit status
+       result->m_hitFound = bFound;
+       // stop looking
+       return true;
+}
 
-       return bFound;
+/* this function is used to pre-filter the object before casting the ray on them.
+   This is useful for "X-Ray" option when we want to see "through" unwanted object.
+ */
+bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo* client)
+{
+       if (client->m_type > KX_ClientObjectInfo::ACTOR)
+       {
+               // Unknown type of object, skip it.
+               // Should not occur as the sensor objects are filtered in RayTest()
+               printf("Invalid client type %d found in ray casting\n", client->m_type);
+               return false;
+       }
+       // no X-Ray function yet
+       return true;
 }
 
 bool KX_ConstraintActuator::Update(double curtime, bool frame)
@@ -287,8 +300,6 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
                        direction.normalize();
                        {
                                MT_Point3 topoint = position + (m_maximumBound) * direction;
-                               MT_Point3 resultpoint;
-                               MT_Vector3 resultnormal;
                                PHY_IPhysicsEnvironment* pe = obj->GetPhysicsEnvironment();
                                KX_IPhysicsController *spc = obj->GetPhysicsController();
 
@@ -304,9 +315,10 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
                                                parent->Release();
                                        }
                                }
-                               result = KX_RayCast::RayTest(spc, pe, position, topoint, resultpoint, resultnormal, KX_RayCast::Callback<KX_ConstraintActuator>(this));
-
+                               KX_RayCast::Callback<KX_ConstraintActuator> callback(this,spc);
+                               result = KX_RayCast::RayTest(pe, position, topoint, callback);
                                if (result)     {
+                                       MT_Vector3 newnormal = callback.m_hitNormal;
                                        // compute new position & orientation
                                        if ((m_option & (KX_ACT_CONSTRAINT_NORMAL|KX_ACT_CONSTRAINT_DISTANCE)) == 0) {
                                                // if none option is set, the actuator does nothing but detect ray 
@@ -316,27 +328,27 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
                                        if (m_option & KX_ACT_CONSTRAINT_NORMAL) {
                                                // the new orientation must be so that the axis is parallel to normal
                                                if (sign)
-                                                       resultnormal = -resultnormal;
+                                                       newnormal = -newnormal;
                                                // apply damping on the direction
                                                if (m_rotDampTime) {
                                                        MT_Scalar rotFilter = 1.0/(1.0+m_rotDampTime);
-                                                       resultnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*resultnormal;
+                                                       newnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*newnormal;
                                                } else if (m_posDampTime) {
-                                                       resultnormal = -filter*direction + (1.0-filter)*resultnormal;
+                                                       newnormal = -filter*direction + (1.0-filter)*newnormal;
                                                }
-                                               obj->AlignAxisToVect(resultnormal, axis);
-                                               direction = -resultnormal;
+                                               obj->AlignAxisToVect(newnormal, axis);
+                                               direction = -newnormal;
                                        }
                                        if (m_option & KX_ACT_CONSTRAINT_DISTANCE) {
                                                if (m_posDampTime) {
-                                                       newdistance = filter*(position-resultpoint).length()+(1.0-filter)*m_minimumBound;
+                                                       newdistance = filter*(position-callback.m_hitPoint).length()+(1.0-filter)*m_minimumBound;
                                                } else {
                                                        newdistance = m_minimumBound;
                                                }
                                        } else {
-                                               newdistance = (position-resultpoint).length();
+                                               newdistance = (position-callback.m_hitPoint).length();
                                        }
-                                       newposition = resultpoint-newdistance*direction;
+                                       newposition = callback.m_hitPoint-newdistance*direction;
                                } else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) {
                                        // no contact but still keep running
                                        result = true;
index d9f39124cac550a96b69b6e1ff287edc789925d4..6ec4de9aad96f6a73e2bca099d94d628f338126f 100644 (file)
@@ -37,6 +37,8 @@
 #include "MT_Vector3.h"
 #include "KX_ClientObjectInfo.h"
 
+class KX_RayCast;
+
 class KX_ConstraintActuator : public SCA_IActuator
 {
        Py_Header;
@@ -100,7 +102,8 @@ protected:
                KX_ACT_CONSTRAINT_DISTANCE = 512
        };
        bool IsValidMode(KX_CONSTRAINTTYPE m); 
-       bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+       bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+       bool NeedRayCast(KX_ClientObjectInfo*);
 
        KX_ConstraintActuator(SCA_IObject* gameobj,
                                                  int posDamptime,
index 700cc00e996c5e5c690e8616628c402d1eacef5b..c1b228e8d26bfdfabf33648e3b21da6a2a5e225d 100644 (file)
@@ -51,6 +51,7 @@ typedef unsigned long uint_ptr;
 #include "KX_GameObject.h"
 #include "RAS_MeshObject.h"
 #include "KX_MeshProxy.h"
+#include "KX_PolyProxy.h"
 #include <stdio.h> // printf
 #include "SG_Controller.h"
 #include "KX_IPhysicsController.h"
@@ -84,6 +85,7 @@ KX_GameObject::KX_GameObject(
        m_bVisible(true),
        m_pPhysicsController1(NULL),
        m_pPhysicsEnvironment(NULL),
+       m_xray(false),
        m_pHitObject(NULL),
        m_isDeformable(false)
 {
@@ -885,6 +887,8 @@ PyMethodDef KX_GameObject::Methods[] = {
        {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
        {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
        {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
+       {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
+       {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
        {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
        {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
        {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
@@ -1146,9 +1150,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value)      // _setattr
 }
 
 
-PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, 
-                                                                                        PyObject* args, 
-                                                                                        PyObject* kwds)
+PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args)
 {
        // only can get the velocity if we have a physics object connected to us...
        int local = 0;
@@ -1162,9 +1164,7 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self,
        }
 }
 
-PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, 
-                                                                                        PyObject* args, 
-                                                                                        PyObject* kwds)
+PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args)
 {
        int local = 0;
        PyObject* pyvect;
@@ -1179,6 +1179,35 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self,
        return NULL;
 }
 
+PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args)
+{
+       // only can get the velocity if we have a physics object connected to us...
+       int local = 0;
+       if (PyArg_ParseTuple(args,"|i",&local))
+       {
+               return PyObjectFrom(GetAngularVelocity((local!=0)));
+       }
+       else
+       {
+               return NULL;
+       }
+}
+
+PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
+{
+       int local = 0;
+       PyObject* pyvect;
+       
+       if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) {
+               MT_Vector3 velocity;
+               if (PyVecTo(pyvect, velocity)) {
+                       setAngularVelocity(velocity, (local!=0));
+                       Py_RETURN_NONE;
+               }
+       }
+       return NULL;
+}
+
 PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value)
 {
        int visible = PyInt_AsLong(value);
@@ -1228,9 +1257,7 @@ PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
 
 
 
-PyObject* KX_GameObject::PyGetVelocity(PyObject* self, 
-                                                                          PyObject* args, 
-                                                                          PyObject* kwds)
+PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args)
 {
        // only can get the velocity if we have a physics object connected to us...
        MT_Vector3 velocity(0.0,0.0,0.0);
@@ -1362,9 +1389,7 @@ PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
        return list;
 }
 
-PyObject* KX_GameObject::PyGetMesh(PyObject* self, 
-                                                                  PyObject* args, 
-                                                                  PyObject* kwds)
+PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args)
 {
        int mesh = 0;
 
@@ -1404,9 +1429,7 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
 
 
 
-PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, 
-                                                                               PyObject* args, 
-                                                                               PyObject* kwds)
+PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args)
 {
        PyObject* pyattach;
        PyObject* pyimpulse;
@@ -1477,9 +1500,7 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
        return NULL;
 }
 
-PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, 
-                                                                                 PyObject* args, 
-                                                                                 PyObject* kwds)
+PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args)
 {
        PyObject* pyvect;
        int axis = 2; //z axis is the default
@@ -1609,25 +1630,45 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo,
        return returnValue;
 }
 
-bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
 {
+       KX_GameObject* hitKXObj = client->m_gameobject;
+       
+       // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
+       // if not, all objects were tested and the front one may not be the correct one.
+       if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
+       {
+               m_pHitObject = hitKXObj;
+               return true;
+       }
+       // return true to stop RayCast::RayTest from looping, the above test was decisive
+       // We would want to loop only if we want to get more than one hit point
+       return true;
+}
 
+/* this function is used to pre-filter the object before casting the ray on them.
+   This is useful for "X-Ray" option when we want to see "through" unwanted object.
+ */
+bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client)
+{
        KX_GameObject* hitKXObj = client->m_gameobject;
        
        if (client->m_type > KX_ClientObjectInfo::ACTOR)
        {
-               // false hit
+               // Unknown type of object, skip it.
+               // Should not occur as the sensor objects are filtered in RayTest()
+               printf("Invalid client type %d found in ray casting\n", client->m_type);
                return false;
        }
-
-       if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
+       
+       // if X-Ray option is selected, skip object that don't match the criteria as we see through them
+       // if not, test all objects because we don't know yet which one will be on front
+       if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
        {
-               m_pHitObject = hitKXObj;
                return true;
        }
-
+       // skip the object
        return false;
-       
 }
 
 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
@@ -1667,8 +1708,6 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
                toPoint = fromPoint + (dist) * toDir;
        }
 
-       MT_Point3 resultPoint;
-       MT_Vector3 resultNormal;
        PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
        KX_IPhysicsController *spc = GetPhysicsController();
        KX_GameObject *parent = GetParent();
@@ -1682,7 +1721,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
                m_testPropName = propName;
        else
                m_testPropName.SetLength(0);
-       KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
+       KX_RayCast::Callback<KX_GameObject> callback(this,spc);
+       KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
 
     if (m_pHitObject)
        {
@@ -1693,13 +1733,24 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
 }
 
 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
-                                  "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or (None,None,None) tuple if no hit\n"
-" prop = property name that object must have; can be omitted => detect any object\n"
-" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
+                                  "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n"
+                                  " If no hit, return (None,None,None) or (None,None,None,None).\n"
+" to   = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
 "        Can be None or omitted => start from self object center\n"
-" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
-"Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n")
+" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
+" prop = property name that object must have; can be omitted => detect any object\n"
+" face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n"
+" xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
+" poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
+"                           which can be None if hit object has no mesh or if there is no hit\n"
+"        If 0 or omitted, return value is a 3-tuple\n"
+"Note: The object on which you call this method matters: the ray will ignore it.\n"
+"      prop and xray option interact as follow:\n"
+"        prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n"
+"        prop off, xray on : idem\n"
+"        prop on,  xray off: return closest hit if it matches prop, no hit otherwise\n"
+"        prop on,  xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n")
 {
        MT_Point3 toPoint;
        MT_Point3 fromPoint;
@@ -1708,8 +1759,9 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
        float dist = 0.0f;
        char *propName = NULL;
        KX_GameObject *other;
+       int face=0, xray=0, poly=0;
 
-       if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) {
+       if (!PyArg_ParseTuple(args,"O|Ofsiii", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) {
                return NULL; // Python sets a simple error
        }
 
@@ -1755,8 +1807,6 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
                return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
        }
        
-       MT_Point3 resultPoint;
-       MT_Vector3 resultNormal;
        PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
        KX_IPhysicsController *spc = GetPhysicsController();
        KX_GameObject *parent = GetParent();
@@ -1770,20 +1820,41 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
                m_testPropName = propName;
        else
                m_testPropName.SetLength(0);
-       KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
+       m_xray = xray;
+       // to get the hit results
+       KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face);
+       KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
 
-    if (m_pHitObject)
+       if (m_pHitObject)
        {
-               PyObject* returnValue = PyTuple_New(3);
+               PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
                if (returnValue) { // unlikely this would ever fail, if it does python sets an error
                        PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
-                       PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint));
-                       PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal));
+                       PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
+                       PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
+                       if (poly)
+                       {
+                               if (callback.m_hitMesh)
+                               {
+                                       // if this field is set, then we can trust that m_hitPolygon is a valid polygon
+                                       RAS_Polygon* poly = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
+                                       KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, poly);
+                                       PyTuple_SET_ITEM(returnValue, 3, polyproxy);
+                               }
+                               else
+                               {
+                                       Py_INCREF(Py_None);
+                                       PyTuple_SET_ITEM(returnValue, 3, Py_None);
+                               }
+                       }
                }
                return returnValue;
        }
-       return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
-       //Py_RETURN_NONE;
+       // no hit
+       if (poly)
+               return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
+       else
+               return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
 }
 
 /* --------------------------------------------------------------------- 
index a7ac2d75a930b2824bd38580cb5c5d7c3f0742f3..508bc7cdfd00cdedec9e978b3f8b1c5460c6050b 100644 (file)
@@ -54,6 +54,7 @@
 
 //Forward declarations.
 struct KX_ClientObjectInfo;
+class KX_RayCast;
 class RAS_MeshObject;
 class KX_IPhysicsController;
 class PHY_IPhysicsEnvironment;
@@ -88,6 +89,7 @@ protected:
        // used for ray casting
        PHY_IPhysicsEnvironment*                        m_pPhysicsEnvironment;
        STR_String                                                      m_testPropName;
+       bool                                                            m_xray;
        KX_GameObject*                                          m_pHitObject;
 
        SG_Node*                                                        m_pSGNode;
@@ -428,7 +430,8 @@ public:
                return (m_pSGNode && m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsVertexParent());
        }
 
-       bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+       bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+       bool NeedRayCast(KX_ClientObjectInfo* client);
 
 
        /**
@@ -726,9 +729,11 @@ public:
 
        KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition);
        KX_PYMETHOD_O(KX_GameObject,SetPosition);
-       KX_PYMETHOD(KX_GameObject,GetLinearVelocity);
-       KX_PYMETHOD(KX_GameObject,SetLinearVelocity);
-       KX_PYMETHOD(KX_GameObject,GetVelocity);
+       KX_PYMETHOD_VARARGS(KX_GameObject,GetLinearVelocity);
+       KX_PYMETHOD_VARARGS(KX_GameObject,SetLinearVelocity);
+       KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity);
+       KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity);
+       KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetMass);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetOrientation);
@@ -737,20 +742,20 @@ public:
        KX_PYMETHOD_O(KX_GameObject,SetVisible);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetState);
        KX_PYMETHOD_O(KX_GameObject,SetState);
-       KX_PYMETHOD(KX_GameObject,AlignAxisToVect);
+       KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect);
        KX_PYMETHOD_O(KX_GameObject,GetAxisVect);
        KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics);
        KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics);
        KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody);
        KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody);
-       KX_PYMETHOD(KX_GameObject,ApplyImpulse);
+       KX_PYMETHOD_VARARGS(KX_GameObject,ApplyImpulse);
        KX_PYMETHOD_O(KX_GameObject,SetCollisionMargin);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetParent);
        KX_PYMETHOD_O(KX_GameObject,SetParent);
        KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren);  
        KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive);
-       KX_PYMETHOD(KX_GameObject,GetMesh);
+       KX_PYMETHOD_VARARGS(KX_GameObject,GetMesh);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetPhysicsId);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetPropertyNames);
        KX_PYMETHOD_NOARGS(KX_GameObject,EndObject);
index d3aa924665e6531574a741623b3f7b2ff1c1c2bb..6223643f75a6e6082ebd295a21c80b7291f88b79 100644 (file)
@@ -143,7 +143,7 @@ bool KX_IpoSGController::Update(double currentTime)
                {
                        if (m_ipo_as_force == true) 
                        {
-                               if (m_game_object && ob) 
+                               if (m_game_object && ob && m_game_object->GetPhysicsController()
                                {
                                        m_game_object->GetPhysicsController()->ApplyForce(m_ipo_local ?
                                                ob->GetWorldOrientation() * m_ipo_xform.GetPosition() :
index a0ac9cfd4ff0338dfd57172e2a147d50da10ab29..29842af7fb6b6c116ac4ae0414f639c7e6d60b81 100644 (file)
@@ -35,6 +35,7 @@
 #include "RAS_MeshObject.h"
 
 #include "KX_VertexProxy.h"
+#include "KX_PolyProxy.h"
 
 #include "KX_PolygonMaterial.h"
 #include "KX_BlenderMaterial.h"
@@ -71,10 +72,12 @@ PyParentObject KX_MeshProxy::Parents[] = {
 
 PyMethodDef KX_MeshProxy::Methods[] = {
 {"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS},
+{"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS},
 {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS},
 {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS},
 {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
 {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS},
+{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS},
 KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh),
 //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS},
 
@@ -146,6 +149,12 @@ PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* self,
        return PyInt_FromLong(num);
 }
 
+PyObject* KX_MeshProxy::PyGetNumPolygons(PyObject* self)
+{
+       int num = m_meshobj->NumPolygons();
+       return PyInt_FromLong(num);
+}
+
 PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self, 
                               PyObject* args, 
                               PyObject* kwds)
@@ -234,6 +243,28 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* self,
                
 }
 
+PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self,
+                              PyObject* args, 
+                              PyObject* kwds)
+{
+    int polyindex= 1;
+       PyObject* polyob = NULL;
+
+       if (!PyArg_ParseTuple(args,"i",&polyindex))
+               return NULL;
+
+       RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex);
+       if (polygon)
+       {
+               polyob = new KX_PolyProxy(m_meshobj, polygon);
+       }
+       else
+       {
+               PyErr_SetString(PyExc_AttributeError, "Invalid polygon index");
+       }
+       return polyob;
+}
+
 KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh,
 "Reinstance the physics mesh.")
 {
index 7c6202c15a4661bd4c312d74fe39d2d7f9ef8641..3335c349673f6b690aa6f605e4d67048f9751a32 100644 (file)
@@ -57,10 +57,12 @@ public:
        KX_PYMETHOD(KX_MeshProxy,GetNumMaterials);
        KX_PYMETHOD(KX_MeshProxy,GetMaterialName);
        KX_PYMETHOD(KX_MeshProxy,GetTextureName);
+       KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons);
        
        // both take materialid (int)
        KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength);
        KX_PYMETHOD(KX_MeshProxy,GetVertex);
+       KX_PYMETHOD(KX_MeshProxy,GetPolygon);
        KX_PYMETHOD_DOC(KX_MeshProxy, reinstancePhysicsMesh);
 };
 
index db0bef8b7e1d504f4d6910c4cc2b91697ffb4d70..3156f543ed57caf0c2297b7f328a5c0c35251b9d 100644 (file)
@@ -122,16 +122,10 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event)
        return result;
 }
 
-bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* result, void * const data)
 {
        KX_GameObject* hitKXObj = client_info->m_gameobject;
        
-       if (client_info->m_type > KX_ClientObjectInfo::ACTOR)
-       {
-               // false hit
-               return false;
-       }
-       
        /* Is this me? In the ray test, there are a lot of extra checks
        * for aliasing artefacts from self-hits. That doesn't happen
        * here, so a simple test suffices. Or does the camera also get
@@ -142,8 +136,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hi
        if ((m_focusmode == 2) || hitKXObj == thisObj)
        {
                m_hitObject = hitKXObj;
-               m_hitPosition = hit_point;
-               m_hitNormal = hit_normal;
+               m_hitPosition = result->m_hitPoint;
+               m_hitNormal = result->m_hitNormal;
                return true;
        }
        
@@ -158,8 +152,6 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
        m_hitObject = 0;
        m_hitPosition = MT_Vector3(0,0,0);
        m_hitNormal =   MT_Vector3(1,0,0);
-       MT_Point3 resultpoint;
-       MT_Vector3 resultnormal;
 
        /* All screen handling in the gameengine is done by GL,
         * specifically the model/view and projection parts. The viewport
@@ -280,7 +272,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
 
        bool result = false;
 
-       result = KX_RayCast::RayTest(physics_controller, physics_environment, frompoint3, topoint3, resultpoint, resultnormal, KX_RayCast::Callback<KX_MouseFocusSensor>(this));
+       KX_RayCast::Callback<KX_MouseFocusSensor> callback(this,physics_controller);
+       KX_RayCast::RayTest(physics_environment, frompoint3, topoint3, callback);
        
        result = (m_hitObject!=0);
 
index b011ebe1288e9bc713a6674e746d53481f6af56c..a6cc39d66ebc41ae15cf8d5d1337810d3699d2d3 100644 (file)
@@ -33,6 +33,8 @@
 
 #include "SCA_MouseSensor.h"
 
+class KX_RayCast;
+
 /**
  * The mouse focus sensor extends the basic SCA_MouseSensor. It has
  * been placed in KX because it needs access to the rasterizer and
@@ -76,7 +78,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
                return result;
        };
 
-       bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+       bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+       bool NeedRayCast(KX_ClientObjectInfo* client) { return true; }
+       
 
        
        /* --------------------------------------------------------------------- */
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp
new file mode 100644 (file)
index 0000000..658c8a9
--- /dev/null
@@ -0,0 +1,265 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "KX_PolyProxy.h"
+#include "KX_MeshProxy.h"
+#include "RAS_MeshObject.h"
+#include "KX_BlenderMaterial.h"
+#include "KX_PolygonMaterial.h"
+
+#include "KX_PyMath.h"
+
+PyTypeObject KX_PolyProxy::Type = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,
+       "KX_PolyProxy",
+       sizeof(KX_PolyProxy),
+       0,
+       PyDestructor,
+       0,
+       __getattr,
+       __setattr,
+       0, //&MyPyCompare,
+       __repr,
+       0, //&cvalue_as_number,
+       0,
+       0,
+       0,
+       0
+};
+
+PyParentObject KX_PolyProxy::Parents[] = {
+       &KX_PolyProxy::Type,
+       &SCA_IObject::Type,
+       &CValue::Type,
+       NULL
+};
+
+PyMethodDef KX_PolyProxy::Methods[] = {
+       KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterialIndex),
+       KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getNumVertex),
+       KX_PYMETHODTABLE_NOARG(KX_PolyProxy,isVisible),
+       KX_PYMETHODTABLE_NOARG(KX_PolyProxy,isCollider),
+       KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterialName),
+       KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getTextureName),
+       KX_PYMETHODTABLE(KX_PolyProxy,getVertexIndex),
+       KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMesh),
+       KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterial),
+       {NULL,NULL} //Sentinel
+};
+
+PyObject*
+KX_PolyProxy::_getattr(const STR_String& attr)
+{
+       if (attr == "matname")
+       {
+               return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
+       }
+       if (attr == "texture")
+       {
+               return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
+       }
+       if (attr == "material")
+       {
+               RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial();
+               if(polymat->GetFlag() & RAS_BLENDERMAT)
+               {
+                       KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
+                       Py_INCREF(mat);
+                       return mat;
+               }
+               else
+               {
+                       KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
+                       Py_INCREF(mat);
+                       return mat;
+               }
+       }
+       if (attr == "matid")
+       {
+               // we'll have to scan through the material bucket of the mes and compare with 
+               // the one of the polygon
+               RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
+               unsigned int matid;
+               for (matid=0; matid<m_mesh->NumMaterials(); matid++)
+               {
+                       RAS_MaterialBucket* meshBucket = m_mesh->GetMaterialBucket(matid);
+                       if (meshBucket == polyBucket)
+                               // found it
+                               break;
+               }
+               return PyInt_FromLong(matid);
+       }
+       if (attr == "v1")
+       {
+               return PyInt_FromLong(m_polygon->GetVertexIndexBase().m_indexarray[0]);
+       }
+       if (attr == "v2")
+       {
+               return PyInt_FromLong(m_polygon->GetVertexIndexBase().m_indexarray[1]);
+       }
+       if (attr == "v3")
+       {
+               return PyInt_FromLong(m_polygon->GetVertexIndexBase().m_indexarray[2]);
+       }
+       if (attr == "v4")
+       {
+               return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexIndexBase().m_indexarray[3]:0));
+       }
+       if (attr == "visible")
+       {
+               return PyInt_FromLong(m_polygon->IsVisible());
+       }
+       if (attr == "collide")
+       {
+               return PyInt_FromLong(m_polygon->IsCollider());
+       }
+       _getattr_up(SCA_IObject);
+}
+
+KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon)
+:      m_mesh((RAS_MeshObject*)mesh),
+       m_polygon(polygon)
+{
+}
+
+KX_PolyProxy::~KX_PolyProxy()
+{
+}
+
+
+// stuff for cvalue related things
+CValue*                KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
+CValue*                KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}      
+STR_String     sPolyName="polygone";
+const STR_String &     KX_PolyProxy::GetText() {return sPolyName;};
+float          KX_PolyProxy::GetNumber() { return -1;}
+STR_String     KX_PolyProxy::GetName() { return sPolyName;}
+void           KX_PolyProxy::SetName(STR_String) { };
+CValue*                KX_PolyProxy::GetReplica() { return NULL;}
+void           KX_PolyProxy::ReplicaSetName(STR_String) {};
+
+
+// stuff for python integration
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialIndex, 
+"getMaterialIndex() : return the material index of the polygon in the mesh\n")
+{
+       RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
+       unsigned int matid;
+       for (matid=0; matid<m_mesh->NumMaterials(); matid++)
+       {
+               RAS_MaterialBucket* meshBucket = m_mesh->GetMaterialBucket(matid);
+               if (meshBucket == polyBucket)
+                       // found it
+                       break;
+       }
+       return PyInt_FromLong(matid);
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getNumVertex,
+"getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n")
+{
+       return PyInt_FromLong(m_polygon->VertexCount());
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isVisible,
+"isVisible() : returns whether the polygon is visible or not\n")
+{
+       return PyInt_FromLong(m_polygon->IsVisible());
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isCollider,
+"isCollider() : returns whether the polygon is receives collision or not\n")
+{
+       return PyInt_FromLong(m_polygon->IsCollider());
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialName,
+"getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n")
+{
+       return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getTextureName,
+"getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n")
+{
+       return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
+}
+
+KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
+"getVertexIndex(vertex) : returns the mesh vertex index of a polygon vertex\n"
+"vertex: index of the vertex in the polygon: 0->3\n"
+"return value can be used to retrieve the vertex details through mesh proxy\n"
+"Note: getVertexIndex(3) on a triangle polygon returns 0\n")
+{
+       int index;
+       if (!PyArg_ParseTuple(args,"i",&index))
+       {
+               return NULL;
+       }
+       if (index < 0 || index > 3)
+       {
+               PyErr_SetString(PyExc_AttributeError, "Valid range for index is 0-3");
+               return NULL;
+       }
+       if (index < m_polygon->VertexCount())
+       {
+               return PyInt_FromLong(m_polygon->GetVertexIndexBase().m_indexarray[index]);
+       }
+       return PyInt_FromLong(0);
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMesh,
+"getMesh() : returns a mesh proxy\n")
+{
+       KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh);
+       return meshproxy;
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterial,
+"getMaterial() : returns a material\n")
+{
+       RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial();
+       if(polymat->GetFlag() & RAS_BLENDERMAT)
+       {
+               KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
+               Py_INCREF(mat);
+               return mat;
+       }
+       else
+       {
+               KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
+               Py_INCREF(mat);
+               return mat;
+       }
+}
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h
new file mode 100644 (file)
index 0000000..506e2c2
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __KX_POLYROXY
+#define __KX_POLYPROXY
+
+#include "SCA_IObject.h"
+
+class KX_PolyProxy     : public SCA_IObject
+{
+       Py_Header;
+protected:
+       class RAS_Polygon*              m_polygon;
+       class RAS_MeshObject*   m_mesh;
+public:
+       KX_PolyProxy(const class RAS_MeshObject*mesh, class RAS_Polygon* polygon);
+       virtual ~KX_PolyProxy();
+
+       // stuff for cvalue related things
+       CValue*         Calc(VALUE_OPERATOR op, CValue *val) ;
+       CValue*         CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+       const STR_String &      GetText();
+       float           GetNumber();
+       STR_String      GetName();
+       void            SetName(STR_String name);                                                               // Set the name of the value
+       void            ReplicaSetName(STR_String name);
+       CValue*         GetReplica();
+
+
+// stuff for python integration
+       virtual PyObject* _getattr(const STR_String& attr);
+
+       KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex)
+       KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex)
+       KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,isVisible)
+       KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,isCollider)
+       KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialName)
+       KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getTextureName)
+       KX_PYMETHOD_DOC(KX_PolyProxy,getVertexIndex)
+       KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMesh)
+       KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterial)
+
+};
+
+#endif //__KX_POLYPROXY
+
index 6179d614e8cc8092e9a492c073d7026052a704ae..e9fb0278d7603bfb5bb2d4222ec21d64bc7d1a30 100644 (file)
 
 #include "GL/glew.h"
 
+// directory header for py function getBlendFileList
 #include <stdlib.h>
-#include <dirent.h> // directory header for py function getBlendFileList
+#ifndef WIN32
+  #include <dirent.h>
+#else
+  #include "BLI_winstuff.h"
+#endif
 
 #ifdef WIN32
 #pragma warning (disable : 4786)
@@ -847,13 +852,30 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
 // override builtin functions import() and open()
 
 
-PyObject *KXpy_open(PyObject *self, PyObject *args)
-{
+PyObject *KXpy_open(PyObject *self, PyObject *args) {
        PyErr_SetString(PyExc_RuntimeError, "Sandbox: open() function disabled!\nGame Scripts should not use this function.");
        return NULL;
 }
 
+PyObject *KXpy_reload(PyObject *self, PyObject *args) {
+       PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function.");
+       return NULL;
+}
+
+PyObject *KXpy_file(PyObject *self, PyObject *args) {
+       PyErr_SetString(PyExc_RuntimeError, "Sandbox: file() function disabled!\nGame Scripts should not use this function.");
+       return NULL;
+}
 
+PyObject *KXpy_execfile(PyObject *self, PyObject *args) {
+       PyErr_SetString(PyExc_RuntimeError, "Sandbox: execfile() function disabled!\nGame Scripts should not use this function.");
+       return NULL;
+}
+
+PyObject *KXpy_compile(PyObject *self, PyObject *args) {
+       PyErr_SetString(PyExc_RuntimeError, "Sandbox: compile() function disabled!\nGame Scripts should not use this function.");
+       return NULL;
+}
 
 PyObject *KXpy_import(PyObject *self, PyObject *args)
 {
@@ -890,19 +912,13 @@ PyObject *KXpy_import(PyObject *self, PyObject *args)
 }
 
 
+static PyMethodDef meth_open[] = {{ "open", KXpy_open, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_reload[] = {{ "reload", KXpy_reload, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_file[] = {{ "file", KXpy_file, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_execfile[] = {{ "execfile", KXpy_execfile, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_compile[] = {{ "compile", KXpy_compile, METH_VARARGS, "(disabled)"}};
 
-static PyMethodDef meth_open[] = {
-       { "open", KXpy_open, METH_VARARGS,
-               "(disabled)"}
-};
-
-
-static PyMethodDef meth_import[] = {
-       { "import", KXpy_import, METH_VARARGS,
-               "our own import"}
-};
-
-
+static PyMethodDef meth_import[] = {{ "import", KXpy_import, METH_VARARGS, "our own import"}};
 
 //static PyObject *g_oldopen = 0;
 //static PyObject *g_oldimport = 0;
@@ -913,15 +929,21 @@ void setSandbox(TPythonSecurityLevel level)
 {
     PyObject *m = PyImport_AddModule("__builtin__");
     PyObject *d = PyModule_GetDict(m);
-       PyObject *meth = PyCFunction_New(meth_open, NULL);
 
        switch (level) {
        case psl_Highest:
                //if (!g_security) {
                        //g_oldopen = PyDict_GetItemString(d, "open");
-                       PyDict_SetItemString(d, "open", meth);
-                       meth = PyCFunction_New(meth_import, NULL);
-                       PyDict_SetItemString(d, "__import__", meth);
+       
+                       // functions we cant trust
+                       PyDict_SetItemString(d, "open", PyCFunction_New(meth_open, NULL));
+                       PyDict_SetItemString(d, "reload", PyCFunction_New(meth_reload, NULL));
+                       PyDict_SetItemString(d, "file", PyCFunction_New(meth_file, NULL));
+                       PyDict_SetItemString(d, "execfile", PyCFunction_New(meth_execfile, NULL));
+                       PyDict_SetItemString(d, "compile", PyCFunction_New(meth_compile, NULL));
+                       
+                       // our own import
+                       PyDict_SetItemString(d, "__import__", PyCFunction_New(meth_import, NULL));
                        //g_security = level;
                //}
                break;
@@ -1026,9 +1048,38 @@ static char GameKeys_module_documentation[] =
 "This modules provides defines for key-codes"
 ;
 
+static char gPyEventToString_doc[] =
+"Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
+;
 
+static PyObject* gPyEventToString(PyObject*, PyObject* value)
+{
+       PyObject* mod, *dict, *key, *val, *ret = NULL;
+       Py_ssize_t pos = 0;
+       
+       mod = PyImport_ImportModule( "GameKeys" );
+       if (!mod)
+               return NULL;
+       
+       dict = PyModule_GetDict(mod);
+       
+       while (PyDict_Next(dict, &pos, &key, &val)) {
+               if (PyObject_Compare(value, val)==0) {
+                       ret = key;
+                       break;
+               }
+       }
+       
+       PyErr_Clear(); // incase there was an error clearing
+       Py_DECREF(mod);
+       if (!ret)       PyErr_SetString(PyExc_ValueError, "expected a valid int keyboard event");
+       else            Py_INCREF(ret);
+       
+       return ret;
+}
 
 static struct PyMethodDef gamekeys_methods[] = {
+       {"EventToString", (PyCFunction)gPyEventToString, METH_O, gPyEventToString_doc},
        { NULL, (PyCFunction) NULL, 0, NULL }
 };
 
index 89e2d645d545b59e97b5ce6d6b01b1f76c46de13..974d4b992a647443b8f3f2d5235f87d378db53bb 100644 (file)
 #include "PHY_IPhysicsEnvironment.h"
 #include "PHY_IPhysicsController.h"
 
-bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, MT_Point3& result_point, MT_Vector3& result_normal, const KX_RayCast& callback)
+KX_RayCast::KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal)
+       :PHY_IRayCastFilterCallback(dynamic_cast<PHY_IPhysicsController*>(ignoreController), faceNormal) 
+{
+}
+
+void KX_RayCast::reportHit(PHY_RayCastResult* result)
+{
+       m_hitFound = true;
+       m_hitPoint.setValue((const float*)result->m_hitPoint);
+       m_hitNormal.setValue((const float*)result->m_hitNormal);
+       m_hitMesh = result->m_meshObject;
+       m_hitPolygon = result->m_polygon;
+}
+
+bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback)
 {
        // Loops over all physics objects between frompoint and topoint,
        // calling callback.RayHit for each one.
@@ -50,58 +64,51 @@ bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsE
        // returns true if an object was found, false if not.
        MT_Point3 frompoint(_frompoint);
        const MT_Vector3 todir( (topoint - frompoint).safe_normalized() );
+       MT_Point3 prevpoint(_frompoint+todir*(-1.f));
        
        PHY_IPhysicsController* hit_controller;
-       PHY__Vector3 phy_pos;
-       PHY__Vector3 phy_normal;
 
-       while((hit_controller = physics_environment->rayTest(dynamic_cast<PHY_IPhysicsController*>(ignore_controller),
+       while((hit_controller = physics_environment->rayTest(callback,
                        frompoint.x(),frompoint.y(),frompoint.z(),
-                       topoint.x(),topoint.y(),topoint.z(),
-                       phy_pos[0],phy_pos[1],phy_pos[2],
-                       phy_normal[0],phy_normal[1],phy_normal[2]))) 
+                       topoint.x(),topoint.y(),topoint.z())) != NULL) 
        {
-               result_point = MT_Point3(phy_pos);
-               result_normal = MT_Vector3(phy_normal);
                KX_ClientObjectInfo* info = static_cast<KX_ClientObjectInfo*>(hit_controller->getNewClientInfo());
                
                if (!info)
                {
                        printf("no info!\n");
                        MT_assert(info && "Physics controller with no client object info");
-                       return false;
+                       break;
                }
                
-               if (callback.RayHit(info, result_point, result_normal))
-                       return true;
-       
-               // There is a bug in the code below: the delta is computed with the wrong
-               // sign on the face opposite to the center, resulting in infinite looping.
-               // In Blender 2.45 this code was never executed because callback.RayHit() always 
-               // returned true, causing the ray sensor to stop on the first object.
-               // To avoid changing the behaviour will simply return false here.
-               // It should be discussed if we want the ray sensor to "see" through objects
-               // that don't have the required property/material (condition to get here)
-               return false;
-       
-               // skip past the object and keep tracing
-               /* We add 0.01 of fudge, so that if the margin && radius == 0., we don't endless loop. */
-               MT_Scalar marg = 0.01 + hit_controller->GetMargin();
-               marg += 2.f * hit_controller->GetMargin();
+               // The biggest danger to to endless loop, prevent this by checking that the
+               // hit point always progresses along the ray direction..
+               prevpoint -= callback.m_hitPoint;
+               if (prevpoint.length2() < MT_EPSILON)
+                       break;
+
+               if (callback.RayHit(info))
+                       // caller may decide to stop the loop and still cancel the hit
+                       return callback.m_hitFound;
+
+               // Skip past the object and keep tracing.
+               // Note that retrieving in a single shot multiple hit points would be possible 
+               // but it would require some change in Bullet.
+               prevpoint = callback.m_hitPoint;
+               /* We add 0.001 of fudge, so that if the margin && radius == 0., we don't endless loop. */
+               MT_Scalar marg = 0.001 + hit_controller->GetMargin();
+               marg *= 2.f;
                /* Calculate the other side of this object */
-               PHY__Vector3 hitpos;
-               hit_controller->getPosition(hitpos);
-               MT_Point3 hitObjPos(hitpos);
-