From c7dbc6548811f37bfeda4013ab70e342d50707b7 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 30 Jun 2008 22:57:52 +0000 Subject: [PATCH] svn merge -r 15292:15392 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- extern/libredcode/debayer.c | 24 +- intern/iksolver/intern/IK_QTask.h | 2 +- intern/moto/include/MT_random.h | 6 +- intern/moto/intern/MT_random.cpp | 10 +- .../gameengine/gamelogic/SCA_GameLogic.vcproj | 24 + .../gameengine/ketsji/KX_ketsji.vcproj | 12 + release/scripts/DirectX8Exporter.py | 34 +- release/scripts/animation_bake_constraints.py | 800 +++++++++++ release/scripts/bpymodules/BPyArmature.py | 75 +- release/scripts/c3d_import.py | 1237 +++++++++++++++++ source/blender/blenkernel/BKE_ipo.h | 8 + source/blender/blenkernel/intern/action.c | 2 +- source/blender/blenkernel/intern/image.c | 4 +- source/blender/blenkernel/intern/ipo.c | 2 +- source/blender/blenkernel/intern/modifier.c | 74 +- .../blenkernel/intern/particle_system.c | 1 + source/blender/blenkernel/intern/sca.c | 3 + source/blender/blenkernel/intern/text.c | 3 +- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 68 + source/blender/blenloader/intern/readfile.c | 12 + source/blender/blenloader/intern/writefile.c | 3 + source/blender/imbuf/IMB_imbuf_types.h | 1 + source/blender/imbuf/intern/IMB_anim.h | 3 +- source/blender/imbuf/intern/anim.c | 88 +- source/blender/include/BIF_butspace.h | 2 + source/blender/include/BIF_interface.h | 1 + source/blender/include/BIF_oops.h | 2 + source/blender/include/butspace.h | 4 + source/blender/include/transform.h | 6 +- source/blender/makesdna/DNA_actuator_types.h | 30 +- .../blender/makesdna/DNA_controller_types.h | 7 +- source/blender/makesdna/DNA_object_types.h | 6 +- source/blender/makesdna/DNA_sensor_types.h | 3 +- source/blender/makesdna/DNA_userdef_types.h | 2 +- .../blender/nodes/intern/CMP_nodes/CMP_math.c | 2 +- source/blender/python/api2_2x/CurNurb.c | 34 + source/blender/python/api2_2x/Lamp.c | 13 +- source/blender/python/api2_2x/Mathutils.c | 62 +- source/blender/python/api2_2x/doc/Curve.py | 2 + .../blender/render/intern/source/pipeline.c | 6 +- source/blender/src/buttons_editing.c | 2 +- source/blender/src/buttons_logic.c | 710 +++++++--- source/blender/src/buttons_scene.c | 2 +- source/blender/src/drawaction.c | 11 +- source/blender/src/drawview.c | 3 +- source/blender/src/editaction.c | 13 +- source/blender/src/editfont.c | 4 +- source/blender/src/editmesh_mods.c | 4 +- source/blender/src/editobject.c | 2 +- source/blender/src/editseq.c | 3 +- source/blender/src/editsima.c | 6 +- source/blender/src/interface.c | 4 + source/blender/src/oops.c | 1 - source/blender/src/poseobject.c | 4 +- source/blender/src/sequence.c | 14 +- source/blender/src/space.c | 24 +- source/blender/src/transform.c | 8 +- source/blender/src/transform_constraints.c | 19 +- source/blender/src/transform_generics.c | 9 +- source/blender/src/transform_snap.c | 571 ++++---- source/blender/src/view.c | 36 +- source/creator/creator.c | 4 +- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 34 +- .../BlenderRoutines/KX_BlenderRenderTools.cpp | 4 +- .../BlenderRoutines/KX_BlenderRenderTools.h | 2 +- .../Converter/BL_ActionActuator.cpp | 49 + .../gameengine/Converter/BL_ActionActuator.h | 7 +- .../Converter/BL_BlenderDataConversion.cpp | 10 + .../gameengine/Converter/BL_ShapeDeformer.cpp | 47 + .../gameengine/Converter/BL_ShapeDeformer.h | 9 + .../gameengine/Converter/BL_SkinDeformer.cpp | 5 +- source/gameengine/Converter/BL_SkinDeformer.h | 8 + .../Converter/KX_ConvertActuators.cpp | 33 +- .../Converter/KX_ConvertControllers.cpp | 29 + .../Converter/KX_ConvertSensors.cpp | 5 +- source/gameengine/Expressions/Value.cpp | 24 +- source/gameengine/Expressions/Value.h | 2 + .../GameLogic/SCA_2DFilterActuator.cpp | 4 +- .../GameLogic/SCA_2DFilterActuator.h | 2 + .../gameengine/GameLogic/SCA_AlwaysSensor.cpp | 7 +- .../gameengine/GameLogic/SCA_AlwaysSensor.h | 2 + source/gameengine/GameLogic/SCA_IActuator.cpp | 10 + source/gameengine/GameLogic/SCA_IActuator.h | 7 + .../gameengine/GameLogic/SCA_IController.cpp | 97 +- source/gameengine/GameLogic/SCA_IController.h | 4 + source/gameengine/GameLogic/SCA_IObject.cpp | 13 +- source/gameengine/GameLogic/SCA_IObject.h | 19 +- source/gameengine/GameLogic/SCA_ISensor.cpp | 57 +- source/gameengine/GameLogic/SCA_ISensor.h | 17 + .../GameLogic/SCA_JoystickSensor.cpp | 6 +- .../gameengine/GameLogic/SCA_JoystickSensor.h | 1 + .../GameLogic/SCA_KeyboardSensor.cpp | 33 +- .../gameengine/GameLogic/SCA_KeyboardSensor.h | 2 + .../gameengine/GameLogic/SCA_LogicManager.cpp | 20 +- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 15 +- source/gameengine/GameLogic/SCA_MouseSensor.h | 2 +- .../GameLogic/SCA_NANDController.cpp | 144 ++ .../gameengine/GameLogic/SCA_NANDController.h | 56 + .../GameLogic/SCA_NORController.cpp | 144 ++ .../gameengine/GameLogic/SCA_NORController.h | 56 + .../GameLogic/SCA_PropertySensor.cpp | 8 +- .../gameengine/GameLogic/SCA_PropertySensor.h | 1 + .../GameLogic/SCA_PythonController.cpp | 9 + .../GameLogic/SCA_PythonController.h | 1 + .../gameengine/GameLogic/SCA_RandomSensor.cpp | 16 +- .../gameengine/GameLogic/SCA_RandomSensor.h | 1 + .../GameLogic/SCA_XNORController.cpp | 148 ++ .../gameengine/GameLogic/SCA_XNORController.h | 56 + .../GameLogic/SCA_XORController.cpp | 148 ++ .../gameengine/GameLogic/SCA_XORController.h | 56 + .../GamePlayer/common/GPC_RenderTools.cpp | 4 +- .../GamePlayer/common/GPC_RenderTools.h | 2 +- .../GamePlayer/ghost/GPG_Application.cpp | 12 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 3 +- .../KXNetwork/KX_NetworkMessageSensor.cpp | 7 +- .../KXNetwork/KX_NetworkMessageSensor.h | 1 + .../Ketsji/KX_BulletPhysicsController.cpp | 7 + .../Ketsji/KX_BulletPhysicsController.h | 1 + source/gameengine/Ketsji/KX_GameObject.cpp | 109 +- source/gameengine/Ketsji/KX_GameObject.h | 44 +- .../gameengine/Ketsji/KX_IPhysicsController.h | 1 + .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 13 +- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 1 + .../gameengine/Ketsji/KX_ObjectActuator.cpp | 131 +- source/gameengine/Ketsji/KX_ObjectActuator.h | 36 +- source/gameengine/Ketsji/KX_RadarSensor.cpp | 1 - source/gameengine/Ketsji/KX_RaySensor.cpp | 14 +- source/gameengine/Ketsji/KX_RaySensor.h | 1 + .../Ketsji/KX_SCA_DynamicActuator.cpp | 206 +++ .../Ketsji/KX_SCA_DynamicActuator.h | 76 + source/gameengine/Ketsji/KX_Scene.cpp | 3 +- source/gameengine/Ketsji/KX_StateActuator.cpp | 207 +++ source/gameengine/Ketsji/KX_StateActuator.h | 83 ++ .../Ketsji/KX_SumoPhysicsController.h | 2 + source/gameengine/Ketsji/KX_TouchSensor.cpp | 14 +- source/gameengine/Ketsji/KX_TouchSensor.h | 1 + source/gameengine/PyDoc/KX_GameObject.py | 38 +- .../gameengine/PyDoc/SCA_PythonController.py | 8 + .../Rasterizer/RAS_2DFilterManager.cpp | 101 +- .../Rasterizer/RAS_2DFilterManager.h | 10 +- .../gameengine/Rasterizer/RAS_IRenderTools.h | 2 +- .../RAS_OpenGLRasterizer.cpp | 3 + .../RAS_VAOpenGLRasterizer.cpp | 5 +- 144 files changed, 5841 insertions(+), 869 deletions(-) create mode 100644 release/scripts/animation_bake_constraints.py create mode 100644 release/scripts/c3d_import.py create mode 100644 source/gameengine/GameLogic/SCA_NANDController.cpp create mode 100644 source/gameengine/GameLogic/SCA_NANDController.h create mode 100644 source/gameengine/GameLogic/SCA_NORController.cpp create mode 100644 source/gameengine/GameLogic/SCA_NORController.h create mode 100644 source/gameengine/GameLogic/SCA_XNORController.cpp create mode 100644 source/gameengine/GameLogic/SCA_XNORController.h create mode 100644 source/gameengine/GameLogic/SCA_XORController.cpp create mode 100644 source/gameengine/GameLogic/SCA_XORController.h create mode 100644 source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp create mode 100644 source/gameengine/Ketsji/KX_SCA_DynamicActuator.h create mode 100644 source/gameengine/Ketsji/KX_StateActuator.cpp create mode 100644 source/gameengine/Ketsji/KX_StateActuator.h diff --git a/extern/libredcode/debayer.c b/extern/libredcode/debayer.c index f7f22e1cc54..de7bec510cb 100644 --- a/extern/libredcode/debayer.c +++ b/extern/libredcode/debayer.c @@ -9,8 +9,6 @@ void redcode_ycbcr2rgb_fullscale( int x,y; int pix_max = 4096; int mask = pix_max - 1; - float Kb = 0.0722; - float Kr = 0.2126; float *o; for (y = 0; y < height; y++) { @@ -25,9 +23,9 @@ void redcode_ycbcr2rgb_fullscale( float y2 = (planes[3][i] & mask); float y2p = (planes[3][i_p] & mask); - float b_ = cb * (1.0 - Kb)/(pix_max/2); - float r_ = cr * (1.0 - Kr)/(pix_max/2); - float g_ = (- Kr * r_ - Kb * b_)/(1.0 - Kr - Kb); + float b_ = cb /(pix_max/2); + float r_ = cr /(pix_max/2); + float g_ = 0.0; float y_[4] = {y1 / pix_max, (y2 + y2p)/2 / pix_max, @@ -68,8 +66,6 @@ void redcode_ycbcr2rgb_halfscale( int x,y; int pix_max = 4096; int mask = pix_max - 1; - float Kb = 0.0722; - float Kr = 0.2126; for (y = 0; y < height; y++) { float *o = out + width * (height - y - 1); @@ -80,9 +76,9 @@ void redcode_ycbcr2rgb_halfscale( float cr = (planes[2][i] & mask) - pix_max/2; float y2 = (planes[3][i] & mask); - float b_ = cb * (1.0 - Kb)/(pix_max/2); - float r_ = cr * (1.0 - Kr)/(pix_max/2); - float g_ = (- Kr * r_ - Kb * b_)/(1.0 - Kr - Kb); + float b_ = cb /(pix_max/2); + float r_ = cr /(pix_max/2); + float g_ = 0.0; float y = (y1 + y2)/2 / pix_max; @@ -101,8 +97,6 @@ void redcode_ycbcr2rgb_quarterscale( int x,y; int pix_max = 4096; int mask = pix_max - 1; - float Kb = 0.0722; - float Kr = 0.2126; for (y = 0; y < height; y += 2) { float *o = out + (width/2) * (height/2 - y/2 - 1); @@ -113,9 +107,9 @@ void redcode_ycbcr2rgb_quarterscale( float cr = (planes[2][i] & mask) - pix_max/2; float y2 = planes[3][i] & mask; - float b_ = cb * (1.0 - Kb)/(pix_max/2); - float r_ = cr * (1.0 - Kr)/(pix_max/2); - float g_ = (- Kr * r_ - Kb * b_)/(1.0 - Kr - Kb); + float b_ = cb /(pix_max/2); + float r_ = cr /(pix_max/2); + float g_ = 0.0; float y = (y1 + y2)/2 / pix_max; diff --git a/intern/iksolver/intern/IK_QTask.h b/intern/iksolver/intern/IK_QTask.h index c291a0e7e50..4d469d737f8 100644 --- a/intern/iksolver/intern/IK_QTask.h +++ b/intern/iksolver/intern/IK_QTask.h @@ -74,7 +74,7 @@ public: virtual bool PositionTask() const { return false; } - virtual void Scale(float scale) {} + virtual void Scale(float) {} protected: int m_id; diff --git a/intern/moto/include/MT_random.h b/intern/moto/include/MT_random.h index d7da546cf03..3afe1dd1662 100644 --- a/intern/moto/include/MT_random.h +++ b/intern/moto/include/MT_random.h @@ -31,10 +31,10 @@ #include -#define MT_RAND_MAX ULONG_MAX +#define MT_RAND_MAX UINT_MAX -extern void MT_srand(unsigned long); -extern unsigned long MT_rand(); +extern void MT_srand(unsigned int); +extern unsigned int MT_rand(); #endif diff --git a/intern/moto/intern/MT_random.cpp b/intern/moto/intern/MT_random.cpp index 96cb394d3da..b8302e093ca 100644 --- a/intern/moto/intern/MT_random.cpp +++ b/intern/moto/intern/MT_random.cpp @@ -76,11 +76,11 @@ #define TEMPERING_SHIFT_T(y) (y << 15) #define TEMPERING_SHIFT_L(y) (y >> 18) -static unsigned long mt[N]; /* the array for the state vector */ +static unsigned int mt[N]; /* the array for the state vector */ static int mti = N+1; /* mti==N+1 means mt[N] is not initialized */ /* initializing the array with a NONZERO seed */ -void MT_srand(unsigned long seed) +void MT_srand(unsigned int seed) { /* setting initial seeds to mt[N] using */ /* the generator Line 25 of Table 1 in */ @@ -91,12 +91,12 @@ void MT_srand(unsigned long seed) mt[mti] = (69069 * mt[mti-1]) & 0xffffffff; } -unsigned long MT_rand() +unsigned int MT_rand() { - static unsigned long mag01[2] = { 0x0, MATRIX_A }; + static unsigned int mag01[2] = { 0x0, MATRIX_A }; /* mag01[x] = x * MATRIX_A for x=0,1 */ - unsigned long y; + unsigned int y; if (mti >= N) { /* generate N words at one time */ int kk; diff --git a/projectfiles_vc7/gameengine/gamelogic/SCA_GameLogic.vcproj b/projectfiles_vc7/gameengine/gamelogic/SCA_GameLogic.vcproj index 07fcfa64a72..e0405b4d7c7 100644 --- a/projectfiles_vc7/gameengine/gamelogic/SCA_GameLogic.vcproj +++ b/projectfiles_vc7/gameengine/gamelogic/SCA_GameLogic.vcproj @@ -395,6 +395,12 @@ + + + + @@ -425,6 +431,12 @@ + + + + + + + + @@ -528,6 +546,12 @@ + + + + diff --git a/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj b/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj index c8173750bdc..9d5a9f55074 100644 --- a/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj +++ b/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj @@ -462,6 +462,9 @@ + + @@ -474,6 +477,9 @@ + + @@ -683,6 +689,9 @@ + + @@ -695,6 +704,9 @@ + + diff --git a/release/scripts/DirectX8Exporter.py b/release/scripts/DirectX8Exporter.py index 2ec42057039..01212545f77 100644 --- a/release/scripts/DirectX8Exporter.py +++ b/release/scripts/DirectX8Exporter.py @@ -6,9 +6,9 @@ # Group: 'Export' # Tooltip: 'Export to DirectX text file format format for XNA Animation Component Library.' """ -__author__ = "minahito (original:Arben (Ben) Omari)" -__url__ = ("blender", "blenderartists.org", "Adjuster's site http://sunday-lab.blogspot.com/, Author's site http://www.omariben.too.it") -__version__ = "3.0" +__author__ = "vertex color exporting feature is added by mnemoto (original:minahito (original:Arben (Ben) Omari))" +__url__ = ("blender", "elysiun", "Adjuster's site http://sunday-lab.blogspot.com/, Author's site http://www.omariben.too.it","Adjuster's site http://ex.homeunix.net/") +__version__ = "3.1" __bpydoc__ = """\ This script exports a Blender mesh with armature to DirectX 8's text file @@ -444,6 +444,7 @@ class xExport: self.writeMeshMaterialList(obj, mesh, tex) self.writeMeshNormals(obj, mesh) self.writeMeshTextureCoords(obj, mesh) + self.writeMeshVertexColors(obj, mesh) self.file.write(" } // End of the Mesh %s \n" % (obj.name)) @@ -464,6 +465,7 @@ class xExport: self.writeMeshMaterialList(obj, mesh, tex) self.writeMeshNormals(obj, mesh) self.writeMeshTextureCoords(obj, mesh) + self.writeMeshVertexColors(obj, mesh) self.file.write(" }\n") self.file.write("}\n") ind = objs.index(obj) @@ -1047,6 +1049,32 @@ template SkinWeights {\n\ self.file.write(",\n") self.file.write("} //End of MeshTextureCoords\n") + + #*********************************************** + #MESH VORTEX COLORS + #*********************************************** + def writeMeshVertexColors(self, name, mesh): + if mesh.hasVertexColours(): + self.file.write("MeshVertexColors {\n") + #VERTICES NUMBER + numvert = reduce( lambda i,f: len(f)+i, mesh.faces, 0) + self.file.write("%d;\n" % (numvert)) + #VERTEX COLORS + + vcounter =0 + for f in mesh.faces: + col = f.col + for i,c in enumerate(col): + # Note vcol alpha has no meaning + self.file.write("%d;%f;%f;%f;%f;" % (vcounter,c.r/255.0, c.g/255.0, c.b/255.0, 1.0)) # c.a/255.0)) + vcounter+=1 + if vcounter == numvert : + self.file.write(";\n") + else : + self.file.write(",\n") + + self.file.write("} //End of MeshVertexColors\n") + #***********************************************#***********************************************#*********************************************** #*********************************************** #FRAMES diff --git a/release/scripts/animation_bake_constraints.py b/release/scripts/animation_bake_constraints.py new file mode 100644 index 00000000000..130e93d8591 --- /dev/null +++ b/release/scripts/animation_bake_constraints.py @@ -0,0 +1,800 @@ +#!BPY + +""" +Name: 'Bake Constraints' +Blender: 246 +Group: 'Animation' +Tooltip: 'Bake a Constrained object/rig to IPOs' +Fillename: 'Bake_Constraint.py' +""" + +__author__ = "Roger Wickes (rogerwickes(at)yahoo.com)" +__script__ = "Bake Constraints" +__version__ = "0.6" +__url__ = ["Communicate problems and errors, http://www.blenderartists.com/forum/private.php?do=newpm to PapaSmurf"] +__email__= ["Roger Wickes, rogerwickes@yahoo.com", "scripts"] +__bpydoc__ = """\ + +bake_constraints + +This script bakes the real-world LocRot of an object (the net effect of any constraints - +(Copy, Limit, Track, Follow, - that affect Location, Rotation) +(usually one constrained to match another's location and/or Tracked to another) +and creates a clone with a set of Ipo Curves named Ipo +These curves control a non-constrained object and thus make it mimic the constrained object +Actions can be then be edited without the need for the drivers/constraining objects + +Developed for use with MoCap data, where a bone is constrained to point at an empty +moving through space and time. This records the actual locrot of the armature +so that the motion can be edited, reoriented, scaled, and used as NLA Actions + +see also wiki Scripts/Manual/ Sandbox/Animation/Bake_Constraints (tbd) + +Usage:
+ - Select the reference Object(s) you want to bake
+ - Set the frame range to bake in the Anim Panel
+ - Set the test code (if you want a self-test) in the RT field in the Anim Panel
+ -- Set RT:1 in the Anim panel to create a test armature
+
+ - Run the script
+ - The clone copy of the object is created and it has an IPO curve assigned to it. + - The clone shadows the object by an offset locrot (see usrDelta) + - That Ipo has Location and Rotation curves that make the shadow mimic the movement of the selected object, + but without using constraints. Bones move identically in relation to the armature as the reference object + + +Version History: + 0.1: bakes Loc Rot for a constrained object + 0.2: bakes Loc and Rot for the bones within Armature object + 0.3: UI for setting options + 0.3.1 add manual to script library + 0.4: bake multiple objects + 0.5: root bone worldspace rotation + 0.6: re-integration with BPyArmature + +License, Copyright, and Attribution: + by Roger WICKES May 2008, released under Blender Artistic Licence to Public Domain + feel free to add to any Blender Python Scripts Bundle. + Thanks to Jean-Baptiste PERIN, IdeasMan42 (Campbell Barton?), Basil_Fawlty/Cage_drei (Andrew Cruse) + much lifted/learned from blender.org/documentation/245PytonDoc and wiki + some modules based on c3D_Import.py, PoseLib16.py and IPO/Armature code examples e.g. camera jitter + +Pseudocode (planned versions): + Initialize + If at least one object is selected + For each selected object, + create a shadow object + remove any constraints on the clone + create or reset an ipo curve named like the object + for each frame + set the clone's locrot key based on the reference object + if it's an armature, + create an action (which is an Ipo for each bone) + for each frame of the animation + for each bone in the armature + set the key + Else you're a smurf + +Test Conditions and Regressions: + 1. (v0.1) Non-armatures (the cube), with ipo curve and constraints at the object level + 2. armatures, with ipo curve and constraints at the object level + 3. armatures, with bones that have ipo curves and constraints + +Naming conventions: + arm = a specific objec type armature + bone = bones that make up the skeleton of an armature + + ob = object, an instance of an object type + ebone = edit bone, a bone in edit mode + pbone = pose bone, a posed bone in an object + tst = testing, self-test routines + usr = user-entered or designated stuff + +Pattern Notes (let me know if I've violated any): + Bergin Starting,Designing, Programming, Coding + Bergin 23 Indent for Structure - I don't like only 2, but the editor is set up that way + Bergin 26 Be Spacey Not Tabby - personal frustraion here. workaround is to Format->convert to whitespace + Bergin 27 Consistent Capitalization - except Blender, because I love it. + Bergin 28 Name Your Constants - not for those I plan on making variable + Python 01 Return Everything - I made this one up, all functions and methods end in return + even though it is decoration in Python, it helps Python throw an indentation error for typing mistakes + Wickes 01 Decorate Your Code - for visual appeal and to ease maintenance, include separators like ######### + to visually distinquish and separate functions, making it quicker to scan through code for methods + Wickes 02 Whitespace helps readability - include blanks around = # and lines (after def, after return) to make it stand out and pretty + +""" +######################################## + +import Blender +from Blender import * +from Blender.Mathutils import * +import struct +import string +import bpy +import BPyMessages +import BPyArmature +# reload(BPyArmature) +from BPyArmature import getBakedPoseData + +Vector= Blender.Mathutils.Vector +Euler= Blender.Mathutils.Euler +Matrix= Blender.Mathutils.Matrix #invert() function at least +RotationMatrix = Blender.Mathutils.RotationMatrix +TranslationMatrix= Blender.Mathutils.TranslationMatrix +Quaternion = Blender.Mathutils.Quaternion +Vector = Blender.Mathutils.Vector +POSE_XFORM= [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT] + +#================= +# Global Variables +#================= + +# set senstitivity for displaying debug/console messages. 0=none, 100=max +# then call debug(num,string) to conditionally display status/info in console window +MODE=Blender.Get('rt') #execution mode: 0=run normal, x=self-test (test error trapping etc) +DEBUG=100 #how much detail on internal processing for big brother to see +BATCH=False #called from command line? is someone there? Would you like some cake? + +#there are two coordinate systems, the real, or absolute 3D space, +# and the local relative to a parent. +COORDINATE_SYSTEMS = ['local','real'] +COORD_LOCAL = 0 +COORD_REAL = 1 + +# User Settings - Change these options manually or via GUI (future TODO) +usrCoord = COORD_REAL # what the user wants +usrParent = False # True=keep parent (if exists), False = breakaway (usually with Real) +usrFreeze = 2 #2=yes, 0=no. Freezes shadow object in place at current frame as origin + #TODO - i wonder if usrFreeze means we should set Delta to the the difference between the original object and parent? +# delta is amount to offset/change from the reference object. future set in a ui, so technically not a constant +usrDelta = [10,10,0,0,0,0] #order specific - Loc xyz Rot xyz +usrACTION = True # Offset baked Action frames to start at frame 1 +usrBAKEobjIPO = False # bake the object Ipo? it is useless for MoCap, as we only want the Action, and the Object does not move + +CURFRAME = 'curframe' #keyword to use when getting the frame number that the scene is presently on +ARMATURE = 'Armature' #en anglais +BONE_SPACES = ['ARMATURESPACE','BONESPACE'] + # 'ARMATURESPACE' - this matrix of the bone in relation to the armature + # 'BONESPACE' - the matrix of the bone in relation to itself + +#Ipo curves created are prefixed with a name, like Ipo_ or Bake_ followed by the object/bone name +#bakedArmName = "b." #used for both the armature class and object instance +#ipoObjectNamePrefix= "" +#ipoBoneNamePrefix = "" +# for example, if on entry an armature named Man was selected, and the object prefix was "a." +# on exit an armature and an IPO curve named a.Man exists for the object as a whole +# if that armature had bones (spine, neck, arm) and the bone prefix was "a." +# the bones and IPO curves will be (a.spine, a.neck, a.arm) + +R2D = 18/3.1415 # radian to grad +BLENDER_VERSION = Blender.Get('version') + +# Gets the current scene, there can be many scenes in 1 blend file. +scn = Blender.Scene.GetCurrent() + +#================= +# Methods +#================= +######################################## +def debug(num,msg): #use log4j or just console here. + + if DEBUG >= num: + if BATCH == False: + print 'debug: '[:num/10+7]+msg + #TODO: else write out to file (runs faster if it doesnt have to display details) + return + +######################################## +def error(str): + debug(0,'ERROR: '+str) + if BATCH == False: + Draw.PupMenu('ERROR%t|'+str) + return + +######################################## +def getRenderInfo(): + context=scn.getRenderingContext() + staframe = context.startFrame() + endframe = context.endFrame() + if endframe 245: debug(0,'WARNING: Programmer check for Bone updates in dupliArmature') + + eboneNames = sortBones(xbones) + + i=0 + # error('bones sorted. continue?') + for abone in eboneNames: #set all editable attributes to fully define the bone. + for bone in xbones: + if bone.name == abone: break # get the reference bone + ebone = Armature.Editbone() #throw me a bone, bone-man! + ebones.append(ebone) #you're on my list, buddy + + ebone.name = bone.name + ebone.headRadius = bone.headRadius + ebone.tailRadius = bone.tailRadius + ebone.weight = bone.weight + ebone.options = bone.options + + ebone.head = bone.head[space] #dictionary lookups + ebone.tail = bone.tail[space] + ebone.matrix = bone.matrix[space] + ebone.roll = bone.roll[space] + + debug(30,'Generating new %s as child of %s' % (bone,bone.parent)) + if bone.hasParent(): +# parent=bone.parent.name +# debug(100,'looking for %s' % parent) +# for parbone in xbones: if parbone.name == parent: break # get the parent bone +# ebone.parent = arm.bones[ebones[j].name] + ebone.parent = arm.bones[bone.parent.name] +# else: +# ebone.parent = None + debug(30,'Generating new editbone %s as child of %s' % (ebone,ebone.parent)) + arm.bones[ebone.name] = ebone # i would have expected an append or add function, but this works + + debug (100,'arm.bones: \n%s' % arm.bones) + debug (20,'Cloned %i bones now in armature %s' %(len(arm.bones),arm.name)) + + myob = scn.objects.new(arm) #interestingly, object must be created before + arm.update() #armature can be saved + debug(40,'dupArm finished %s instanced as object %s' % (arm.name,myob.getName())) + print ob.matrix + print myob.matrix + + return myob + +def scrub(): # scrubs to startframe + staFrame,endFrame,curFrame = getRenderInfo() + + # eye-candy, go from current to start, fwd or back + if not BATCH: + print "Positioning to start..." + frameinc=(staFrame-curFrame)/10 + if abs(frameinc) >= 1: + for i in range(10): + curFrame+=frameinc + Blender.Set(CURFRAME,curFrame) # computes the constrained location of the 'real' objects + Blender.Redraw() + Blender.Set(CURFRAME, staFrame) + +######################################## +def bakeBones(ref_ob,arm_ob): #copy pose from ref_ob to arm_ob + scrub() + staFrame,endFrame,curFrame = getRenderInfo() + act = getBakedPoseData(ref_ob, staFrame, endFrame, ACTION_BAKE = True, ACTION_BAKE_FIRST_FRAME = usrACTION) # bake the pose positions of the reference ob to the armature ob + arm_ob.action = act + scrub() + + # user comprehension feature - change action name and channel ipo names to match the names of the bone they drive + debug (80,'Renaming each action ipo to match the bone they pose') + act.name = arm_ob.name + arm_channels = act.getAllChannelIpos() + pose= arm_ob.getPose() + pbones= pose.bones.values() #we want the bones themselves, not the dictionary lookup + print arm_channels.keys() + for pbone in pbones: + debug (100,'Channel listing for %s: %s' % (pbone.name,arm_channels[pbone.name] )) + ipo=arm_channels[pbone.name] + ipo.name = pbone.name # since bone names are unique within an armature, the pose names can be the same since they are within an Action + + return + +######################################## +def getOrCreateCurve(ipo, curvename): + + """ + Retrieve or create a Blender Ipo Curve named C{curvename} in the C{ipo} Ipo + Either an ipo curve named C{curvename} exists before the call then this curve is returned, + Or such a curve doesn't exist before the call .. then it is created into the c{ipo} Ipo and returned + """ + try: + mycurve = ipo.getCurve(curvename) + if mycurve != None: + pass + else: + mycurve = ipo.addCurve(curvename) + except: + mycurve = ipo.addCurve(curvename) + return mycurve + +######################################## +def eraseCurve(ipo,numCurves): + debug(80,'Erasing %i curves for %' % (numCurves,ipo.GetName())) + for i in range(numCurves): + nbBezPoints = ipo.getNBezPoints(i) + for j in range(nbBezPoints): + ipo.delBezPoint(i) + return + +######################################## +def resetIPO(ipo): + ipoName=ipoObjectNamePrefix + obName + debug(40,'Resetting ipo curve named %s' %ipoName) + numCurves = ipo.getNcurves() #like LocX, LocY, etc + if numCurves > 0: + eraseCurve(ipo, numCurves) #erase data if one exists + return + +######################################## +def resetIPOs(ob): #resets all IPO curvess assocated with an object and its bones + debug(30,'Resetting any ipo curves linked to %s' %ob.getName()) + ipo = ob.getIpo() #may be None + ipoName = ipo.getName() #name of the IPO that guides/controls this object + debug(70,'Object IPO is %s' %ipoName) + try: + ipo = Ipo.Get(ipoName) + except: + ipo = Ipo.New('Object', ipoName) + resetIPO(ipo) + if ob.getType() == ARMATURE: + arm_data=ob.getData() + bones=arm_data.bones.values() + for bone in bones: + #for each bone: get the name and check for a Pose IPO + debug(10,'Processing '+ bone.name) + return + +######################################## +def parse(string,delim): + index = string.find(delim) # -1 if not found, else pointer to delim + if index+1: return string[:index] + return string + +######################################## +def newIpo(ipoName): #add a new Ipo object to the Blender scene + ipo=Blender.Ipo.New('Object',ipoName) + + ipo.addCurve('LocX') + ipo.addCurve('LocY') + ipo.addCurve('LocZ') + ipo.addCurve('RotX') + ipo.addCurve('RotY') + ipo.addCurve('RotZ') + return ipo + +######################################## +def makeUpaName(type,name): #i know this exists in Blender somewhere... + debug(90,'Making up a new %s name using %s as a basis.' % (type,name)) + name = (parse(name,'.')) + if type == 'Ipo': + ipoName = name # maybe we get lucky today + ext = 0 + extlen = 3 # 3 digit extensions, like hello.002 + success = False + while not(success): + try: + debug(100,'Trying %s' % ipoName) + ipo = Ipo.Get(ipoName) + #that one exists if we get here. add on extension and keep trying + ext +=1 + if ext>=10**extlen: extlen +=1 # go to more digits if 999 not found + ipoName = '%s.%s' % (name, str(ext).zfill(extlen)) + except: # could not find it + success = True + name=ipoName + else: + debug (0,'FATAL ERROR: I dont know how to make up a new %s name based on %s' % (type,ob)) + return + return name + +######################################## +def createIpo(ob): #create an Ipo and curves and link them to this object + #first, we have to create a unique name + #try first with just the name of the object to keep things simple. + ipoName = makeUpaName('Ipo',ob.getName()) # make up a name for a new Ipo based on the object name + + debug(20,'Ipo and LocRot curves called %s' % ipoName) + + ipo=newIpo(ipoName) + + ob.setIpo(ipo) #link them + return ipo + +######################################## +def getLocLocal(ob): + key = [ + ob.LocX, + ob.LocY, + ob.LocZ, + ob.RotX*R2D, #get the curves in this order + ob.RotY*R2D, + ob.RotZ*R2D + ] + return key + +######################################## +def getLocReal(ob): + obMatrix = ob.matrixWorld #Thank you IdeasMan42 + loc = obMatrix.translationPart() + rot = obMatrix.toEuler() + key = [ + loc.x, + loc.y, + loc.z, + rot.x/10, + rot.y/10, + rot.z/10 + ] + return key + +######################################## +def getLocRot(ob,space): + if space in xrange(len(COORDINATE_SYSTEMS)): + if space == COORD_LOCAL: + key = getLocLocal(ob) + return key + elif space == COORD_REAL: + key = getLocReal(ob) + return key + else: #hey, programmers make mistakes too. + debug(0,'Fatal Error: getLoc called with %i' % space) + return + +######################################## +def getCurves(ipo): + ipos = [ + ipo[Ipo.OB_LOCX], + ipo[Ipo.OB_LOCY], + ipo[Ipo.OB_LOCZ], + ipo[Ipo.OB_ROTX], #get the curves in this order + ipo[Ipo.OB_ROTY], + ipo[Ipo.OB_ROTZ] + ] + return ipos + +######################################## +def addPoint(time,keyLocRot,ipos): + if BLENDER_VERSION < 245: + debug(0,'WARNING: addPoint uses BezTriple') + for i in range(len(ipos)): + point = BezTriple.New() #this was new with Blender 2.45 API + point.pt = (time, keyLocRot[i]) + point.handleTypes = [1,1] + + ipos[i].append(point) + return ipos + +######################################## +def bakeFrames(ob,myipo): #bakes an object in a scene, returning the IPO containing the curves + myipoName = myipo.getName() + debug(20,'Baking frames for scene %s object %s to ipo %s' % (scn.getName(),ob.getName(),myipoName)) + ipos = getCurves(myipo) + #TODO: Gui setup idea: myOffset + # reset action to start at frame 1 or at location + myOffset=0 #=1-staframe + #loop through frames in the animation. Often, there is rollup and the mocap starts late + staframe,endframe,curframe = getRenderInfo() + for frame in range(staframe, endframe+1): + debug(80,'Baking Frame %i' % frame) + #tell Blender to advace to frame + Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects + if not BATCH: Blender.Redraw() # no secrets, let user see what we are doing + + #using the constrained Loc Rot of the object, set the location of the unconstrained clone. Yea! Clones are FreeMen + key = getLocRot(ob,usrCoord) #a key is a set of specifed exact channel values (LocRotScale) for a certain frame + key = [a+b for a,b in zip(key, usrDelta)] #offset to the new location + + myframe= frame+myOffset + Blender.Set(CURFRAME,myframe) + + time = Blender.Get('curtime') #for BezTriple + ipos = addPoint(time,key,ipos) #add this data at this time to the ipos + debug(100,'%s %i %.3f %.2f %.2f %.2f %.2f %.2f %.2f' % (myipoName, myframe, time, key[0], key[1], key[2], key[3], key[4], key[5])) + # eye-candy - smoothly rewind the animation, showing now how the clone match moves + if endframe-staframe <400 and not BATCH: + for frame in range (endframe,staframe,-1): #rewind + Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects + Blender.Redraw() + Blender.Set(CURFRAME,staframe) + Blender.Redraw() + + return ipos + +######################################## +def duplicateLinked(ob): + obType = ob.type + debug(10,'Duplicating %s Object named %s' % (obType,ob.getName())) + scn.objects.selected = [ob] +## rdw: simplified by just duplicating armature. kept code as reference for creating armatures +## disadvantage is that you cant have clone as stick and original as octahedron +## since they share the same Armature. User can click Make Single User button. +## if obType == ARMATURE: #build a copy from scratch +## myob= dupliArmature(ob) +## else: + Blender.Object.Duplicate() # Duplicate linked, including pose constraints. + myobs = Object.GetSelected() #duplicate is top on the list + myob = myobs[0] + if usrParent == False: + myob.clrParent(usrFreeze) + debug(20,'=myob= was created as %s' % myob.getName()) + return myob + +######################################## +def removeConstraints(ob): + for const in ob.constraints: + debug(90,'removed %s => %s' % (ob.name, const)) + ob.constraints.remove(const) + return + +######################################## +def removeConstraintsOb(ob): # from object or armature + debug(40,'Removing constraints from '+ob.getName()) + if BLENDER_VERSION > 241: #constraints module not available before 242 + removeConstraints(ob) + if ob.getType() == ARMATURE: + pose = ob.getPose() + for pbone in pose.bones.values(): + #bone = pose.bones[bonename] + removeConstraints(pbone) + #should also check if it is a deflector? + return + +######################################## +def deLinkOb(type,ob): #remove linkages + if type == 'Ipo': + success = ob.clearIpo() #true=there was one + if success: debug(80,'deLinked Ipo curve to %s' % ob.getName()) + return + +######################################## +def bakeObject(ob): #bakes the core object locrot and assigns the Ipo to a Clone + if ob != None: + # Clone the object - duplicate it, clean the clone, and create an ipo curve for the clone + myob = duplicateLinked(ob) #clone it + removeConstraintsOb(myob) #my object is a free man + deLinkOb('Ipo',myob) #kids, it's not nice to share. you've been lied to + if usrBAKEobjIPO: + myipo = createIpo(myob) #create own IPO and curves for the clone object + ipos = bakeFrames(ob,myipo) #bake the locrot for this obj for the scene frames + +# staframe,endframe,curframe = getRenderInfo() +# frame = staframe +# Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects +# frame +=1 +# Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects +# frame -=1 +# Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects +# if not BATCH: Blender.Redraw() +# + return myob + +######################################## +def bake(ob): #bakes an object of any type + + debug(30,'Baking %s object %s' % (ob.getType(), ob)) + + myob = bakeObject(ob) #creates and bakes the object motion + + if ob.getType() == ARMATURE: +# error('Object baked. Continue with bones?') + bakeBones(ob,myob) #go into the bones and copy from -> to in frame range + #future idea: bakeMesh (net result of Shapekeys, Softbody, Cloth, Fluidsim,...) + + return + +######################################## +def tstCreateArm(): #create a test armature in scene + # rip-off from http://www.blender.org/documentation/245PythonDoc/Pose-module.html - thank you! + + debug(0,'Making Test Armature') + # New Armature + arm_data= Armature.New('myArmature') + print arm_data + arm_ob = scn.objects.new(arm_data) + arm_data.makeEditable() + + # Add 4 bones + ebones = [Armature.Editbone(), Armature.Editbone(), Armature.Editbone(), Armature.Editbone()] + + # Name the editbones + ebones[0].name = 'Bone.001' + ebones[1].name = 'Bone.002' + ebones[2].name = 'Bone.003' + ebones[3].name = 'Bone.004' + + # Assign the editbones to the armature + for eb in ebones: + arm_data.bones[eb.name]= eb + + # Set the locations of the bones + ebones[0].head= Mathutils.Vector(0,0,0) + ebones[0].tail= Mathutils.Vector(0,0,1) #tip + ebones[1].head= Mathutils.Vector(0,0,1) + ebones[1].tail= Mathutils.Vector(0,0,2) + ebones[2].head= Mathutils.Vector(0,0,2) + ebones[2].tail= Mathutils.Vector(0,0,3) + ebones[3].head= Mathutils.Vector(0,0,3) + ebones[3].tail= Mathutils.Vector(0,0,4) + + ebones[1].parent= ebones[0] + ebones[2].parent= ebones[1] + ebones[3].parent= ebones[2] + + arm_data.update() + # Done with editing the armature + + # Assign the pose animation + arm_pose = arm_ob.getPose() + + act = arm_ob.getAction() + if not act: # Add a pose action if we dont have one + act = Armature.NLA.NewAction() + act.setActive(arm_ob) + + xbones=arm_ob.data.bones.values() + pbones = arm_pose.bones.values() + + frame = 1 + for pbone in pbones: # set bones to no rotation + pbone.quat[:] = 1.000,0.000,0.000,0.0000 + pbone.insertKey(arm_ob, frame, Object.Pose.ROT) + + # Set a different rotation at frame 25 + pbones[0].quat[:] = 1.000,0.1000,0.2000,0.20000 + pbones[1].quat[:] = 1.000,0.6000,0.5000,0.40000 + pbones[2].quat[:] = 1.000,0.1000,0.3000,0.40000 + pbones[3].quat[:] = 1.000,-0.2000,-0.3000,0.30000 + + frame = 25 + for i in xrange(4): + pbones[i].insertKey(arm_ob, frame, Object.Pose.ROT) + + pbones[0].quat[:] = 1.000,0.000,0.000,0.0000 + pbones[1].quat[:] = 1.000,0.000,0.000,0.0000 + pbones[2].quat[:] = 1.000,0.000,0.000,0.0000 + pbones[3].quat[:] = 1.000,0.000,0.000,0.0000 + + frame = 50 + for pbone in pbones: # set bones to no rotation + pbone.quat[:] = 1.000,0.000,0.000,0.0000 + pbone.insertKey(arm_ob, frame, Object.Pose.ROT) + + return arm_ob + +######################################## +def tstMoveOb(ob): # makes a simple LocRot animation of object in the scene + anim = [ + #Loc Rot/10 + # + ( 0,0,0, 0, 0, 0), #frame 1 origin + ( 1,0,0, 0, 0, 0), #frame 2 + ( 1,1,0, 0, 0, 0), + ( 1,1,1, 0, 0, 0), + ( 1,1,1,4.5, 0, 0), + ( 1,1,1,4.5,4.5, 0), + ( 1,1,1,4.5,4.5,4.5) + ] + space = COORD_LOCAL + ipo = createIpo(ob) #create an Ipo and curves for this object + ipos = getCurves(ipo) + + # span this motion over the currently set anim range + # to set points, i need time but do not know how it is computed, so will have to advance the animation + staframe,endframe,curframe = getRenderInfo() + + frame = staframe #x position of new ipo datapoint. set to staframe if you want a match + frameDelta=(endframe-staframe)/(len(anim)) #accomplish the animation in frame range + for key in anim: #effectively does a getLocRot() + #tell Blender to advace to frame + Blender.Set('curframe',frame) # computes the constrained location of the 'real' objects + time = Blender.Get('curtime') + + ipos = addPoint(time,key,ipos) #add this data at this time to the ipos + + debug(100,'%s %i %.3f %.2f %.2f %.2f %.2f %.2f %.2f' % (ipo.name, frame, time, key[0], key[1], key[2], key[3], key[4], key[5])) + frame += frameDelta + Blender.Set('curframe',curframe) # reset back to where we started + return +#================= +# Program Template +#================= +######################################## +def main(): + # return code set via rt button in Blender Buttons Scene Context Anim panel + + if MODE == 1: #create test armature #1 + ob = tstCreateArm() # make test arm and select it + tstMoveOb(ob) + scn.objects.selected = [ob] + + obs = Blender.Object.GetSelected() #scn.objects.selected + debug(20,'Baking %i objects' % len(obs)) + + if len(obs) >= 1: # user might have multiple objects selected + for ob in obs: + bake(ob) + else: + error('Please select at least one object') + return + +######################################## +def benchmark(): # This lets you benchmark (time) the script's running duration + + Window.WaitCursor(1) + t = sys.time() + debug(60,'%s began at %.0f' %(__script__,sys.time())) + + # Run the function on the active scene + in_editmode = Window.EditMode() + if in_editmode: Window.EditMode(0) + + main() + + if in_editmode: Window.EditMode(1) + + # Timing the script is a good way to be aware on any speed hits when scripting + debug(60,'%s Script finished in %.2f seconds' % (__script__,sys.time()-t) ) + Window.WaitCursor(0) + return + +######################################## +# This lets you can import the script without running it +if __name__ == '__main__': + debug(0, "------------------------------------") + debug(0, '%s %s Script begins with mode=%i debug=%i batch=%s version=%i' % (__script__,__version__,MODE,DEBUG,BATCH,BLENDER_VERSION)) + + benchmark() diff --git a/release/scripts/bpymodules/BPyArmature.py b/release/scripts/bpymodules/BPyArmature.py index d0b41dc35c5..63df02d080c 100644 --- a/release/scripts/bpymodules/BPyArmature.py +++ b/release/scripts/bpymodules/BPyArmature.py @@ -11,13 +11,19 @@ # 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 +# Version History: +# 1.0 original release bakes an armature into a matrix +# 1.1 optional params (ACTION_BAKE, ACTION_BAKE_FIRST_FRAME, direct function to key and return the Action import Blender +from Blender import sys import bpy -def getBakedPoseData(ob_arm, start_frame, end_frame): +def getBakedPoseData(ob_arm, start_frame, end_frame, ACTION_BAKE = False, ACTION_BAKE_FIRST_FRAME = True): ''' If you are currently getting IPO's this function can be used to - return a list of frame aligned bone dictionary's + ACTION_BAKE==False: return a list of frame aligned bone dictionary's + ACTION_BAKE==True: return an action with keys aligned to bone constrained movement + if ACTION_BAKE_FIRST_FRAME is not supplied or is true: keys begin at frame 1 The data in these can be swaped in for the IPO loc and quat @@ -77,7 +83,13 @@ def getBakedPoseData(ob_arm, start_frame, end_frame): # --------------------------------- Main loop to collect IPO data frame_index = 0 + NvideoFrames= end_frame-start_frame for current_frame in xrange(start_frame, end_frame+1): + if frame_index==0: start=sys.time() + elif frame_index==15: print NvideoFrames*(sys.time()-start),"seconds estimated..." #slows as it grows *3 + elif frame_index >15: + percom= frame_index*100/NvideoFrames + print "Frame %i Overall %i percent complete\r" % (current_frame, percom), ob_arm.action = backup_action #pose.update() # not needed Blender.Set('curframe', current_frame) @@ -88,9 +100,7 @@ def getBakedPoseData(ob_arm, start_frame, end_frame): for index, parent_index, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, ipo in armature_bone_data: matrix= pose_bone.poseMatrix - parent_bone= rest_bone.parent - if parent_index != -1: parent_pose_matrix = armature_bone_data[parent_index][6].poseMatrix parent_bone_matrix_inv = armature_bone_data[parent_index][5] @@ -98,40 +108,45 @@ def getBakedPoseData(ob_arm, start_frame, end_frame): rest_matrix= rest_matrix * parent_bone_matrix_inv matrix=matrix * rest_matrix.copy().invert() - pose_bone.quat= matrix.toQuat() pose_bone.loc= matrix.translationPart() - pose_bone.insertKey(ob_arm, 1, POSE_XFORM) # always frame 1 + if ACTION_BAKE==False: + pose_bone.insertKey(ob_arm, 1, POSE_XFORM) # always frame 1 + + # THIS IS A BAD HACK! IT SUCKS BIGTIME BUT THE RESULT ARE NICE + # - use a temp action and bake into that, always at the same frame + # so as not to make big IPO's, then collect the result from the IPOs - # THIS IS A BAD HACK! IT SUCKS BIGTIME BUT THE RESULT ARE NICE - # - use a temp action and bake into that, always at the same frame - # so as not to make big IPO's, then collect the result from the IPOs + # Now get the data from the IPOs + if not ipo: ipo = armature_bone_data[index][7] = new_action.getChannelIpo(bone_name) - # Now get the data from the IPOs - if not ipo: ipo = armature_bone_data[index][7] = new_action.getChannelIpo(bone_name) + loc = Vector() + quat = Quaternion() - loc = Vector() - quat = Quaternion() + for curve in ipo: + val = curve.evaluate(1) + curve_name= curve.name + if curve_name == 'LocX': loc[0] = val + elif curve_name == 'LocY': loc[1] = val + elif curve_name == 'LocZ': loc[2] = val + elif curve_name == 'QuatW': quat[3] = val + elif curve_name == 'QuatX': quat[0] = val + elif curve_name == 'QuatY': quat[1] = val + elif curve_name == 'QuatZ': quat[2] = val - for curve in ipo: - val = curve.evaluate(1) - curve_name= curve.name - if curve_name == 'LocX': loc[0] = val - elif curve_name == 'LocY': loc[1] = val - elif curve_name == 'LocZ': loc[2] = val - elif curve_name == 'QuatW': quat[3] = val - elif curve_name == 'QuatX': quat[0] = val - elif curve_name == 'QuatY': quat[1] = val - elif curve_name == 'QuatZ': quat[2] = val - - bake_data[frame_index][bone_name] = loc, quat - - + bake_data[frame_index][bone_name] = loc, quat + else: + if ACTION_BAKE_FIRST_FRAME: pose_bone.insertKey(ob_arm, frame_index+1, POSE_XFORM) + else: pose_bone.insertKey(ob_arm, current_frame , POSE_XFORM) frame_index+=1 - + print "\nBaking Complete." ob_arm.action = backup_action - Blender.Set('curframe', backup_frame) - return bake_data + if ACTION_BAKE==False: + Blender.Set('curframe', backup_frame) + return bake_data + elif ACTION_BAKE==True: + return new_action + else: print "ERROR: Invalid ACTION_BAKE %i sent to BPyArmature" % ACTION_BAKE diff --git a/release/scripts/c3d_import.py b/release/scripts/c3d_import.py new file mode 100644 index 00000000000..d67d56261d1 --- /dev/null +++ b/release/scripts/c3d_import.py @@ -0,0 +1,1237 @@ +#!BPY + +""" +Name: 'Motion Capture (.c3d)...' +Blender: 246 +Group: 'Import' +Tooltip: 'Import a C3D Motion Capture file' +""" +__script__ = "C3D Motion Capture file import" +__author__ = " Jean-Baptiste PERIN, Roger D. Wickes (rogerwickes@yahoo.com)" +__version__ = "0.8" +__url__ = ["Communicate problems and errors, BlenderArtists.org, Python forum"] +__email__= ["rogerwickes@yahoo.com", "c3d script"] +__bpydoc__ = """\ +c3d_import.py v0.8 + +Script loading Graphics Lab Motion Capture file, +Usage:
+ - Run the script
+ - Choose the file to open
+ - Press Import C3D button
+ +Version History: + 0.4: PERIN Released under Blender Artistic Licence + 0.5: WICKES used marker names, fixed 2.45 depricated call + 0.6: WICKES creates armature for each subject + 0.7: WICKES constrains armature to follow the empties (markers). Verified for shake hands s + 0.8: WICKES resolved DEC support issue +""" + +#---------------------------------------------- +# (c) Jean-Baptiste PERIN december 2005, released under Blender Artistic Licence +# for the Blender 2.40 Python Scripts Bundle. +#---------------------------------------------- + +###################################################### +# This script imports a C3D file into blender. +# Loader is based on MATLAB C3D loader from +# Alan Morris, Toronto, October 1998 +# Jaap Harlaar, Amsterdam, april 2002 +###################################################### + +import string +import Blender +from Blender import * +import bpy +import struct +import BPyMessages +Vector= Blender.Mathutils.Vector +Euler= Blender.Mathutils.Euler +Matrix= Blender.Mathutils.Matrix +RotationMatrix = Blender.Mathutils.RotationMatrix +TranslationMatrix= Blender.Mathutils.TranslationMatrix + +#================= +# Global Variables, Constants, Defaults, and Shorthand References +#================= +# set senstitivity for displaying debug/console messages. 0=few, 100=max, including clicks at major steps +# debug(num,string) to conditionally display status/info in console window +DEBUG=Blender.Get('rt') + +# marker sets known in the world +HUMAN_CMU= "HumanRTKm.mkr" # The Human Real-Time capture marker set used by CMU +HUMAN_CMU2="HumanRT.mkr" # found in another file, seems same as others in that series +MARKER_SETS = [ HUMAN_CMU, HUMAN_CMU2 ] # marker sets that this program supports (can make an armature for) +XYZ_LIMIT= 10000 #max value for coordinates if in integer format + +# what layers to put stuff on in scene. 1 is selected, so everything goes there +# selecting only layer 2 shows only the armature moving, 12 shows only the empties +LAYERS_ARMOB= [1,2] +LAYERS_MARKER=[1,12] +CLEAN=True # Should program ignore markers at (0,0,0) and beyond the outer limits? + +scn = Blender.Scene.GetCurrent() +# Why on earth would you rename a scene when importing data??? - Campbell +# scn.name="MoCap" #may want this enterable or derived based on motion being analyzed +#TODO: ultimately, a library of motions to append from means you need good naming of things + +BCS=Blender.Constraint.Settings # shorthand dictionary - define with brace, reference with bracket +trackto={"+x":BCS.TRACKX, "+y":BCS.TRACKY, "+z":BCS.TRACKZ, "-x":BCS.TRACKNEGX, "-y":BCS.TRACKNEGY, "-z":BCS.TRACKNEGZ} +trackup={"x":BCS.UPX, "y":BCS.UPY, "z":BCS.UPZ} + +#=============================# +# Classes +#=============================# +class Marker: + def __init__(self, x, y, z): + self.x=0.0 + self.y=0.0 + self.z=0.0 + + def __repr__(self): #report on self, as in if just printed + return str("[x = "+str(self.x) +" y = " + str(self.y)+" z = "+ str(self.z)+"]") + +class ParameterGroup: + def __init__(self, nom, description, parameter): + self.name = nom + self.description = description + self.parameter = parameter + + def __repr__(self): + return self.name, " ", self.description, " ", self.parameter + +class Parameter: + def __init__(self, name, datatype, dim, data, description): + self.name = name + self.datatype = datatype + self.dim = dim + self.data = data + self.description = description + + def __repr__(self): + return self.name, " ", self.description, " ", self.dim + +class MyVector: + def __init__(self, fx,fy,fz): + self.x=fx + self.y=fy + self.z=fz + +class Mybone: + "information structure for bone generation and posing" + def __init__(self, name,vec,par,head,tail,const): + self.name=name # name of this bone. must be unique within armature + self.vec=vec # edit bone vector it points + self.parent=par # name of parent bone to locate head and form a chain + self.headMark=head # list of 0+ markers where the head of this non-parented bone should be placed + self.tailMark=tail # list of 0+ markers where the tip should be placed + self.const=const # list of 0+ constraint tuples to control posing + self.head=MyVector(0,0,0) #T-pose location + self.tail=MyVector(0,0,0) + def __repr__(self): + return '[Mybone "%s"]' % self.name + + +#=============================# +# functions/modules +#=============================# +def error(str): + Draw.PupMenu('ERROR%t|'+str) + return +def status(str): + Draw.PupMenu('STATUS%t|'+str+"|Continue?") + return +def debug(num,msg): #use log4j or just console here. + if DEBUG >= num: + print 'debug:', (' '*num), msg + #TODO: if level 0, make a text file in Blender file to record major stuff + return + +def names(ob): return ob.name + + +######### +# Cette fonction renvoie la liste des empties +# in : +# out : emp_list (List of Object) la liste des objets de type "Empty" +######### +def getEmpty(name): + obs = [ob for ob in scn.objects if ob.type=="Empty" and ob.name==name] + if len(obs)==0: + return None + elif len(obs)==1: + return obs[0] + else: + error("FATAL ERROR: %i empties %s in file" % (len(obs),ob[0])) +######### +# Cette fonction renvoie un empty +# in : objname : le nom de l'empty recherche +# out : myobj : l'empty cree ou retrouve +######### +def GetOrCreateEmpty(objname): + myobj= getEmpty(objname) + if myobj==None: + myobj = scn.objects.new("Empty",objname) + myobj.layers= LAYERS_MARKER + debug(50,'Marker/Empty created %s' % myobj) + return myobj + +def GetOrCreateCurve(ipo, curvename): + """ + Retrieve or create a Blender Ipo Curve named C{curvename} in the C{ipo} Ipo + + >>> import mylib + + >>> lIpo = GetOrCreateIPO("Une IPO") + >>> laCurve = GetOrCreateCurve(lIpo, "RotX") + + Either an ipo curve named C{curvename} exists before the call then this curve is returned, + Or such a curve doesn't exist before the call .. then it is created into the c{ipo} Ipo and returned + + @type ipo: Blender Ipo + @param ipo: the Ipo in which the curve must be retrieved or created. + @type curvename: string + @param curvename: name of the IPO. + @rtype: Blender Curve + @return: a Blender Curve named C{curvename} in the C{ipo} Ipo + """ + try: + mycurve = ipo.getCurve(curvename) + if mycurve != None: + pass + else: + mycurve = ipo.addCurve(curvename) + except: + mycurve = ipo.addCurve(curvename) + return mycurve + +def eraseIPO (objectname): + object = Blender.Object.Get(objectname) + lIpo = object.getIpo() + if lIpo != None: + nbCurves = lIpo.getNcurves() + for i in range(nbCurves): + nbBezPoints = lIpo.getNBezPoints(i) + for j in range(nbBezPoints): + lIpo.delBezPoint(i) + +def comp_loc(emptyNameList): + myloc=Vector(0,0,0) + for emName in emptyNameList: + myobj = Blender.Object.Get(emName) + for i in range(3): + myloc[i]= myloc[i]+(myobj.loc[i]/len(emptyNameList)) #take the average loc of all marks + return myloc + +def comp_len(head, tail): # computes the length of a bone + headvec=comp_loc(head) + tailvec=comp_loc(tail) + netvec=headvec-tailvec + return netvec.length + +def createHumanCMU(): # human bone structure, makes a node set for CMU MoCap Lab + # order of bones: "spine","chest","neck","head",...face toward you in front view + # pose constraints are tuples of (type,target,influence,other-as-needed) + # constraint stack order is important. for proper bone pointing and orinetation: + # IK, then TT +YZ in world space. then LR XZ to 0 in world space, this points the bone, twists it, but then + # limits the rotation to the sidebar enpty with the Z facing it, and Y pointing along the bone. + nodes=[] # bonename, vector, parent, head targets, tail targets, constraint list + for i in range(23): nodes.append(Mybone("name","vec","par",[],[],[])) + nodes[0]= Mybone("root", "-Y","",["RBWT", "LBWT"],["RFWT", "LFWT", "RBWT", "LBWT"],[("LOC","RBWT",1.0),("LOC","LBWT",0.5),("IK","RFWT",1.0),("IK","LFWT",0.5),("TT","RBWT",1,"+YZ"),("LR","XZ",1)]) + nodes[1]= Mybone("spine","+Z","root",[],["STRN","T10"],[("IK","STRN",1.0),("IK","T10",0.5),("TT","STRN",1,"+YZ"),("LR","XZ",1)]) + nodes[2]= Mybone("chest","+Z","spine",[],["CLAV","C7"],[("IK","CLAV",1.0),("IK","C7",0.5),("TT","CLAV",1,"+YZ"),("LR","XZ",1)]) + nodes[3]= Mybone("neck", "+Z","chest",[],["RBHD","LBHD"],[("IK","RBHD",1.0),("IK","LBHD",0.5),("TT","LBHD",1,"+YZ"),("LR","XZ",1)]) + nodes[4]= Mybone("head" ,"-Y","neck",[],["RFHD","LFHD"],[("IK","RFHD",1.0),("IK","LFHD",0.5),("TT","LFHD",1,"+YZ"),("LR","XZ",1)]) + + nodes[5]= Mybone("shoulder.R","-X","chest",[],["RSHO"],[("IK","RSHO",1.0)]) + nodes[6]= Mybone("toparm.R", "-X","shoulder.R",[],["RELB"],[("IK","RELB",1.0),("TT","RUPA",1,"+YZ"),("LR","XZ",1)]) + nodes[7]= Mybone("lowarm.R", "-X","toparm.R",[],["RWRA","RWRB"],[("IK","RWRA",1.0),("IK","RWRB",0.5),("TT","RFRM",1,"+YZ"),("LR","XZ",1)]) + nodes[8]= Mybone("hand.R", "-X","lowarm.R",[],["RFIN"],[("IK","RFIN",1.0),("TT","RWRA",1,"+YZ"),("LR","XZ",1)]) #missing ,"RTHM" + + nodes[9]= Mybone("hip.R", "-X","root",[],["RFWT","RBWT"],[("IK","RFWT",1.0),("IK","RBWT",0.5)]) + nodes[10]=Mybone("topleg.R","-Z","hip.R",[],["RKNE"],[("IK","RKNE",1),("TT","RTHI",1,"+YZ"),("LR","XZ",1)]) + nodes[11]=Mybone("lowleg.R","-Z","topleg.R",[],["RANK","RHEE"],[("IK","RHEE",1.0),("TT","RSHN",1,"+YZ"),("LR","XZ",1)]) + nodes[12]=Mybone("foot.R", "-Y","lowleg.R",[],["RTOE","RMT5"],[("IK","RTOE",1.0),("IK","RMT5",0.2),("TT","RMT5",1,"+YZ")]) + nodes[13]=Mybone("toes.R", "-Y","foot.R",[],["RTOE"],[("IK","RTOE",1.0)]) + + nodes[14]=Mybone("shoulder.L","+X","chest",[],["LSHO"],[("IK","LSHO",1.0)]) + nodes[15]=Mybone("toparm.L", "+X","shoulder.L",[],["LELB"],[("IK","LELB",1.0),("TT","LUPA",1,"+YZ"),("LR","XZ",1)]) + nodes[16]=Mybone("lowarm.L", "+X","toparm.L",[],["LWRA","LWRB"],[("IK","LWRA",1.0),("IK","LWRB",0.5),("TT","LFRM",1,"+YZ"),("LR","XZ",1)]) + nodes[17]=Mybone("hand.L", "+X","lowarm.L",[],["LFIN"],[("IK","LFIN",1.0),("TT","RWRA",1,"+YZ"),("LR","XZ",1)]) #missing ,"LTHM" + + nodes[18]=Mybone("hip.L", "+X","root",[],["LFWT","LBWT"],[("IK","LFWT",1.0),("IK","LBWT",0.5)]) + nodes[19]=Mybone("topleg.L","-Z","hip.L",[],["LKNE"],[("IK","LKNE",1),("TT","LTHI",1,"+YZ"),("LR","XZ",1)]) + nodes[20]=Mybone("lowleg.L","-Z","topleg.L",[],["LANK","LHEE"],[("IK","LHEE",1.0),("TT","LSHN",1,"+YZ"),("LR","XZ",1)]) + nodes[21]=Mybone("foot.L", "-Y","lowleg.L",[],["LTOE","LMT5"],[("IK","LTOE",1.0),("IK","LMT5",0.2),("TT","LMT5",1,"+YZ"),("LR","XZ",1)]) + nodes[22]=Mybone("toes.L", "-Y","foot.L",[],["LTOE"],[("IK","LTOE",1.0)]) + return nodes + +def createNodes(marker_set): # make a list of bone name, parent, edit head loc, edit tail loc, pose constraints + #ultimately, I want to read in an XML file here that specifies the node trees for various marker sets + if marker_set==HUMAN_CMU: nodes= createHumanCMU() #load up and verify the file has the CMU marker set + elif marker_set==HUMAN_CMU2: nodes= createHumanCMU() + else: nodes=[] + return nodes +def findEntry(item,list): + for i in range(len(list)): + if item==list[i]: break + debug(100,"findEtnry %s is %i in list of %i items" % (item,i,len(list))) + return i +def makeNodes(prefix, markerList, empties, marker_set): #make sure the file has the nodes selected + nodes= createNodes(marker_set) # list has generic marker names; replace them with the actual object names created + #each entry in markerlist has a corresponding entry in empties in the same order + errList=[] + for i in range(len(nodes)): + node= nodes[i] + debug(60,"Adapting node %s to prefix %s" % (node,prefix)) + + #replace generic head markers with actual empty names + for im in range(len(node.headMark)): + marker= node.headMark[im] + mark= prefix+marker + imn= findEntry(mark,markerList) + if imn < len(markerList): + debug(90,"Adapating head marker %s to %s" % (marker,empties[imn].name)) + nodes[i].headMark[im]= empties[imn].name + else: errList.append([node.name,"head location",mark,node,2]) + + #replace generic tail markers with actual empty names + for im in range(len(node.tailMark)): + marker= node.tailMark[im] + mark= prefix+marker + imn= findEntry(mark,markerList) + if imn < len(markerList): + debug(90,"Adapating marker %s to %s" % (marker,empties[imn].name)) + nodes[i].tailMark[im]= empties[imn].name + else: errList.append([node.name,"tail location",mark,node,2]) + + #replace generic constraint markers (if the constraint references a marker) with empty name + for im in range(len(node.const)): + const=node.const[im] + if const[0] in ("LOC","IK","TT"): + marker=const[1] + mark= prefix+marker + imn= findEntry(mark,markerList) + if imn < len(markerList): + debug(90,"Adapating %s constraint marker %s to %s" % (const[0],marker,empties[imn].name)) + if const[0] in ("IK","LR","LOC"): + nodes[i].const[im]=(const[0], empties[imn].name, const[2]) + else: nodes[i].const[im]=(const[0], empties[imn].name, const[2], const[3]) + else: errList.append([node.name,const[0]+" constraint",mark,node,4]) + + if errList!=[]: #we have issues. + for err in errList: + debug(0,"Bone "+err[0]+" specifies "+err[2]+" as "+err[1]+"which was not specified in file.") + #need a popup here to ignore/cleanup node tree, or add the marker(?) or abort + usrOption= 1 + if usrOption==0: #ignore this marker (remove it) + for node in nodes: #find the bone in error + if node.name==err[0]: + print "Before",node + if err[3] in range(2,3): + node[err[3]].remove(err[2]) #find the marker in error and remove it + elif err[3]==4: #find the constraint and remove it + for const in node.const: + if const[1]==err[2]: node.const.remove(const) + print "After",node + elif usrOption==1: #add these markers as static empties, and user will automate them later + #and the bones will be keyed to them, so it will all be good. + #file may have just mis-named the empty, or the location can be derived based on other markers + em= GetOrCreateEmpty(err[2]) + else: abort() #abend + if DEBUG==100: status("Nodes Updated") + return nodes #nodes may be updated + +def makeBones(arm,nodes): + debug(20,"Making %i edit bones" % len(nodes)) + for node in nodes: + bone= Blender.Armature.Editbone() + bone.name= node.name + arm.bones[bone.name]= bone #add it to the armature + debug(50,"Bone added: %s" % bone) + if bone.name <> node.name: + debug(0,"ERROR: duplicate node % name specified" % node.name) + node.name= bone.name #you may not get what you asked for + if node.parent!="": #parent + debug(60,"Bone parent: %s"%node.parent) + bone.parent= arm.bones[node.parent] + bone.options = [Armature.CONNECTED] + #compute head = average of the reference empties + if node.headMark==[]: # no head explicitly stated, must be tail of parent + for parnode in nodes: + if node.parent==parnode.name: break + node.headMark= parnode.tailMark + node.head= parnode.tail + else: node.head= comp_loc(node.headMark) #node head is specified, probably only for root. + + bone.head= node.head + debug(60,"%s bone head: (%0.2f, %0.2f, %0.2f)" % (bone.name,bone.head.x, bone.head.y, bone.head.z)) + mylen=comp_len(node.headMark,node.tailMark) # length of the bone as it was recorded for that person + # for our T position, compute the bone length, add it to the head vector component to get the tail + if node.vec[0]=="-": mylen=-mylen + debug(80,"Bone vector %s length %0.2f" %(node.vec,mylen)) + node.tail= Vector(node.head) + myvec=node.vec[1].lower() + if myvec=="x": node.tail.x+=mylen + elif myvec=="y": node.tail.y+=mylen + elif myvec=="z": node.tail.z+=mylen + else: + debug(0,"%s %s %s %s" % (node.vec,myvec,node.vec[0],node.vec[1])) + error("ERROR IN BONE SPEC ") + bone.tail= node.tail + debug(60,"Bone tail: (%i,%i,%i)" %(bone.tail.x, bone.tail.y, bone.tail.z)) + #Armature created in the T postion, but with bone lengths to match the marker set and subject + #when this is constrained to the markers, the recorded action will be relative to a know Rotation + #so that all recorded actions should be interchangeable. wooot! + #Only have to adjust starting object loc when matching up actions. + return #arm #updated + +def makeConstLoc(pbone,const): + const_new= pbone.constraints.append(Constraint.Type.COPYLOC) + const_new.name = const[0]+"-"+const[1] + const_target=Blender.Object.Get(const[1]) + const_new[BCS.TARGET]= const_target + const_new.influence = const[2] + return + +def makeConstLimRot(pbone,const): + const_new= pbone.constraints.append(Constraint.Type.LIMITROT) + const_new.name = const[0]+"-"+const[1] + for axis in const[1]: + if axis.lower()=="x": const_new[BCS.LIMIT] |= BCS.LIMIT_XROT #set + if axis.lower()=="y": const_new[BCS.LIMIT] |= BCS.LIMIT_YROT #set + if axis.lower()=="z": const_new[BCS.LIMIT] |= BCS.LIMIT_ZROT #set + const_new[BCS.OWNERSPACE]= BCS.SPACE_LOCAL + const_new.influence = const[2] + # fyi, const[Constraint.Settings.LIMIT] &= ~Constraint.Settings.LIMIT_XROT #reset + return + +def makeConstIK(prefix,pbone,const): + #Blender 246 only supports one IK Solver per bone, but we might want many, + # so we need to create a reference empty named after the bone + # that floats between the markers, so the bone can point to it as a singularity + myob= GetOrCreateEmpty(prefix+pbone.name) + # note that this empty gets all the IK constraints added on + myconst= myob.constraints.append(Constraint.Type.COPYLOC) + myconst.name=const[0]+"-"+const[1] + myconst[Constraint.Settings.TARGET]= Blender.Object.Get(const[1]) + myconst.influence = const[2] + + #point the bone once to the empty via IK + success=False + for myconst in pbone.constraints: + if myconst.type == Constraint.Type.IKSOLVER: success=True + if not(success): #add an IK constraint to the bone to point to the empty + #print pbone + myconst= pbone.constraints.append(Constraint.Type.IKSOLVER) + myconst.name = const[1] + myconst[BCS.TARGET]= myob + myconst.influence = const[2] + #const_new[Constraint.Settings.BONE]= ? + myconst[BCS.CHAINLEN]= 1 + myconst[BCS.USETIP]= True + myconst[BCS.STRETCH]= False + return + +def makeConstTT(pbone,const): + myconst= pbone.constraints.append(Constraint.Type.TRACKTO) + myconst.name=const[0]+"-"+const[1] + debug(70,"%s %s" % (myconst,const[3])) + myob= GetOrCreateEmpty(const[1]) + myconst[BCS.TARGET]= myob + myconst.influence = const[2] + #const[3] is the Track and the thrird char is the Up indicator + myconst[BCS.TRACK]= trackto[const[3][0:2].lower()] + myconst[BCS.UP]=trackup[const[3][2].lower()]#up direction + myconst[BCS.OWNERSPACE]= BCS.SPACE_LOCAL + myconst[BCS.TARGETSPACE]= [BCS.SPACE_LOCAL] + if const[3][1]==const[3][2]: debug(0,"WARNING: Track To axis and up axis should not be the same. Constraint is INACTIVE") + return + +def makePoses(prefix,arm_ob,nodes): # pose this armature object based on node requirements + #this is constraint-based posing, not hard-keyed posing. + #we do constraint-based first so that user can adjust the constraints, possibly smooth/tweak motion + # add additional bones or referneces/constraints, before baking to hard keyframes + + pose= arm_ob.getPose() + debug(0,"Posing %s %s" % (arm_ob, pose)) + for node in nodes: + debug(30, "examining %s" %node) + if len(node.const)>0: #constraints for this bone are desired + pbone = pose.bones[node.name] + debug(40,"Posing bone %s" %pbone) + for const in node.const: + debug(50,"Constraining %s by %s" %(pbone,const)) + if const[0]=="LOC":makeConstLoc(pbone,const) + elif const[0]=="IK": makeConstIK(prefix,pbone,const) + elif const[0]=="LR": makeConstLimRot(pbone,const) + elif const[0]=="TT": makeConstTT(pbone,const) + else: + error("FATAL: constraint %s not supported" %const[0]) + break + debug(10, "Posing complete. Cycling pose and edit mode") + pose.update() + return + +def make_arm(subject,prefix,markerList, emptyList,marker_set): + debug(10,"**************************") + debug(00, "**** Making Armature for %s..." % subject) + debug(10, "**************************") + # copied from bvh import bvh_node_dict2armature; trying to use similar process for further integtration down the road + # Add the new armature, + + nodes= makeNodes(prefix, markerList, emptyList, marker_set) #assume everyone in file uses the same mocap suit + # each person in the file may be different height, so each needs their own new armature to match marker location + +## obs= Blender.Object.Get() +## success=False +## for ob in obs: +## if ob.name==subject: +## success=True +## if success: +## menu="Human Armature already exists for this subject." +## menu+="%t|Create another in this scene" +## menu+="%l|Start a new scene" +## menu+="%l|Use this armature" +## menusel= Draw.PupMenu(menu) + + arm= Blender.Armature.New(subject) #make an armature. + debug(10,"Created Armature %s" % arm) + # Put us into editmode + arm.makeEditable() + arm.drawType = Armature.OCTAHEDRON + makeBones(arm,nodes) + scn = Blender.Scene.GetCurrent() #add it to the current scene. could create new scenes here as yaf + arm_ob= scn.objects.new(arm) #instance it in the scene. this is the new way for 2.46 to instance objects + arm_ob.name= subject #name it something like the person it represents + arm_ob.layers= LAYERS_ARMOB + debug(20,"Instanced Armature %s" % arm_ob) + arm.update() #exit editmode. Arm must be instanced as an object before you can save changes or pose it + Blender.Redraw() # show the world + if DEBUG==100: status("T-Bones made.") + + makePoses(prefix,arm_ob,nodes) #constrain arm_ob with these markers + + scn.update(1) #make everyone behave themselves in the scene, and respect the new constraints + return arm_ob + +def setupAnim(StartFrame, EndFrame, VideoFrameRate): + debug(100, 'VideoFrameRate is %i' %VideoFrameRate) + if VideoFrameRate<1: VideoFrameRate=1 + if VideoFrameRate>120: VideoFrameRate=120 + # set up anim panel for them + context=scn.getRenderingContext() + context.startFrame(StartFrame) + context.endFrame(EndFrame) + context.framesPerSec(int(VideoFrameRate)) + Blender.Set("curframe",StartFrame) + Blender.Redraw() + return + +def makeCloud(Nmarkers,markerList,StartFrame,EndFrame,Markers): + debug(10, "**************************") + debug(00, "*** Making Cloud Formation") + debug(10, "**************************") + empties=[] + ipos=[] + curvesX=[] + curvesY=[] + curvesZ=[] + debug(0, "%i Markers (empty cloud) will be put on layers %s" % (Nmarkers,LAYERS_MARKER)) + # Empty Cloud formation + for i in range(Nmarkers): + debug(100,"%i marker %s"%(i, markerList[i])) + emptyname = markerList[i] # rdw: to use meaningful names from Points parameter + em= GetOrCreateEmpty(emptyname) #in this scene + #make a list of the actual empty + empties.append(em) + #assign it an ipo with the loc xyz curves + lipo = Ipo.New("Object",em.name) + ipos.append(lipo) + curvesX.append(GetOrCreateCurve(ipos[i],'LocX')) + curvesY.append(GetOrCreateCurve(ipos[i],'LocY')) + curvesZ.append(GetOrCreateCurve(ipos[i],'LocZ')) + empties[i].setIpo(ipos[i]) + debug(30,"Cloud of %i empties created." % len(empties)) + NvideoFrames= EndFrame-StartFrame+1 + debug(10, "**************************") + debug(00, "**** Calculating Marker Ipo Curves over %i Frames ..." % NvideoFrames) + debug(10, "**************************") + err= index=0 #number of errors, logical frame + for frame in range(StartFrame,EndFrame+1): + if index==0: start=sys.time() + elif index==100: + tmp=(NvideoFrames-100)*(sys.time()-start)/6000 + debug(0,"%i minutes process time estimated" % tmp) + elif index >100: print index*100/(NvideoFrames-1),"% complete\r", + for i in range(Nmarkers): + if Markers[index][i].z < 0: Markers[index][i].z= -Markers[index][i].z + success=True + if CLEAN: #check for good data + # C3D marker decoding may have coordinates negative (improper sign bit decoding?) + myX= abs(Markers[index][i].x) + myY= abs(Markers[index][i].y) + myZ= Markers[index][i].z + if myX > 10000 or myY > 10000 or myZ > 10000: success=False + if myX <.01 and myY <.01 and myZ <.01: success=False # discontinuity in marker tracking (lost marker) + + if success: + curvesX[i].append((frame, Markers[index][i].x)) #2.46 knot method + curvesY[i].append((frame, Markers[index][i].y)) + curvesZ[i].append((frame, Markers[index][i].z)) + if frame==StartFrame: debug(40, "%s loc frame %i: (%0.2f, %0.2f, %0.2f)" % (markerList[i],frame,Markers[index][i].x,Markers[index][i].y,Markers[index][i].z)) + else: + err+=1 # some files have thousands... + #debug(30,"Point ignored for marker:%s frame %i: (%i, %i, %i)" % (markerList[i],frame,Markers[index][i].x,Markers[index][i].y,Markers[index][i].z)) + index += 1 + debug(70, "%i points ignored across all markers and frames. Recalculating..." % err) + + for i in range(Nmarkers): + curvesX[i].Recalc() + curvesY[i].Recalc() + curvesZ[i].Recalc() + Blender.Set('curframe', StartFrame) + Blender.Redraw() + if DEBUG==100: status("Clound formed") + return empties + +def getNumber(str, length): + if length==2: # unsigned short + return struct.unpack('H',str[0:2])[0], str[2:] + sum = 0 + for i in range(length): + #sum = (sum << 8) + ord(str[i]) for big endian + sum = sum + ord(str[i])*(2**(8*i)) + return sum, str[length:] +def unpackFloat(chunk,proctype): + #print proctype + myvar=chunk[0:4] + if proctype==2: #DEC-VAX + myvar=chunk[2:4]+chunk[0:2] #swap lo=hi word order pair + return struct.unpack('f',myvar[0:4])[0] + +def getFloat(chunk,proctype): + return unpackFloat(chunk, proctype), chunk[4:] +def parseFloat(chunk,ptr,proctype): + return unpackFloat(chunk[ptr:ptr+4], proctype), ptr+4 + + +def load_c3d(FullFileName): +# Input: FullFileName - file (including path) to be read +# +# Variable: +# Markers 3D-marker data [Nmarkers x NvideoFrames x Ndim(=3)] +# VideoFrameRate Frames/sec +# AnalogSignals Analog signals [Nsignals x NanalogSamples ] +# AnalogFrameRate Samples/sec +# Event Event(Nevents).time ..value ..name +# ParameterGroup ParameterGroup(Ngroups).Parameters(Nparameters).data ..etc. +# CameraInfo MarkerRelated CameraInfo [Nmarkers x NvideoFrames] +# ResidualError MarkerRelated ErrorInfo [Nmarkers x NvideoFrames] + + Markers=[]; + VideoFrameRate=120; + AnalogSignals=[]; + AnalogFrameRate=0; + Event=[]; + ParameterGroups=[]; + CameraInfo=[]; + ResidualError=[]; + + debug(10, "*********************") + debug(10, "**** Opening File ***") + debug(10, "*********************") + + #ind=findstr(FullFileName,'\'); + #if ind>0, FileName=FullFileName(ind(length(ind))+1:length(FullFileName)); else FileName=FullFileName; end + debug(0, "FileName = " + FullFileName) + fid=open(FullFileName,'rb'); # native format (PC-intel). ideasman says maybe rU + content = fid.read(); + content_memory = content + #Header section + NrecordFirstParameterblock, content = getNumber(content,1) # Reading record number of parameter section + + key, content = getNumber(content,1) + if key!=80: + error('File: does not comply to the C3D format') + fid.close() + return + #Paramter section + content = content[512*(NrecordFirstParameterblock-1)+1:] # first word ignored + #file format spec says that 3rd byte=NumberofParmaterRecords... but is ignored here. + proctype,content =getNumber(content,1) + proctype = proctype-83 + proctypes= ["unknown","(INTEL-PC)","(DEC-VAX)","(MIPS-SUN/SGI)"] + + if proctype in (1,2): debug(0, "Processor coding %s"%proctypes[proctype]) + elif proctype==3: debug(0,"Program untested with %s"%proctypes[proctype]) + else: + debug(0, "INVALID processor type %i"%proctype) + proctype=1 + debug(0,"OVERRIDE processor type %i"%proctype) + + #if proctype==2, + # fclose(fid); + # fid=fopen(FullFileName,'r','d'); % DEC VAX D floating point and VAX ordering + #end + debug(10, "***********************") + debug(00, "**** Reading Header ***") + debug(10, "***********************") + + # ############################################### + # ## ## + # ## read header ## + # ## ## + # ############################################### + + #%NrecordFirstParameterblock=fread(fid,1,'int8'); % Reading record number of parameter section + #%key1=fread(fid,1,'int8'); % key = 80; + + content = content_memory + #fseek(fid,2,'bof'); + content = content[2:] + + # + Nmarkers, content=getNumber(content, 2) + NanalogSamplesPerVideoFrame, content = getNumber(content, 2) + StartFrame, content = getNumber(content, 2) + EndFrame, content = getNumber(content, 2) + MaxInterpolationGap, content = getNumber(content, 2) + + Scale, content = getFloat(content,proctype) + + NrecordDataBlock, content = getNumber(content, 2) + NanalogFramesPerVideoFrame, content = getNumber(content, 2) + + if NanalogFramesPerVideoFrame > 0: + NanalogChannels=NanalogSamplesPerVideoFrame/NanalogFramesPerVideoFrame + else: + NanalogChannels=0 + + VideoFrameRate, content = getFloat(content,proctype) + + AnalogFrameRate=VideoFrameRate*NanalogFramesPerVideoFrame + NvideoFrames = EndFrame - StartFrame + 1 + + debug(0, "Scale= %0.2f" %Scale) + debug(0, "NanalogFramesPerVideoFrame= %i" %NanalogFramesPerVideoFrame) + debug(0, "Video Frame Rate= %i" %VideoFrameRate) + debug(0, "AnalogFrame Rate= %i"%AnalogFrameRate) + debug(0, "# markers= %i" %Nmarkers) + debug(0, "StartFrame= %i" %StartFrame) + debug(0, "EndFrame= %i" %EndFrame) + debug(0, "# Video Frames= %i" %NvideoFrames) + + if Scale>0: + debug(0, "Marker data is in integer format") + if Scale>(XYZ_LIMIT/32767): + Scale=XYZ_LIMIT/32767.0 + debug(0, "OVERRIDE: Max coordinate is %i, Scale changed to %0.2f" % (XYZ_LIMIT,Scale)) + else: debug(0, "Marker data is in floating point format") + if VideoFrameRate<1 or VideoFrameRate>120: + VideoFrameRate= 120 + debug(0, "OVERRIDE Video Frame Rate= %i" %VideoFrameRate) + if proctype not in (1,2): # Intel, DEC are known good + debug(0, "OVERRIDE|Program not tested with this encoding. Set to Intel") + proctype= 1 + + debug(10, "***********************") + debug(10, "**** Reading Events ...") + debug(10, "***********************") + + content = content_memory + content = content[298:] #bizarre .. ce devrait être 150 selon la doc rdw skips first 299 bytes? + + EventIndicator, content = getNumber(content, 2) + EventTime=[] + EventValue=[] + EventName=[] + + debug(0, "Event Indicator = %i" %EventIndicator) + if EventIndicator==12345: #rdw: somehow, this original code seems fishy, but I cannot deny it. + Nevents, content = getNumber(content, 2) + debug(0, "Nevents= %i" %Nevents) + content = content[2:] + if Nevents>0: + for i in range(Nevents): + letime, content = getFloat(content,proctype) + EventTime.append(letime) + content = content_memory + content = content[188*2:] + for i in range(Nevents): + lavalue, content = getNumber(content, 1) + EventValue.append(lavalue) + content = content_memory + content = content[198*2:] + for i in range(Nevents): + lenom = content[0:4] + content = content[4:] + EventName.append(lenom) + + debug(00, "***************************") + debug(00, "**** Reading Parameters ...") + debug(10, "***************************") + subjects=[] # a name would be nice, but human will do + prefixes=[] # added on to mocap marker names, one for each subject + marker_subjects = [] # hopefully will be specified in the file and known to this program + markerList=[] + ParameterGroups = [] + ParameterNumberIndex = [] + + content = content_memory + content = content[512*(NrecordFirstParameterblock-1):] + + dat1, content = getNumber(content, 1) + key2, content = getNumber(content, 1) + + NparameterRecords, content = getNumber(content, 1) + debug(100, "NparameterRecords=%i"%NparameterRecords) + proctype,content =getNumber(content,1) + proctype = proctype-83 # proctype: 1(INTEL-PC); 2(DEC-VAX); 3(MIPS-SUN/SGI) + + for i in range(NparameterRecords): + leparam = ParameterGroup(None, None, []) + ParameterGroups.append(leparam) + ParameterNumberIndex.append(0) + # + Ncharacters, content = getNumber(content, 1) + if Ncharacters>=128: + Ncharacters = -(2**8)+(Ncharacters) + GroupNumber, content = getNumber(content, 1) + if GroupNumber>=128: + GroupNumber = -(2**8)+(GroupNumber) + debug(80,"GroupNumber = %i, Nchar=%i" %(GroupNumber,Ncharacters)) + + while Ncharacters > 0: + if GroupNumber<0: + GroupNumber=abs(GroupNumber) + GroupName = content[0:Ncharacters] + content = content[Ncharacters:] + #print "Group Number = ", GroupNumber + ParameterGroups[GroupNumber].name = GroupName + #print "ParameterGroupName =", GroupName + offset, content = getNumber(content, 2) + deschars, content = getNumber(content, 1) + GroupDescription = content[0:deschars] + content = content[deschars:] + ParameterGroups[GroupNumber].description = GroupDescription + # + ParameterNumberIndex[GroupNumber]=0 + content = content[offset-3-deschars:] + else: + + ParameterNumberIndex[GroupNumber]=ParameterNumberIndex[GroupNumber]+1 + ParameterNumber=ParameterNumberIndex[GroupNumber] + #print "ParameterNumber=", ParameterNumber + ParameterGroups[GroupNumber].parameter.append(Parameter(None, None, [], [], None)) + ParameterName = content[0:Ncharacters] + content = content[Ncharacters:] + #print "ParameterName = ",ParameterName + if len(ParameterName)>0: + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].name=ParameterName + offset, content = getNumber(content, 2) + filepos = len(content_memory)-len(content) + nextrec = filepos+offset-2 + + type, content=getNumber(content, 1) + if type>=128: + type = -(2**8)+type + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].type=type + + dimnum, content=getNumber(content, 1) + if dimnum == 0: + datalength = abs(type) + else: + mult=1 + dimension=[] + for j in range (dimnum): + ladim, content = getNumber(content, 1) + dimension.append(ladim) + mult=mult*dimension[j] + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].dim.append(dimension[j]) + datalength = abs(type)*mult + + #print "ParameterNumber = ", ParameterNumber, " Group Number = ", GroupNumber + + if type==-1: + data = "" + wordlength=dimension[0] + if dimnum==2 and datalength>0: + for j in range(dimension[1]): + data=string.rstrip(content[0:wordlength]) + content = content[wordlength:] + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data.append(data) + elif dimnum==1 and datalength>0: + data=content[0:wordlength] + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data.append(data) # ??? + + myParam=string.rstrip(ParameterName) + myGroup=string.rstrip(GroupName) + msg= "-%s-%s-" % (myGroup,myParam) + if myGroup == "POINT": + if myParam== "LABELS": + # named in form of subject:marker. + # the list "empties" is a corresponding list of actual empty object names that make up the cloud + markerList= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + debug(0, "%sLABELS = %i %s" %(msg, len(markerList),markerList)) #list of logical markers from 0 to n corresponding to points + elif myParam== "LABELS2": #more labels + # named in form of subject:marker. + # the list "empties" is a corresponding list of actual empty object names that make up the cloud + momarkList= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + markerList+=momarkList + debug(0, "%sLABELS2 = %i %s" %(msg, len(momarkList),momarkList)) #list of logical markers from 0 to n corresponding to points + else: debug(70, "%s UNUSED = %s" %(msg,ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data)) + elif myGroup in ["SUBJECT", "SUBJECTS"]: #info about the actor + if myParam in ["NAME", "NAMES"]: + subjects= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + debug(0, "%sNames of Subjects = %s" %(msg, subjects)) # might be useful in naming armatures + for i in range(len(subjects)): + subjects[i]=subjects[i].rstrip() + if subjects[i]=="": subjects[i]="Human" + elif myParam == "LABEL_PREFIXES": + prefixes = ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + debug(0, "%sMarker Prefixes = %s" %(msg, prefixes)) # to xlate marker name to that in file + for i in range(len(prefixes)): + prefixes[i]=prefixes[i].rstrip() + elif myParam== "MARKER_SETS": + marker_subjects= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + debug(0, "%sMarker Set = %s"%(msg, marker_subjects)) # marker set that each subject was wearing + elif myParam== "MODEL_PARAM": + action= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + debug(0, "%sModel Paramter = %s"%(msg,action)) # might be a good name for the blender scene + elif myParam== "LABELS": + # named in form of subject:marker. + # the list "empties" is a corresponding list of actual empty object names that make up the cloud + markerList= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + debug(0, "%sLABELS = %i %s"%(msg, len(markerList),markerList)) #list of logical markers from 0 to n corresponding to points + else: debug(70, "%sUNUSED = %s"%(msg, ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data)) + else: + debug(70, "%sUNUSED = %s"%(msg, ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data)) + elif type == 1: + debug(100,"Block type %i is largely unsupported and untested."%type) + data = [] + Nparameters=datalength/abs(type) + debug(100, "Nparameters=%i"%Nparameters) + for i in range(Nparameters): + ladata,content = getNumber(content, 1) + data.append(ladata) + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data + #print ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + + #print "type boolean" + elif type == 2 and datalength>0: + debug(100,"Block type %i is largely unsupported and untested."%type) + data = [] + Nparameters=datalength/abs(type) + debug(100, "Nparameters=%i"%Nparameters) + for i in range(Nparameters): + ladata,content = getNumber(content, 2) + data.append(ladata) + #ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data + if dimnum>1: + #???? print "arg je comprends pas" + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data + #???ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=reshape(data,dimension) + else: + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data + #print ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + #pass + #print "type integer" + elif type == 4 and datalength>0: + debug(100,"Block type %i is largely unsupported and untested."%type) + data = [] + Nparameters=datalength/abs(type) + debug(100, "Nparameters=%i"%Nparameters) + for i in range(Nparameters): + ladata,content = getFloat(content,proctype) + data.append(ladata) + if dimnum>1: + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data + #print "arg je comprends pas" + #???ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=reshape(data,dimension) + else: + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data + #print ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data + else: + debug(100,"Block type %i is largely unsupported and untested."%type) + #print "error" + pass + deschars, content= getNumber(content, 1) + if deschars>0: + description = content[0:deschars] + content = content[deschars:] + ParameterGroups[GroupNumber].parameter[ParameterNumber-1].description=description + + content = content_memory + content = content[nextrec:] + + Ncharacters,content = getNumber(content, 1) + if Ncharacters>=128: + Ncharacters = -(2**8)+(Ncharacters) + GroupNumber,content = getNumber(content, 1) + if GroupNumber>=128: + GroupNumber = -(2**8)+(GroupNumber) + debug(80,"GroupNumber = %i, Nchar=%i" %(GroupNumber,Ncharacters)) + + debug(00, "***************************") + debug(00, "**** Examining Parameters ...") + debug(10, "***************************") + + if len(subjects)==0: subjects=["Test"] #well, somebody got mocapped! + for i in range(0, len(subjects)-len(prefixes)): prefixes.append("") + for i in range(0, len(subjects)-len(marker_subjects)): marker_subjects.append(subjects[i]) + + #make a markerlist if they didn't + debug(0, "%i Markers specified, %i marker names supplied" %(Nmarkers,len(markerList))) + if len(markerList)==0: + debug(0, "File missing any POINT LABELS marker list. Making defaults") + #I guess just make cloud of empty.xxx + if len(markerList)XYZ_LIMIT or abs(myy)>XYZ_LIMIT or abs(myz)>XYZ_LIMIT: + err+=1 + if err>100: + debug(0, "Warning: 100 data points for markers seem way out there") + debug(0, "data read: (%i, %i, %i)" %(x,y,z)) + debug(0, "Consider revising Scale %0.2f" % Scale) + debug(0, "which now givs coordinates: (%i, %i, %i)" %(x*Scale,y*Scale,z*Scale)) + err=-0 + if abs(myx)>XYZ_LIMIT: myx= XYZ_LIMIT*myx/abs(myx) #preserve sign + if abs(myy)>XYZ_LIMIT: myy= XYZ_LIMIT*myy/abs(myy) #preserve sign + if abs(myz)>XYZ_LIMIT: myz= XYZ_LIMIT*myz/abs(myz) #preserve sign + Markers[i][j].x = myx + Markers[i][j].y = myy + Markers[i][j].z = myz + + a,ptr_read = parseFloat(content, ptr_read, proctype) + a = int(a) + highbyte = int(a/256) + lowbyte=a-highbyte*256 + CameraInfo[i][j] = highbyte + ResidualError[i][j] = lowbyte*abs(Scale) + #Monitor marker location to ensure data block is being parsed properly + if j==0: debug(90,"Frame %i loc of %s: (%i, %i, %i)" % (i,markerList[j],myx,myy,myz)) + if i==0: debug(50, "Initial loc of %s: (%i, %i, %i)" % (markerList[j],myx,myy,myz)) + + ptr_read+=residuals #skip over the following + #for j in range (NanalogFramesPerVideoFrame): + # for k in range(NanalogChannels): + # val, content = getNumber(content, 2) + # AnalogSignals[j+NanalogFramesPerVideoFrame*(i)][k]=val #??? i-1 + #else + # for i=1:NvideoFrames + # for j=1:Nmarkers + # Markers(i,j,1:3)=fread(fid,3,'int16')'.*Scale; + # ResidualError(i,j)=fread(fid,1,'int8'); + # CameraInfo(i,j)=fread(fid,1,'int8'); + # end + # waitbar(i/NvideoFrames) + # for j=1:NanalogFramesPerVideoFrame, + # AnalogSignals(j+NanalogFramesPerVideoFrame*(i-1),1:NanalogChannels)=... + # fread(fid,NanalogChannels,'int16')'; + # end + # end + #end + + else: #Scale is positive, but should be <1 to scale down, like 0.05 + two16= -2**16 + if len(content) < NvideoFrames*(Nmarkers*(6+2)+residuals): + error("%i bytes is not enough data for |%i frames|%i markers|%i residual" %(len(content),NvideoFrames,Nmarkers,residuals)) + #Note: I really tried to optimize this loop, since it was taking hours to process + for i in range(NvideoFrames): + if i==0: start=sys.time() + elif i==10: + tmp=(sys.time()-start)*NvideoFrames/600 + debug(0,"%i minutes remaining..." % tmp) + else: print "%i percent complete. On Frame %i Points procesed: %i\r" % (i*100/NvideoFrames,i,i*Nmarkers), + + for j in range(Nmarkers): + #x, content = getNumber(content,2) + # this is old skool signed int, not but not a short. + x = ord(content[ptr_read+0]) + (ord(content[ptr_read+1])<<8) + if x>32768: x+=two16 + y = ord(content[ptr_read+2]) + (ord(content[ptr_read+3])<<8) + if y>32768: y+=two16 + z = ord(content[ptr_read+4]) + (ord(content[ptr_read+5])<<8) + if z>32768: z+=two16 + +## +## x = ord(content[ptr_read]) + ord(content[ptr_read+1])*(2**8) +## ptr_read+=2 +## if x > 32768: +## x=-(2**16)+(x) +## #y, content = getNumber(content,2) +## y = ord(content[ptr_read]) + ord(content[ptr_read+1])*(2**8) +## ptr_read+=2 +## if y > 32768: +## y=-(2**16)+(y) +## #z, content = getNumber(content,2) +## z = ord(content[ptr_read]) + ord(content[ptr_read+1])*(2**8) +## ptr_read+=2 +## if z > 32768: +## z=-(2**16)+(z) +## +## print "(%i=%i, %i=%i, %i=%i)" %(x,myx,y,myy,z,myz) + + # for integers, I changed Scale above to avoid getting impossible numbers + Markers[i][j].x = x*Scale + Markers[i][j].y = y*Scale + Markers[i][j].z = z*Scale + +## ResidualError[i][j], content = getNumber(content, 1) +## CameraInfo[i][j], content = getNumber(content, 1) + #try to improve performance by: + ResidualError[i][j]= ord(content[ptr_read+6]) + CameraInfo[i][j]= ord(content[ptr_read+7]) + + content= content[ptr_read+8:] + ptr_read=0 + + if j==0: debug(100,"Frame %i loc of %s: %s" % (i,markerList[j],Markers[i][j])) + if i==0: debug(50, "Initial loc of %s: (%s)" % (markerList[j],Markers[i][j])) + + #for j in range (NanalogFramesPerVideoFrame): + # for k in range(NanalogChannels): + # val, content = getNumber(content, 2) + #AnalogSignals(j+NanalogFramesPerVideoFrame*(i-1),1:NanalogChannels)=val + ptr_read= residuals # skip over the above + print "\ndone with file." + fid.close() + + cloud= makeCloud(Nmarkers,markerList,StartFrame,EndFrame,Markers) + + setupAnim(StartFrame, EndFrame,VideoFrameRate) + + debug(10, "**************************") + debug(00, "**** Making %i Armatures" % len(subjects)) + debug(10, "**************************") + for i in range(len(subjects)): + marker_set= marker_subjects[i] + success=False + if len(marker_set)>0: + for trymark in MARKER_SETS: + if trymark[0:len(marker_set)]==marker_set: + marker_set=trymark + success=True + if success: + debug(0, "Armature for %s will be put on layers %s" % (subjects[i],LAYERS_ARMOB)) + debug(0, " based on an markers beginning with %s" % prefixes[i]) + ob= make_arm(subjects[i],prefixes[i],markerList,cloud,marker_set) + else: + debug(00, "Presently, this program can automatically create a constrained armature for marker sets %s" % MARKER_SETS) + debug(00, "%s uses an unknown marker set %s" % (subjects[i],marker_set)) + debug(10, "Have a nice day! If you figure out an armature node system for this cloud, please add it to the program.") + + debug(10, "**************************") + debug(00, "**** Conclusion") + minmax=[0,0,0,0,0,0] + for i in range(NvideoFrames): + for j in range(Nmarkers): + if minmax[0]>Markers[i][j].x: minmax[0]=Markers[i][j].x + if minmax[1]>Markers[i][j].y: minmax[1]=Markers[i][j].y + if minmax[2]>Markers[i][j].z: minmax[2]=Markers[i][j].z + if minmax[3]flag= chan->flag; con= chan->constraints.first; - for(pcon= pchan->constraints.first; pcon; pcon= pcon->next) { + for(pcon= pchan->constraints.first; pcon; pcon= pcon->next, con= con->next) { pcon->enforce= con->enforce; pcon->headtail= con->headtail; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index b2557c9c07e..c73279746fb 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -857,8 +857,8 @@ void BKE_add_image_extension(char *string, int imtype) extension= ".bmp"; } else if(G.have_libtiff && (imtype==R_TIFF)) { - if(!BLI_testextensie(string, ".tif")) - extension= ".tif"; + if(!BLI_testextensie(string, ".tif") && + !BLI_testextensie(string, ".tiff")) extension= ".tif"; } #ifdef WITH_OPENEXR else if( ELEM(imtype, R_OPENEXR, R_MULTILAYER)) { diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 321d4f1d37e..59eb3837aab 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1859,7 +1859,7 @@ void set_icu_vars(IpoCurve *icu) /* yafray: aperture & focal distance params */ switch(icu->adrcode) { case CAM_LENS: - icu->ymin= 5.0; + icu->ymin= 1.0; icu->ymax= 1000.0; break; case CAM_STA: diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 561a97d8646..d3cc451c6fc 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -1424,10 +1424,10 @@ void vertgroup_flip_name (char *name, int strip_number) } static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, - Object *ob, - DerivedMesh *dm, - int initFlags, - int axis) + Object *ob, + DerivedMesh *dm, + int initFlags, + int axis) { int i; float tolerance = mmd->tolerance; @@ -1436,7 +1436,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, int maxVerts = dm->getNumVerts(dm); int maxEdges = dm->getNumEdges(dm); int maxFaces = dm->getNumFaces(dm); - int vector_size, j, a, b; + int vector_size=0, j, a, b; bDeformGroup *def, *defb; bDeformGroup **vector_def = NULL; int (*indexMap)[2]; @@ -1465,7 +1465,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, if (mmd->mirror_ob) { float obinv[4][4]; - + Mat4Invert(obinv, mmd->mirror_ob->obmat); Mat4MulMat4(mtx, ob->obmat, obinv); Mat4Invert(imtx, mtx); @@ -1476,16 +1476,16 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, MVert *mv = CDDM_get_vert(result, numVerts); int isShared; float co[3]; - + dm->getVert(dm, i, &inMV); - + VecCopyf(co, inMV.co); - + if (mmd->mirror_ob) { VecMat4MulVecfl(co, mtx, co); } isShared = ABS(co[axis])<=tolerance; - + /* Because the topology result (# of vertices) must be the same if * the mesh data is overridden by vertex cos, have to calc sharedness * based on original coordinates. This is why we test before copy. @@ -1493,10 +1493,10 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, DM_copy_vert_data(dm, result, i, numVerts, 1); *mv = inMV; numVerts++; - + indexMap[i][0] = numVerts - 1; indexMap[i][1] = !isShared; - + if(isShared) { co[axis] = 0; if (mmd->mirror_ob) { @@ -1508,33 +1508,33 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, } else { MVert *mv2 = CDDM_get_vert(result, numVerts); MDeformVert *dvert = NULL; - + DM_copy_vert_data(dm, result, i, numVerts, 1); *mv2 = *mv; - + co[axis] = -co[axis]; if (mmd->mirror_ob) { VecMat4MulVecfl(co, imtx, co); } VecCopyf(mv2->co, co); - + if (mmd->flag & MOD_MIR_VGROUP){ dvert = DM_get_vert_data(result, numVerts, CD_MDEFORMVERT); - + if (dvert) { for(j = 0; j < dvert[0].totweight; ++j) { char tmpname[32]; - + if(dvert->dw[j].def_nr < 0 || dvert->dw[j].def_nr >= vector_size) continue; - + def = vector_def[dvert->dw[j].def_nr]; strcpy(tmpname, def->name); vertgroup_flip_name(tmpname,0); - + for(b = 0, defb = ob->defbase.first; defb; defb = defb->next, b++) { @@ -1547,7 +1547,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, } } } - + numVerts++; } } @@ -1555,25 +1555,25 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, for(i = 0; i < maxEdges; i++) { MEdge inMED; MEdge *med = CDDM_get_edge(result, numEdges); - + dm->getEdge(dm, i, &inMED); - + DM_copy_edge_data(dm, result, i, numEdges, 1); *med = inMED; numEdges++; - + med->v1 = indexMap[inMED.v1][0]; med->v2 = indexMap[inMED.v2][0]; if(initFlags) med->flag |= ME_EDGEDRAW | ME_EDGERENDER; - + if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) { MEdge *med2 = CDDM_get_edge(result, numEdges); - + DM_copy_edge_data(dm, result, i, numEdges, 1); *med2 = *med; numEdges++; - + med2->v1 += indexMap[inMED.v1][1]; med2->v2 += indexMap[inMED.v2][1]; } @@ -1582,13 +1582,13 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, for(i = 0; i < maxFaces; i++) { MFace inMF; MFace *mf = CDDM_get_face(result, numFaces); - + dm->getFace(dm, i, &inMF); - + DM_copy_face_data(dm, result, i, numFaces, 1); *mf = inMF; numFaces++; - + mf->v1 = indexMap[inMF.v1][0]; mf->v2 = indexMap[inMF.v2][0]; mf->v3 = indexMap[inMF.v3][0]; @@ -1600,15 +1600,15 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, || (mf->v4 && indexMap[inMF.v4][1])) { MFace *mf2 = CDDM_get_face(result, numFaces); static int corner_indices[4] = {2, 1, 0, 3}; - + DM_copy_face_data(dm, result, i, numFaces, 1); *mf2 = *mf; - + mf2->v1 += indexMap[inMF.v1][1]; mf2->v2 += indexMap[inMF.v2][1]; mf2->v3 += indexMap[inMF.v3][1]; if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1]; - + /* mirror UVs if enabled */ if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) { MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE); @@ -1622,14 +1622,14 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, } } } - + /* Flip face normal */ SWAP(int, mf2->v1, mf2->v3); DM_swap_face_data(result, numFaces, corner_indices); - + test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3); numFaces++; - } + } } if (vector_def) MEM_freeN(vector_def); @@ -1644,8 +1644,8 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, } static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, - Object *ob, DerivedMesh *dm, - int initFlags) + Object *ob, DerivedMesh *dm, + int initFlags) { DerivedMesh *result = dm; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index f06ef221795..458171cc232 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2596,6 +2596,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo for(ec= lb->first; ec; ec= ec->next) { PartDeflect *pd= ec->ob->pd; + co = NULL; if(ec->type==PSYS_EC_EFFECTOR && pd->forcefield==PFIELD_GUIDE && ec->ob->type==OB_CURVE && part->phystype!=PART_PHYS_BOIDS) { diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 92544f19721..16ca5d7542d 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -465,6 +465,9 @@ void init_actuator(bActuator *act) case ACT_PARENT: act->data = MEM_callocN(sizeof( bParentActuator ), "parent act"); break; + case ACT_STATE: + act->data = MEM_callocN(sizeof( bStateActuator ), "state act"); + break; default: ; /* this is very severe... I cannot make any memory for this */ /* logic brick... */ diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 876547042dc..53b7bb975a3 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -942,7 +942,8 @@ char *txt_to_buf (Text *text) if (!text) return NULL; if (!text->curl) return NULL; if (!text->sell) return NULL; - + if (!text->lines.first) return NULL; + linef= text->lines.first; charf= 0; diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 4d277cf98e1..4fa880c36d1 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -374,6 +374,7 @@ void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3 void tubemap(float x, float y, float z, float *u, float *v); void spheremap(float x, float y, float z, float *u, float *v); +int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3]); int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 322a9e6fd02..2084ab3da5f 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -4032,6 +4032,74 @@ int AxialLineIntersectsTriangle(int axis, float p1[3], float p2[3], float v0[3], return 1; } +/* Returns the number of point of interests + * 0 - lines are colinear + * 1 - lines are coplanar, i1 is set to intersection + * 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively + * */ +int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3]) +{ + float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3]; + float d; + + VecSubf(c, v3, v1); + VecSubf(a, v2, v1); + VecSubf(b, v4, v3); + + VecCopyf(dir1, a); + Normalize(dir1); + VecCopyf(dir2, b); + Normalize(dir2); + d = Inpf(dir1, dir2); + if (d == 1.0f || d == -1.0f) { + /* colinear */ + return 0; + } + + Crossf(ab, a, b); + d = Inpf(c, ab); + + /* test if the two lines are coplanar */ + if (d > -0.000001f && d < 0.000001f) { + Crossf(cb, c, b); + + VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab)); + VecAddf(i1, v1, a); + VecCopyf(i2, i1); + + return 1; /* one intersection only */ + } + /* if not */ + else { + float n[3], t[3]; + float v3t[3], v4t[3]; + VecSubf(t, v1, v3); + + /* offset between both plane where the lines lies */ + Crossf(n, a, b); + Projf(t, t, n); + + /* for the first line, offset the second line until it is coplanar */ + VecAddf(v3t, v3, t); + VecAddf(v4t, v4, t); + + VecSubf(c, v3t, v1); + VecSubf(a, v2, v1); + VecSubf(b, v4t, v3); + + Crossf(ab, a, b); + Crossf(cb, c, b); + + VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab)); + VecAddf(i1, v1, a); + + /* for the second line, just substract the offset from the first intersection point */ + VecSubf(i2, i1, t); + + return 2; /* two nearest points */ + } +} + int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]) { return (min1[0]data; parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob); } + else if(act->type==ACT_STATE) { + /* bStateActuator *statea = act->data; */ + } act= act->next; } @@ -3307,11 +3310,19 @@ static void direct_link_object(FileData *fd, Object *ob) direct_link_constraints(fd, &ob->constraints); link_glob_list(fd, &ob->controllers); + if (ob->init_state) { + /* if a known first state is specified, set it so that the game will start ok */ + ob->state = ob->init_state; + } else if (!ob->state) { + ob->state = 1; + } cont= ob->controllers.first; while(cont) { cont->data= newdataadr(fd, cont->data); cont->links= newdataadr(fd, cont->links); test_pointer_array(fd, (void **)&cont->links); + if (cont->state_mask == 0) + cont->state_mask = 1; cont= cont->next; } @@ -7635,6 +7646,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 2595b95bbf0..9f28e13ff7b 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -715,6 +715,9 @@ static void write_actuators(WriteData *wd, ListBase *lb) case ACT_PARENT: writestruct(wd, DATA, "bParentActuator", 1, act->data); break; + case ACT_STATE: + writestruct(wd, DATA, "bStateActuator", 1, act->data); + break; default: ; /* error: don't know how to write this file */ } diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 94203bab447..73ef83393b0 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -149,6 +149,7 @@ typedef enum { #define IB_zbuffloat (1 << 16) #define IB_multilayer (1 << 17) #define IB_imginfo (1 << 18) +#define IB_animdeinterlace (1 << 19) /* * The bit flag is stored in the ImBuf.ftype variable. diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index 71d35949833..7dc1f966b71 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -183,8 +183,9 @@ struct anim { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; - AVFrame *pFrameRGB; AVFrame *pFrame; + AVFrame *pFrameRGB; + AVFrame *pFrameDeinterlaced; struct SwsContext *img_convert_ctx; int videoStream; #endif diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c index 87d67f5263b..720f5b0f7c8 100644 --- a/source/blender/imbuf/intern/anim.c +++ b/source/blender/imbuf/intern/anim.c @@ -600,6 +600,7 @@ static int startffmpeg(struct anim * anim) { anim->videoStream = videoStream; anim->pFrame = avcodec_alloc_frame(); + anim->pFrameDeinterlaced = avcodec_alloc_frame(); anim->pFrameRGB = avcodec_alloc_frame(); if (avpicture_get_size(PIX_FMT_BGR32, anim->x, anim->y) @@ -609,10 +610,20 @@ static int startffmpeg(struct anim * anim) { avcodec_close(anim->pCodecCtx); av_close_input_file(anim->pFormatCtx); av_free(anim->pFrameRGB); + av_free(anim->pFrameDeinterlaced); av_free(anim->pFrame); return -1; } + if (anim->ib_flags & IB_animdeinterlace) { + avpicture_fill((AVPicture*) anim->pFrameDeinterlaced, + MEM_callocN(avpicture_get_size( + anim->pCodecCtx->pix_fmt, + anim->x, anim->y), + "ffmpeg deinterlace"), + anim->pCodecCtx->pix_fmt, anim->x, anim->y); + } + if (pCodecCtx->has_b_frames) { anim->preseek = 25; /* FIXME: detect gopsize ... */ } else { @@ -638,12 +649,13 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { AVPacket packet; int64_t pts_to_search = 0; int pos_found = 1; + int filter_y = 0; if (anim == 0) return (0); ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect, 0); - avpicture_fill((AVPicture *)anim->pFrameRGB, + avpicture_fill((AVPicture*) anim->pFrameRGB, (unsigned char*) ibuf->rect, PIX_FMT_BGR32, anim->x, anim->y); @@ -722,6 +734,32 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { } if(frameFinished && pos_found == 1) { + AVFrame * input = anim->pFrame; + + /* This means the data wasnt read properly, + this check stops crashing */ + if (input->data[0]==0 && input->data[1]==0 + && input->data[2]==0 && input->data[3]==0){ + av_free_packet(&packet); + break; + } + + if (anim->ib_flags & IB_animdeinterlace) { + if (avpicture_deinterlace( + (AVPicture*) + anim->pFrameDeinterlaced, + (const AVPicture*) + anim->pFrame, + anim->pCodecCtx->pix_fmt, + anim->pCodecCtx->width, + anim->pCodecCtx->height) + < 0) { + filter_y = 1; + } else { + input = anim->pFrameDeinterlaced; + } + } + if (G.order == B_ENDIAN) { int * dstStride = anim->pFrameRGB->linesize; @@ -735,8 +773,8 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { unsigned char* top; sws_scale(anim->img_convert_ctx, - anim->pFrame->data, - anim->pFrame->linesize, + input->data, + input->linesize, 0, anim->pCodecCtx->height, dst2, @@ -793,27 +831,25 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { int i; unsigned char* r; - /* This means the data wasnt read properly, this check stops crashing */ - if (anim->pFrame->data[0]!=0 || anim->pFrame->data[1]!=0 || anim->pFrame->data[2]!=0 || anim->pFrame->data[3]!=0) { - sws_scale(anim->img_convert_ctx, - anim->pFrame->data, - anim->pFrame->linesize, - 0, - anim->pCodecCtx->height, - dst2, - dstStride2); + sws_scale(anim->img_convert_ctx, + input->data, + input->linesize, + 0, + anim->pCodecCtx->height, + dst2, + dstStride2); - /* workaround: sws_scale - sets alpha = 0... */ + /* workaround: sws_scale + sets alpha = 0... */ - r = (unsigned char*) ibuf->rect; - - for (i = 0; i < ibuf->x * ibuf->y;i++){ - r[3] = 0xff; - r+=4; - } + r = (unsigned char*) ibuf->rect; + + for (i = 0; i < ibuf->x * ibuf->y;i++){ + r[3] = 0xff; + r+=4; } + av_free_packet(&packet); break; } @@ -823,6 +859,10 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { av_free_packet(&packet); } + if (filter_y && ibuf) { + IMB_filtery(ibuf); + } + return(ibuf); } @@ -834,6 +874,11 @@ static void free_anim_ffmpeg(struct anim * anim) { av_close_input_file(anim->pFormatCtx); av_free(anim->pFrameRGB); av_free(anim->pFrame); + + if (anim->ib_flags & IB_animdeinterlace) { + MEM_freeN(anim->pFrameDeinterlaced->data[0]); + } + av_free(anim->pFrameDeinterlaced); sws_freeContext(anim->img_convert_ctx); } anim->duration = 0; @@ -983,6 +1028,7 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) { char head[256], tail[256]; unsigned short digits; int pic; + int filter_y = (anim->ib_flags & IB_animdeinterlace); if (anim == NULL) return(0); @@ -1040,6 +1086,7 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) { case ANIM_FFMPEG: ibuf = ffmpeg_fetchibuf(anim, position); if (ibuf) anim->curposition = position; + filter_y = 0; /* done internally */ break; #endif #ifdef WITH_REDCODE @@ -1052,6 +1099,7 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) { if (ibuf) { if (anim->ib_flags & IB_ttob) IMB_flipy(ibuf); + if (filter_y) IMB_filtery(ibuf); sprintf(ibuf->name, "%s.%04d", anim->name, anim->curposition + 1); } diff --git a/source/blender/include/BIF_butspace.h b/source/blender/include/BIF_butspace.h index cbbd8013c82..f0b37814947 100644 --- a/source/blender/include/BIF_butspace.h +++ b/source/blender/include/BIF_butspace.h @@ -99,6 +99,8 @@ extern void validate_editbonebutton_cb(void *bonev, void *namev); #define BUTS_ACT_SEL 64 #define BUTS_ACT_ACT 128 #define BUTS_ACT_LINK 256 +#define BUTS_SENS_STATE 512 +#define BUTS_ACT_STATE 1024 /* buttons grid */ diff --git a/source/blender/include/BIF_interface.h b/source/blender/include/BIF_interface.h index fbd4e4ecd91..3da4466d4d3 100644 --- a/source/blender/include/BIF_interface.h +++ b/source/blender/include/BIF_interface.h @@ -185,6 +185,7 @@ void uiDrawBlock(struct uiBlock *block); void uiGetMouse(int win, short *adr); void uiComposeLinks(uiBlock *block); void uiSetButLock(int val, char *lockstr); +uiBut *uiFindInlink(uiBlock *block, void *poin); void uiClearButLock(void); int uiDoBlocks(struct ListBase *lb, int event, int movemouse_quit); void uiSetCurFont(uiBlock *block, int index); diff --git a/source/blender/include/BIF_oops.h b/source/blender/include/BIF_oops.h index adeac4f3871..2375a918d0e 100644 --- a/source/blender/include/BIF_oops.h +++ b/source/blender/include/BIF_oops.h @@ -43,6 +43,8 @@ struct Camera; struct Texture; struct Lattice; struct bArmature; +struct Tex; + void add_curve_oopslinks(struct Curve *cu, struct Oops *oops, short flag); void add_from_link(struct Oops *from, struct Oops *oops); void add_material_oopslinks(struct Material *ma, struct Oops *oops, short flag); diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 7571d64be91..c0542e3f34c 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -52,6 +52,8 @@ struct Image; #define BUTS_ACT_SEL 64 #define BUTS_ACT_ACT 128 #define BUTS_ACT_LINK 256 +#define BUTS_SENS_STATE 512 +#define BUTS_ACT_STATE 1024 /* internal */ @@ -583,6 +585,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_SETACTOR 2715 #define B_SETMAINACTOR 2716 #define B_SETDYNA 2717 +#define B_SET_STATE_BIT 2718 +#define B_INIT_STATE_BIT 2719 /* *********************** */ #define B_FPAINTBUTS 2900 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 7d497dc05ec..4e3b80134f9 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -102,9 +102,9 @@ typedef struct TransCon { /* Apply function pointer for linear vectorial transformation */ /* The last three parameters are pointers to the in/out/printable vectors */ void (*applySize)(struct TransInfo *, struct TransData *, float [3][3]); - /* Apply function pointer for rotation transformation (prototype will change */ - void (*applyRot)(struct TransInfo *, struct TransData *, float [3]); - /* Apply function pointer for rotation transformation (prototype will change */ + /* Apply function pointer for size transformation */ + void (*applyRot)(struct TransInfo *, struct TransData *, float [3], float *); + /* Apply function pointer for rotation transformation */ } TransCon; typedef struct TransDataIpokey { diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index a326f5b01d6..51f03a676e4 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -50,6 +50,7 @@ typedef struct bActionActuator { short type, flag; /* Playback type */ int sta, end; /* Start & End frames */ char name[32]; /* For property-driven playback */ + char frameProp[32]; /* Set this property to the actions current frame */ int blendin; /* Number of frames of blending */ short priority; /* Execution priority */ short strideaxis; /* Displacement axis */ @@ -80,7 +81,7 @@ typedef struct bEditObjectActuator { char name[32]; float linVelocity[3]; /* initial lin. velocity on creation */ short localflag; /* flag for the lin. vel: apply locally */ - short pad; + short dyn_operation; } bEditObjectActuator; typedef struct bSceneActuator { @@ -97,7 +98,8 @@ typedef struct bPropertyActuator { } bPropertyActuator; typedef struct bObjectActuator { - int flag, type; + short flag, type; + int damping; float forceloc[3], forcerot[3]; float loc[3], rot[3]; float dloc[3], drot[3]; @@ -190,11 +192,13 @@ typedef struct bVisibilityActuator { } bVisibilityActuator; typedef struct bTwoDFilterActuator{ - char pad[4]; - /* Tells what type of 2D Filter*/ + char pad[2]; + /* bitwise flag for enabling or disabling depth(bit 0) and luminance(bit 1) */ + short texture_flag; + /* Tells what type of 2D Filter */ short type; /* (flag == 0) means 2D filter is activate and - (flag != 0) means 2D filter is inactive*/ + (flag != 0) means 2D filter is inactive */ short flag; int int_arg; /* a float argument */ @@ -208,6 +212,11 @@ typedef struct bParentActuator { struct Object *ob; } bParentActuator; +typedef struct bStateActuator { + int type; /* 0=Set, 1=Add, 2=Rem, 3=Chg */ + unsigned int mask; /* the bits to change */ +} bStateActuator; + typedef struct bActuator { struct bActuator *next, *prev, *mynew; short type; @@ -246,6 +255,7 @@ typedef struct FreeCamera { #define ACT_ANG_VEL_LOCAL 32 //#define ACT_ADD_LIN_VEL_LOCAL 64 #define ACT_ADD_LIN_VEL 64 +#define ACT_CLAMP_VEL 128 #define ACT_OBJECT_FORCE 0 #define ACT_OBJECT_TORQUE 1 @@ -279,11 +289,14 @@ typedef struct FreeCamera { #define ACT_2DFILTER 19 #define ACT_PARENT 20 #define ACT_SHAPEACTION 21 +#define ACT_STATE 22 /* actuator flag */ #define ACT_SHOW 1 #define ACT_DEL 2 #define ACT_NEW 4 +#define ACT_LINKED 8 +#define ACT_VISIBLE 16 /* link codes */ #define LINK_SENSOR 0 @@ -349,10 +362,11 @@ typedef struct FreeCamera { /* editObjectActuator->type */ #define ACT_EDOB_ADD_OBJECT 0 #define ACT_EDOB_END_OBJECT 1 -#define ACT_EDOB_REPLACE_MESH 2 +#define ACT_EDOB_REPLACE_MESH 2 #define ACT_EDOB_TRACK_TO 3 -#define ACT_EDOB_MAKE_CHILD 4 -#define ACT_EDOB_END_CHILD 5 +#define ACT_EDOB_DYNAMICS 4 + + /* editObjectActuator->flag */ #define ACT_TRACK_3D 1 diff --git a/source/blender/makesdna/DNA_controller_types.h b/source/blender/makesdna/DNA_controller_types.h index 95c9b0d0cf7..376f95b0145 100644 --- a/source/blender/makesdna/DNA_controller_types.h +++ b/source/blender/makesdna/DNA_controller_types.h @@ -57,7 +57,7 @@ typedef struct bController { struct bSensor **slinks; short val, valo; - int pad5; + unsigned int state_mask; } bController; @@ -66,11 +66,16 @@ typedef struct bController { #define CONT_LOGIC_OR 1 #define CONT_EXPRESSION 2 #define CONT_PYTHON 3 +#define CONT_LOGIC_NAND 4 +#define CONT_LOGIC_NOR 5 +#define CONT_LOGIC_XOR 6 +#define CONT_LOGIC_XNOR 7 /* controller->flag */ #define CONT_SHOW 1 #define CONT_DEL 2 #define CONT_NEW 4 +#define CONT_MASK 8 #endif diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 83168248b9a..c4e8cb4925b 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -216,7 +216,9 @@ typedef struct Object { struct DerivedMesh *derivedDeform, *derivedFinal; int lastDataMask; /* the custom data layer mask that was last used to calculate derivedDeform and derivedFinal */ - int pad; + unsigned int state; /* bit masks of game controllers that are active */ + unsigned int init_state; /* bit masks of initial state as recorded by the users */ + int pad2; /*#ifdef WITH_VERSE*/ void *vnode; /* pointer at object VerseNode */ @@ -440,6 +442,8 @@ extern Object workob; #define OB_ADDCONT 512 #define OB_ADDACT 1024 #define OB_SHOWCONT 2048 +#define OB_SETSTBIT 4096 +#define OB_INITSTBIT 8192 /* ob->restrictflag */ #define OB_RESTRICT_VIEW 1 diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index 90e2b8f9f41..ae7b92bb06c 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -144,7 +144,7 @@ typedef struct bSensor { /* just add here, to avoid align errors... */ short invert; /* Whether or not to invert the output. */ - short freq2; /* The negative pulsing frequency? Not used anymore... */ + short level; /* Whether the sensor is level base (edge by default) */ int pad; } bSensor; @@ -202,6 +202,7 @@ typedef struct bJoystickSensor { #define SENS_DEL 2 #define SENS_NEW 4 #define SENS_NOT 8 +#define SENS_VISIBLE 16 /* sensor->pulse */ #define SENS_PULSE_CONT 0 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index acc1651e9fa..3de5b0ff5ba 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -310,7 +310,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_DUP_ACT (1 << 10) /* gameflags */ -#define USER_VERTEX_ARRAYS 1 +#define USER_DEPRECATED_FLAG 1 #define USER_DISABLE_SOUND 2 #define USER_DISABLE_MIPMAP 4 diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_math.c b/source/blender/nodes/intern/CMP_nodes/CMP_math.c index d00ce18a44f..421c1343df7 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_math.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_math.c @@ -57,7 +57,7 @@ static void do_math(bNode *node, float *out, float *in, float *in2) break; case 3: /* Divide */ { - if(in[1]==0) /* We don't want to divide by zero. */ + if(in2[0]==0) /* We don't want to divide by zero. */ out[0]= 0.0; else out[0]= in[0] / in2[0]; diff --git a/source/blender/python/api2_2x/CurNurb.c b/source/blender/python/api2_2x/CurNurb.c index 174b5fb08dc..b2120bd63c6 100644 --- a/source/blender/python/api2_2x/CurNurb.c +++ b/source/blender/python/api2_2x/CurNurb.c @@ -53,6 +53,8 @@ static int CurNurb_setFlagU( BPy_CurNurb * self, PyObject * args ); static PyObject *CurNurb_getFlagV( BPy_CurNurb * self ); static PyObject *CurNurb_oldsetFlagV( BPy_CurNurb * self, PyObject * args ); static int CurNurb_setFlagV( BPy_CurNurb * self, PyObject * args ); +static PyObject *CurNurb_getOrderU( BPy_CurNurb * self ); +static int CurNurb_setOrderU( BPy_CurNurb * self, PyObject * args ); static PyObject *CurNurb_getType( BPy_CurNurb * self ); static PyObject *CurNurb_oldsetType( BPy_CurNurb * self, PyObject * args ); static int CurNurb_setType( BPy_CurNurb * self, PyObject * args ); @@ -176,6 +178,9 @@ static PyGetSetDef BPy_CurNurb_getseters[] = { (getter)CurNurb_getFlagV, (setter)CurNurb_setFlagV, "The knot type in the V direction", NULL}, + {"orderU", + (getter)CurNurb_getOrderU, (setter)CurNurb_setOrderU, + "order setting for U direction", NULL}, {"type", (getter)CurNurb_getType, (setter)CurNurb_setType, "The curve type (poly: bezier, or NURBS)", @@ -710,6 +715,35 @@ static int CurNurb_setFlagV( BPy_CurNurb * self, PyObject * args ) return 0; } +static PyObject *CurNurb_getOrderU( BPy_CurNurb * self ) +{ + return PyInt_FromLong( ( long ) self->nurb->orderu ); +} + +static int CurNurb_setOrderU( BPy_CurNurb * self, PyObject * args ) +{ + int order; + + args = PyNumber_Int( args ); + if( !args ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected integer argument" ); + + order = ( int )PyInt_AS_LONG( args ); + Py_DECREF( args ); + + if( order < 2 ) order = 2; + else if( order > 6 ) order = 6; + + if( self->nurb->pntsu < order ) + order = self->nurb->pntsu; + + self->nurb->orderu = (short)order; + makeknots( self->nurb, 1, self->nurb->flagu >> 1 ); + + return 0; +} + /* * CurNurb_getIter * diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index ef3174ac4ed..53d25a6429d 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -1520,12 +1520,11 @@ static PyObject *Lamp_oldsetType( BPy_Lamp * self, PyObject * value ) char *type = PyString_AsString(value); PyObject *arg, *error; - /* parse string argument */ - - if( !value ) - return ( EXPP_ReturnPyObjError( PyExc_TypeError, - "expected string argument" ) ); - + /* parse string argument */ + if( !type ) + return EXPP_ReturnPyObjError ( PyExc_TypeError, + "expected string argument" ); + /* check for valid arguments, set type accordingly */ if( !strcmp( type, "Lamp" ) ) @@ -1546,7 +1545,7 @@ static PyObject *Lamp_oldsetType( BPy_Lamp * self, PyObject * value ) /* build tuple, call wrapper */ - arg = Py_BuildValue( "(i)", type ); + arg = Py_BuildValue( "(i)", self->lamp->type ); error = EXPP_setterWrapper ( (void *)self, arg, (setter)Lamp_setType ); Py_DECREF ( arg ); return error; diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c index 87ac3e3e6ba..85c56a61628 100644 --- a/source/blender/python/api2_2x/Mathutils.c +++ b/source/blender/python/api2_2x/Mathutils.c @@ -1452,8 +1452,8 @@ PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args ) "vectors must be of the same size\n" ) ); if( vec1->size == 3 || vec1->size == 2) { - float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3]; - float d; + int result; + if (vec1->size == 3) { VECCOPY(v1, vec1->vec); VECCOPY(v2, vec2->vec); @@ -1477,63 +1477,19 @@ PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args ) v4[1] = vec4->vec[1]; v4[2] = 0.0f; } + + result = LineIntersectLine(v1, v2, v3, v4, i1, i2); - VecSubf(c, v3, v1); - VecSubf(a, v2, v1); - VecSubf(b, v4, v3); - - VECCOPY(dir1, a); - Normalize(dir1); - VECCOPY(dir2, b); - Normalize(dir2); - d = Inpf(dir1, dir2); - if (d == 1.0f || d == -1.0f) { + if (result == 0) { /* colinear */ return EXPP_incr_ret( Py_None ); } - - Crossf(ab, a, b); - d = Inpf(c, ab); - - /* test if the two lines are coplanar */ - if (d > -0.000001f && d < 0.000001f) { - Crossf(cb, c, b); - - VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab)); - VecAddf(i1, v1, a); - VECCOPY(i2, i1); - } - /* if not */ else { - float n[3], t[3]; - VecSubf(t, v1, v3); - - /* offset between both plane where the lines lies */ - Crossf(n, a, b); - Projf(t, t, n); - - /* for the first line, offset the second line until it is coplanar */ - VecAddf(v3, v3, t); - VecAddf(v4, v4, t); - - VecSubf(c, v3, v1); - VecSubf(a, v2, v1); - VecSubf(b, v4, v3); - - Crossf(ab, a, b); - Crossf(cb, c, b); - - VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab)); - VecAddf(i1, v1, a); - - /* for the second line, just substract the offset from the first intersection point */ - VecSubf(i2, i1, t); + tuple = PyTuple_New( 2 ); + PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW) ); + PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW) ); + return tuple; } - - tuple = PyTuple_New( 2 ); - PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW) ); - PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW) ); - return tuple; } else { return ( EXPP_ReturnPyObjError( PyExc_TypeError, diff --git a/source/blender/python/api2_2x/doc/Curve.py b/source/blender/python/api2_2x/doc/Curve.py index ba8d6d21970..765921665cd 100644 --- a/source/blender/python/api2_2x/doc/Curve.py +++ b/source/blender/python/api2_2x/doc/Curve.py @@ -535,6 +535,8 @@ class CurNurb: @type flagU: int @ivar flagV: The CurNurb knot flag V. See L{setFlagU} for description. @type flagV: int + @ivar orderU: The CurNurb knot order U, for nurbs curves only, this is clamped by the number of points, so the orderU will never be greater. + @type orderU: int @ivar type: The type of the curve (Poly: 0, Bezier: 1, NURBS: 4) @type type: int @ivar knotsU: The knot vector in the U direction. The tuple will be empty diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index ebb52c49132..6a0af82b4d7 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2675,9 +2675,9 @@ void RE_set_max_threads(int threads) void RE_init_threadcount(Render *re) { - if ((re->r.mode & R_FIXED_THREADS)==0 || commandline_threads == 0) { /* Automatic threads */ + if(commandline_threads >= 1) { /* only set as an arg in background mode */ + re->r.threads= MIN2(commandline_threads, BLENDER_MAX_THREADS); + } else if ((re->r.mode & R_FIXED_THREADS)==0 || commandline_threads == 0) { /* Automatic threads */ re->r.threads = BLI_system_thread_count(); - } else if(commandline_threads >= 1 && commandline_threads<=BLENDER_MAX_THREADS) { - re->r.threads= commandline_threads; } } diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index a9261185f42..179a094a981 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -6311,7 +6311,7 @@ static void editing_panel_mesh_texface(void) uiDefButBitS(block, TOG, TF_TILES, B_REDR_3D_IMA, "Tiles", 660,160,60,19, &tf->mode, 0, 0, 0, 0, "Use tilemode for face"); uiDefButBitS(block, TOG, TF_LIGHT, REDRAWVIEW3D, "Light", 720,160,60,19, &tf->mode, 0, 0, 0, 0, "Use light for face"); uiDefButBitS(block, TOG, TF_INVISIBLE, REDRAWVIEW3D, "Invisible",780,160,60,19, &tf->mode, 0, 0, 0, 0, "Make face invisible"); - uiDefButBitS(block, TOG, TF_DYNAMIC, REDRAWVIEW3D, "Collision", 840,160,60,19, &tf->mode, 0, 0, 0, 0, "Use face for collision detection"); + uiDefButBitS(block, TOG, TF_DYNAMIC, REDRAWVIEW3D, "Collision", 840,160,60,19, &tf->mode, 0, 0, 0, 0, "Use face for collision and ray-sensor detection"); uiBlockBeginAlign(block); uiDefButBitS(block, TOG, TF_SHAREDCOL, REDRAWVIEW3D, "Shared", 600,135,60,19, &tf->mode, 0, 0, 0, 0, "Blend vertex colors across face when vertices are shared"); diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index b6877b2e2b7..4e5e8a605ee 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -88,6 +88,7 @@ #include "mydevice.h" #include "nla.h" /* For __NLA : Important, do not remove */ #include "butspace.h" // own module +#include "interface.h" /* internals */ void buttons_enji(uiBlock *, Object *); @@ -228,7 +229,7 @@ static void sca_move_sensor(void *datav, void *data2_unused) bSensor *sens_to_delete= datav; int val; Base *base; - bSensor *sens; + bSensor *sens, *tmp; val= pupmenu("Move up%x1|Move down %x2"); @@ -245,12 +246,24 @@ static void sca_move_sensor(void *datav, void *data2_unused) if(sens) { if( val==1 && sens->prev) { - BLI_remlink(&base->object->sensors, sens); - BLI_insertlinkbefore(&base->object->sensors, sens->prev, sens); + for (tmp=sens->prev; tmp; tmp=tmp->prev) { + if (tmp->flag & SENS_VISIBLE) + break; + } + if (tmp) { + BLI_remlink(&base->object->sensors, sens); + BLI_insertlinkbefore(&base->object->sensors, tmp, sens); + } } else if( val==2 && sens->next) { - BLI_remlink(&base->object->sensors, sens); - BLI_insertlink(&base->object->sensors, sens->next, sens); + for (tmp=sens->next; tmp; tmp=tmp->next) { + if (tmp->flag & SENS_VISIBLE) + break; + } + if (tmp) { + BLI_remlink(&base->object->sensors, sens); + BLI_insertlink(&base->object->sensors, tmp, sens); + } } BIF_undo_push("Move sensor"); allqueue(REDRAWBUTSLOGIC, 0); @@ -267,7 +280,7 @@ static void sca_move_controller(void *datav, void *data2_unused) bController *controller_to_del= datav; int val; Base *base; - bController *cont; + bController *cont, *tmp; val= pupmenu("Move up%x1|Move down %x2"); @@ -284,12 +297,27 @@ static void sca_move_controller(void *datav, void *data2_unused) if(cont) { if( val==1 && cont->prev) { - BLI_remlink(&base->object->controllers, cont); - BLI_insertlinkbefore(&base->object->controllers, cont->prev, cont); + /* locate the controller that has the same state mask but is earlier in the list */ + tmp = cont->prev; + while(tmp) { + if(tmp->state_mask & cont->state_mask) + break; + tmp = tmp->prev; + } + if (tmp) { + BLI_remlink(&base->object->controllers, cont); + BLI_insertlinkbefore(&base->object->controllers, tmp, cont); + } } else if( val==2 && cont->next) { + tmp = cont->next; + while(tmp) { + if(tmp->state_mask & cont->state_mask) + break; + tmp = tmp->next; + } BLI_remlink(&base->object->controllers, cont); - BLI_insertlink(&base->object->controllers, cont->next, cont); + BLI_insertlink(&base->object->controllers, tmp, cont); } BIF_undo_push("Move controller"); allqueue(REDRAWBUTSLOGIC, 0); @@ -306,7 +334,7 @@ static void sca_move_actuator(void *datav, void *data2_unused) bActuator *actuator_to_move= datav; int val; Base *base; - bActuator *act; + bActuator *act, *tmp; val= pupmenu("Move up%x1|Move down %x2"); @@ -323,12 +351,25 @@ static void sca_move_actuator(void *datav, void *data2_unused) if(act) { if( val==1 && act->prev) { - BLI_remlink(&base->object->actuators, act); - BLI_insertlinkbefore(&base->object->actuators, act->prev, act); + /* locate the first visible actuators before this one */ + for (tmp = act->prev; tmp; tmp=tmp->prev) { + if (tmp->flag & ACT_VISIBLE) + break; + } + if (tmp) { + BLI_remlink(&base->object->actuators, act); + BLI_insertlinkbefore(&base->object->actuators, tmp, act); + } } else if( val==2 && act->next) { - BLI_remlink(&base->object->actuators, act); - BLI_insertlink(&base->object->actuators, act->next, act); + for (tmp=act->next; tmp; tmp=tmp->next) { + if (tmp->flag & ACT_VISIBLE) + break; + } + if (tmp) { + BLI_remlink(&base->object->actuators, act); + BLI_insertlink(&base->object->actuators, tmp, act); + } } BIF_undo_push("Move actuator"); allqueue(REDRAWBUTSLOGIC, 0); @@ -348,7 +389,7 @@ void do_logic_buts(unsigned short event) bActuator *act; Base *base; Object *ob; - int didit; + int didit, bit; ob= OBACT; if(ob==0) return; @@ -462,6 +503,18 @@ void do_logic_buts(unsigned short event) make_unique_prop_names(cont->name); base->object->scaflag |= OB_SHOWCONT; BLI_addtail(&(base->object->controllers), cont); + /* set the controller state mask from the current object state. + A controller is always in a single state, so select the lowest bit set + from the object state */ + for (bit=0; bit<32; bit++) { + if (base->object->state & (1<state_mask = (1<state_mask == 0) { + /* shouldn't happen, object state is never 0 */ + cont->state_mask = 1; + } } base= base->next; } @@ -469,6 +522,32 @@ void do_logic_buts(unsigned short event) allqueue(REDRAWBUTSLOGIC, 0); break; + case B_SET_STATE_BIT: + base= FIRSTBASE; + while(base) { + if(base->object->scaflag & OB_SETSTBIT) { + base->object->scaflag &= ~OB_SETSTBIT; + base->object->state = 0x3FFFFFFF; + } + base= base->next; + } + allqueue(REDRAWBUTSLOGIC, 0); + break; + + case B_INIT_STATE_BIT: + base= FIRSTBASE; + while(base) { + if(base->object->scaflag & OB_INITSTBIT) { + base->object->scaflag &= ~OB_INITSTBIT; + base->object->state = base->object->init_state; + if (!base->object->state) + base->object->state = 1; + } + base= base->next; + } + allqueue(REDRAWBUTSLOGIC, 0); + break; + case B_CHANGE_CONT: base= FIRSTBASE; while(base) { @@ -505,7 +584,7 @@ void do_logic_buts(unsigned short event) BIF_undo_push("Delete controller"); allqueue(REDRAWBUTSLOGIC, 0); break; - + case B_ADD_ACT: base= FIRSTBASE; while(base) { @@ -661,6 +740,14 @@ static char *controller_name(int type) return "AND"; case CONT_LOGIC_OR: return "OR"; + case CONT_LOGIC_NAND: + return "NAND"; + case CONT_LOGIC_NOR: + return "NOR"; + case CONT_LOGIC_XOR: + return "XOR"; + case CONT_LOGIC_XNOR: + return "XNOR"; case CONT_EXPRESSION: return "Expression"; case CONT_PYTHON: @@ -671,7 +758,7 @@ static char *controller_name(int type) static char *controller_pup(void) { - return "Controllers %t|AND %x0|OR %x1|Expression %x2|Python %x3"; + return "Controllers %t|AND %x0|OR %x1|XOR %x6|NAND %x4|NOR %x5|XNOR %x7|Expression %x2|Python %x3"; } static char *actuator_name(int type) @@ -717,6 +804,8 @@ static char *actuator_name(int type) return "2D Filter"; case ACT_PARENT: return "Parent"; + case ACT_STATE: + return "State"; } return "unknown"; } @@ -732,21 +821,21 @@ static char *actuator_pup(Object *owner) return "Actuators %t|Action %x15|Motion %x0|Constraint %x9|Ipo %x1" "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17" - "|Visibility %x18|2D Filter %x19|Parent %x20"; + "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22"; break; case OB_MESH: return "Actuators %t|Shape Action %x21|Motion %x0|Constraint %x9|Ipo %x1" "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17" - "|Visibility %x18|2D Filter %x19|Parent %x20"; + "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22"; break; default: return "Actuators %t|Motion %x0|Constraint %x9|Ipo %x1" "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17" - "|Visibility %x18|2D Filter %x19|Parent %x20"; + "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22"; } } @@ -815,7 +904,8 @@ static ID **get_selected_and_linked_obs(short *count, short scavisflag) if(scavisflag & BUTS_ACT_ACT) OBACT->scavisflag |= OB_VIS_ACT; } - if(scavisflag & (BUTS_SENS_LINK|BUTS_CONT_LINK|BUTS_ACT_LINK)) { + /* BUTS_XXX_STATE are similar to BUTS_XXX_LINK for selecting the object */ + if(scavisflag & (BUTS_SENS_LINK|BUTS_CONT_LINK|BUTS_ACT_LINK|BUTS_SENS_STATE|BUTS_ACT_STATE)) { doit= 1; while(doit) { doit= 0; @@ -824,7 +914,7 @@ static ID **get_selected_and_linked_obs(short *count, short scavisflag) while(ob) { /* 1st case: select sensor when controller selected */ - if((scavisflag & BUTS_SENS_LINK) && (ob->scavisflag & OB_VIS_SENS)==0) { + if((scavisflag & (BUTS_SENS_LINK|BUTS_SENS_STATE)) && (ob->scavisflag & OB_VIS_SENS)==0) { sens= ob->sensors.first; while(sens) { for(a=0; atotlinks; a++) { @@ -879,7 +969,7 @@ static ID **get_selected_and_linked_obs(short *count, short scavisflag) } /* 4th case: select actuator when controller selected */ - if( (scavisflag & BUTS_ACT_LINK) && (ob->scavisflag & OB_VIS_CONT)) { + if( (scavisflag & (BUTS_ACT_LINK|BUTS_ACT_STATE)) && (ob->scavisflag & OB_VIS_CONT)) { cont= ob->controllers.first; while(cont) { for(a=0; atotlinks; a++) { @@ -984,6 +1074,10 @@ static void draw_default_sensor_header(bSensor *sens, (short)(x + 10 + 0.85 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, &sens->invert, 0.0, 0.0, 0, 0, "Invert the level (output) of this sensor"); + uiDefButS(block, TOG, 1, "Lvl", + (short)(x + 10 + 0.70 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, + &sens->level, 0.0, 0.0, 0, 0, + "Level detector versus edge detector (only applicable in case of logic state transition)"); } static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname) @@ -1458,6 +1552,7 @@ static int get_col_actuator(int type) case ACT_GAME: return TH_BUT_SETTING2; case ACT_VISIBILITY: return TH_BUT_NUM; case ACT_CONSTRAINT: return TH_BUT_ACTION; + case ACT_STATE: return TH_BUT_SETTING2; default: return TH_BUT_NEUTRAL; } } @@ -1468,7 +1563,23 @@ static void set_col_actuator(int item, int medium) } -static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, short yco, short width) +char *get_state_name(Object *ob, short bit) +{ + bController *cont; + unsigned int mask; + + mask = (1<controllers.first; + while (cont) { + if (cont->state_mask & mask) { + return cont->name; + } + cont = cont->next; + } + return (char*)""; +} + +static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, short xco, short yco, short width) { bSoundActuator *sa = NULL; bCDActuator *cda = NULL; @@ -1487,11 +1598,12 @@ static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, sho bVisibilityActuator *visAct = NULL; bTwoDFilterActuator *tdfa = NULL; bParentActuator *parAct = NULL; + bStateActuator *staAct = NULL; float *fp; short ysize = 0, wval; char *str; - int myline; + int myline, stbit; /* yco is at the top of the rect, draw downwards */ uiBlockSetEmboss(block, UI_EMBOSSM); @@ -1501,7 +1613,7 @@ static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, sho { case ACT_OBJECT: { - ysize= 129; + ysize= 152; glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); @@ -1539,14 +1651,18 @@ static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, sho uiDefButF(block, NUM, 0, "", xco+45+wval, yco-125, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-125, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, ""); - uiDefButBitI(block, TOG, ACT_FORCE_LOCAL, 0, "L", xco+45+3*wval, yco-22, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitI(block, TOG, ACT_TORQUE_LOCAL, 0, "L", xco+45+3*wval, yco-41, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitI(block, TOG, ACT_DLOC_LOCAL, 0, "L", xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitI(block, TOG, ACT_DROT_LOCAL, 0, "L", xco+45+3*wval, yco-83, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitI(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitI(block, TOG, ACT_ANG_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-125, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); + uiDefBut(block, LABEL, 0, "damp", xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity"); + uiDefButI(block, NUM, 0, "", xco+45, yco-148, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, ""); + uiDefButBitS(block, TOG, ACT_CLAMP_VEL, 0, "clamp",xco+45+wval, yco-148, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between SET and CLAMP Velocity"); + + uiDefButBitS(block, TOG, ACT_FORCE_LOCAL, 0, "L", xco+45+3*wval, yco-22, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); + uiDefButBitS(block, TOG, ACT_TORQUE_LOCAL, 0, "L", xco+45+3*wval, yco-41, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); + uiDefButBitS(block, TOG, ACT_DLOC_LOCAL, 0, "L", xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); + uiDefButBitS(block, TOG, ACT_DROT_LOCAL, 0, "L", xco+45+3*wval, yco-83, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); + uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); + uiDefButBitS(block, TOG, ACT_ANG_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-125, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitI(block, TOG, ACT_ADD_LIN_VEL, 0, "add",xco+45+3*wval+15, yco-106, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV"); + uiDefButBitS(block, TOG, ACT_ADD_LIN_VEL, 0, "add",xco+45+3*wval+15, yco-106, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV"); yco-= ysize; break; @@ -1573,31 +1689,34 @@ static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, sho #else str= "Action types %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6"; #endif - uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &aa->type, 0.0, 0.0, 0.0, 0.0, "Action playback type"); - uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, 1, "AC: ", xco+30, yco-44, width-60, 19, &aa->act, "Action name"); + uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, (width-60)/2, 19, &aa->type, 0.0, 0.0, 0.0, 0.0, "Action playback type"); + uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, 1, "AC: ", xco+30 + ((width-60)/2), yco-24, (width-60)/2, 19, &aa->act, "Action name"); if(aa->type == ACT_ACTION_FROM_PROP) { - uiDefBut(block, TEX, 0, "Prop: ",xco+30, yco-64, width-60, 19, aa->name, 0.0, 31.0, 0, 0, "Use this property to define the Action position"); + uiDefBut(block, TEX, 0, "Prop: ",xco+30, yco-44, width-60, 19, aa->name, 0.0, 31.0, 0, 0, "Use this property to define the Action position"); } else { - uiDefButI(block, NUM, 0, "Sta: ",xco+30, yco-64, (width-60)/2, 19, &aa->sta, 0.0, MAXFRAMEF, 0, 0, "Start frame"); - uiDefButI(block, NUM, 0, "End: ",xco+30+(width-60)/2, yco-64, (width-60)/2, 19, &aa->end, 0.0, MAXFRAMEF, 0, 0, "End frame"); + uiDefButI(block, NUM, 0, "Sta: ",xco+30, yco-44, (width-60)/2, 19, &aa->sta, 0.0, MAXFRAMEF, 0, 0, "Start frame"); + uiDefButI(block, NUM, 0, "End: ",xco+30+(width-60)/2, yco-44, (width-60)/2, 19, &aa->end, 0.0, MAXFRAMEF, 0, 0, "End frame"); } + + uiDefButI(block, NUM, 0, "Blendin: ", xco+30, yco-64, (width-60)/2, 19, &aa->blendin, 0.0, MAXFRAMEF, 0.0, 0.0, "Number of frames of motion blending"); + uiDefButS(block, NUM, 0, "Priority: ", xco+30+(width-60)/2, yco-64, (width-60)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers, With 2 or more actions at once, the overriding channels must be lower in the stack"); - - - uiDefButI(block, NUM, 0, "Blendin: ", xco+30, yco-84, (width-60)/2, 19, &aa->blendin, 0.0, MAXFRAMEF, 0.0, 0.0, "Number of frames of motion blending"); - uiDefButS(block, NUM, 0, "Priority: ", xco+30+(width-60)/2, yco-84, (width-60)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers"); + uiDefBut(block, TEX, 0, "FrameProp: ",xco+30, yco-84, width-60, 19, aa->frameProp, 0.0, 31.0, 0, 0, "Assign this property this actions current frame number"); + #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR if(aa->type == ACT_ACTION_MOTION) { - uiDefButF(block, NUM, 0, "Cycle: ",xco+30, yco-104, (width-60)/2, 19, &aa->stridelength, 0.0, 2500.0, 0, 0, "Distance covered by a single cycle of the action"); + uiDefButF(block, NUM, 0, "Cycle: ",xco+30, yco-84, (width-60)/2, 19, &aa->stridelength, 0.0, 2500.0, 0, 0, "Distance covered by a single cycle of the action"); } #endif + + yco-=ysize; break; } @@ -1821,8 +1940,15 @@ static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, sho uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2-40, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the tracking takes"); uiDefButS(block, TOG, 0, "3D", xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking"); } - - str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3"; + else if(eoa->type==ACT_EDOB_DYNAMICS) { + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3"; + uiDefButS(block, MENU, B_REDR, str, xco+40, yco-44, (width-80), 19, &(eoa->dyn_operation), 0.0, 0.0, 0, 0, ""); + } + str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3|Dynamics %x4"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, ""); yco-= ysize; @@ -2022,6 +2148,37 @@ static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, sho break; + case ACT_STATE: + ysize = 34; + + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, + (float)yco-ysize, (float)xco+width, (float)yco, 1); + + staAct = act->data; + + str= "Operation %t|Cpy %x0|Add %x1|Sub %x2|Inv %x3"; + + uiDefButI(block, MENU, B_REDR, str, + xco + 10, yco - 24, 65, 19, &staAct->type, + 0.0, 0.0, 0, 0, + "Select the bit operation on object state mask"); + + for (wval=0; wval<15; wval+=5) { + uiBlockBeginAlign(block); + for (stbit=0; stbit<5; stbit++) { + uiDefButBitI(block, TOG, (1<<(stbit+wval)), 0, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(wval+stbit))); + } + for (stbit=0; stbit<5; stbit++) { + uiDefButBitI(block, TOG, (1<<(stbit+wval+15)), 0, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(wval+stbit+15))); + } + } + uiBlockEndAlign(block); + + yco-= ysize; + + break; + case ACT_RANDOM: ysize = 69; @@ -2225,7 +2382,11 @@ static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, sho break; case ACT_2DFILTER_CUSTOMFILTER: uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30,yco-44,width-60,19,&tdfa->int_arg,0.0,MAX_RENDER_PASS-1,0.0,0.0,"Set motion blur value"); - uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+30,yco-64,width-60, 19, &tdfa->text, ""); + uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+30,yco-64,width/2-32, 19, &tdfa->text, ""); + uiDefButS(block, TOG|BIT|0, B_REDR, "Depth", xco+width/2+2 , yco - 64, width/4-16 , 19, + &tdfa->texture_flag, 0.0, 0.0, 0, 0, "Includes Depth Texture (bgl_DepthTexture)"); + uiDefButS(block, TOG|BIT|1, B_REDR, "Luminance", xco+3*width/4-14 , yco - 64, width/4-16 , 19, + &tdfa->texture_flag, 0.0, 0.0, 0, 0, "Includes Luminance Texture (bgl_LuminanceTexture)"); break; } @@ -2596,6 +2757,118 @@ void buttons_bullet(uiBlock *block, Object *ob) uiBlockEndAlign(block); } +static void check_object_state(void *arg1_but, void *arg2_mask) +{ + unsigned int *cont_mask = arg2_mask; + uiBut *but = arg1_but; + + if (*cont_mask == 0 || !(G.qual & LR_SHIFTKEY)) + *cont_mask = (1<retval); + but->retval = B_REDR; +} + +static void check_controller_state_mask(void *arg1_but, void *arg2_mask) +{ + unsigned int *cont_mask = arg2_mask; + uiBut *but = arg1_but; + + /* a controller is always in a single state */ + *cont_mask = (1<retval); + but->retval = B_REDR; +} + +static int first_bit(unsigned int mask) +{ + int bit; + + for (bit=0; bit<32; bit++) { + if (mask & (1<uiblocks, "Controller state mask", UI_EMBOSS, UI_HELV, curarea->win); + + /* use this for a fake extra empy space around the buttons */ + uiDefBut(block, LABEL, 0, "", -5, -5, 200, 34, NULL, 0, 0, 0, 0, ""); + + for (offset=0; offset<15; offset+=5) { + uiBlockBeginAlign(block); + for (stbit=0; stbit<5; stbit++) { + but = uiDefButBitI(block, TOG, (1<<(stbit+offset)), (stbit+offset), "", (short)(xco+12*stbit+13*offset), yco, 12, 12, (int *)&(cont->state_mask), 0, 0, 0, 0, ""); + uiButSetFunc(but, check_controller_state_mask, but, &(cont->state_mask)); + } + for (stbit=0; stbit<5; stbit++) { + but = uiDefButBitI(block, TOG, (1<<(stbit+offset+15)), (stbit+offset+15), "", (short)(xco+12*stbit+13*offset), yco-12, 12, 12, (int *)&(cont->state_mask), 0, 0, 0, 0, ""); + uiButSetFunc(but, check_controller_state_mask, but, &(cont->state_mask)); + } + } + uiBlockEndAlign(block); + + uiBlockSetDirection(block, UI_TOP); + + return block; +} + +static void do_object_state_menu(void *arg, int event) +{ + Object *ob = arg; + + switch (event) { + case 0: + ob->state = 0x3FFFFFFF; + break; + case 1: + ob->state = ob->init_state; + if (!ob->state) + ob->state = 1; + break; + case 2: + ob->init_state = ob->state; + break; + } + allqueue(REDRAWBUTSLOGIC, 0); +} + +static uiBlock *object_state_mask_menu(void *arg_obj) +{ + uiBlock *block; + short xco = 0; + + block= uiNewBlock(&curarea->uiblocks, "obstatemenu", UI_EMBOSSP, UI_HELV, curarea->win); + uiBlockSetButmFunc(block, do_object_state_menu, arg_obj); + + uiDefBut(block, BUTM, 1, "Set all bits", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, BUTM, 1, "Recall init state", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefBut(block, SEPR, 0, "", 0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, BUTM, 1, "Store init state", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, ""); + + uiBlockSetDirection(block, UI_TOP); + return block; +} + +static int is_sensor_linked(uiBlock *block, bSensor *sens) +{ + bController *cont; + int i, count; + + for (count=0, i=0; itotlinks; i++) { + cont = sens->links[i]; + if (uiFindInlink(block, cont) != NULL) + return 1; + } + return 0; +} + /* never used, see CVS 1.134 for the code */ /* static FreeCamera *new_freecamera(void) */ @@ -2614,7 +2887,7 @@ void logic_buts(void) uiBlock *block; uiBut *but; World *wrld; - int a; + int a, iact, stbit, offset; short xco, yco, count, width, ycoo; char *pupstr, name[32]; @@ -2686,78 +2959,27 @@ void logic_buts(void) uiClearButLock(); idar= get_selected_and_linked_obs(&count, G.buts->scaflag); - - /* ******************************* */ - xco= 375; yco= 170; width= 230; - uiBlockSetEmboss(block, UI_EMBOSSP); - uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 80, 19, ""); - uiBlockSetEmboss(block, UI_EMBOSS); - - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects"); - uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object"); - uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller"); - uiBlockEndAlign(block); - + /* clean ACT_LINKED and ACT_VISIBLE of all potentially visible actuators so that + we can determine which is actually linked/visible */ for(a=0; ascavisflag & OB_VIS_SENS) == 0) continue; - - /* presume it is only objects for now */ - uiBlockSetEmboss(block, UI_EMBOSS); - uiBlockBeginAlign(block); - if(ob->sensors.first) uiSetCurFont(block, UI_HELVB); - uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors"); - if(ob->sensors.first) uiSetCurFont(block, UI_HELV); - uiDefButBitS(block, TOG, OB_ADDSENS, B_ADD_SENS, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor"); - uiBlockEndAlign(block); - yco-=20; - - if(ob->scaflag & OB_SHOWSENS) { - - sens= ob->sensors.first; - while(sens) { - uiBlockSetEmboss(block, UI_EMBOSSM); - uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor"); - uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Sensor settings"); - - ycoo= yco; - if(sens->flag & SENS_SHOW) - { - uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(), (short)(xco+22), yco, 100, 19, &sens->type, 0, 0, 0, 0, "Sensor type"); - but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, sens->name, 0, 31, 0, 0, "Sensor name"); - uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0); - - sens->otype= sens->type; - yco= draw_sensorbuttons(sens, block, xco, yco, width,ob->id.name); - if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; - } - else { - set_col_sensor(sens->type, 1); - glRecti(xco+22, yco, xco+width-22,yco+19); - but= uiDefBut(block, LABEL, 0, sensor_name(sens->type), (short)(xco+22), yco, 100, 19, sens, 0, 0, 0, 0, ""); - uiButSetFunc(but, sca_move_sensor, sens, NULL); - but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+122), yco, (short)(width-144), 19, sens, 0, 31, 0, 0, ""); - uiButSetFunc(but, sca_move_sensor, sens, NULL); - } - - but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, ""); - uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER); - - yco-=20; - - sens= sens->next; - } - yco-= 6; + act= ob->actuators.first; + while(act) { + act->flag &= ~(ACT_LINKED|ACT_VISIBLE); + act = act->next; + } + /* same for sensors */ + sens= ob->sensors.first; + while(sens) { + sens->flag &= ~(SENS_VISIBLE); + sens = sens->next; } } - + + /* start with the controller because we need to know which one is visible */ /* ******************************* */ - xco= 675; yco= 170; width= 230; + xco= 695; yco= 170; width= 275; uiBlockSetEmboss(block, UI_EMBOSSP); uiDefBlockBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, 19, ""); @@ -2785,59 +3007,193 @@ void logic_buts(void) if(ob->controllers.first) uiSetCurFont(block, UI_HELV); uiDefButBitS(block, TOG, OB_ADDCONT, B_ADD_CONT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller"); uiBlockEndAlign(block); - yco-=20; + yco-=17; + /* mark all actuators linked to these controllers */ + /* note that some of these actuators could be from objects that are not in the display list. + It's ok because those actuators will not be displayed here */ + cont= ob->controllers.first; + while(cont) { + for (iact=0; iacttotlinks; iact++) { + act = cont->links[iact]; + act->flag |= ACT_LINKED; + } + cont = cont->next; + } + if(ob->scaflag & OB_SHOWCONT) { - - cont= ob->controllers.first; - while(cont) { - uiBlockSetEmboss(block, UI_EMBOSSM); - uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X, xco, yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Delete Controller"); - uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings"); - - if(cont->flag & CONT_SHOW) { - cont->otype= cont->type; - uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 100, 19, &cont->type, 0, 0, 0, 0, "Controller type"); - but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, cont->name, 0, 31, 0, 0, "Controller name"); - uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0); - - ycoo= yco; - yco= draw_controllerbuttons(cont, block, xco, yco, width); - if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; + + /* first show the state */ + uiBlockSetEmboss(block, UI_EMBOSSP); + uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 40, 19, "Object state menu: store and retrieve initial state"); + uiBlockSetEmboss(block, UI_EMBOSS); + if (!ob->state) + ob->state = 1; + for (offset=0; offset<15; offset+=5) { + uiBlockBeginAlign(block); + for (stbit=0; stbit<5; stbit++) { + but = uiDefButBitI(block, TOG, 1<<(stbit+offset), stbit+offset, "", (short)(xco+35+12*stbit+13*offset), yco, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset))); + uiButSetFunc(but, check_object_state, but, &(ob->state)); } - else { - cpack(0x999999); - glRecti(xco+22, yco, xco+width-22,yco+19); - but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 100, 19, cont, 0, 0, 0, 0, "Controller type"); - uiButSetFunc(but, sca_move_controller, cont, NULL); - but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+122), yco,(short)(width-144), 19, cont, 0, 0, 0, 0, "Controller name"); - uiButSetFunc(but, sca_move_controller, cont, NULL); - ycoo= yco; + for (stbit=0; stbit<5; stbit++) { + but = uiDefButBitI(block, TOG, 1<<(stbit+offset+15), stbit+offset+15, "", (short)(xco+35+12*stbit+13*offset), yco-12, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset+15))); + uiButSetFunc(but, check_object_state, but, &(ob->state)); } + } + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, OB_SETSTBIT, B_SET_STATE_BIT, "All",(short)(xco+235), yco-10, 25, 19, &ob->scaflag, 0, 0, 0, 0, "Set all state bits"); + uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini",(short)(xco+260), yco-10, 25, 19, &ob->scaflag, 0, 0, 0, 0, "Set the initial state"); + uiBlockEndAlign(block); + + yco-=35; - but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, ""); - uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR); - - uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, cont, LINK_CONTROLLER, 0, 0, 0, ""); - - yco-=20; + /* display only the controllers that match the current state */ + offset = 0; + for (stbit=0; stbit<32; stbit++) { + if (!(ob->state & (1<controllers.first; + while(cont) { + if (cont->state_mask & (1<totlinks; iact++) { + act = cont->links[iact]; + act->flag |= ACT_VISIBLE; + } + uiBlockSetEmboss(block, UI_EMBOSSM); + uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X, xco, yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Delete Controller"); + uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings"); + uiBlockSetEmboss(block, UI_EMBOSSP); + sprintf(name, "%d", first_bit(cont->state_mask)+1); + uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state mask"); + uiBlockSetEmboss(block, UI_EMBOSSM); - cont= cont->next; + if(cont->flag & CONT_SHOW) { + cont->otype= cont->type; + uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 100, 19, &cont->type, 0, 0, 0, 0, "Controller type"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-166), 19, cont->name, 0, 31, 0, 0, "Controller name"); + uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0); + + ycoo= yco; + yco= draw_controllerbuttons(cont, block, xco, yco, width); + if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; + } + else { + cpack(0x999999); + glRecti(xco+22, yco, xco+width-22,yco+19); + but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 100, 19, cont, 0, 0, 0, 0, "Controller type"); + uiButSetFunc(but, sca_move_controller, cont, NULL); + but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+122), yco,(short)(width-166), 19, cont, 0, 0, 0, 0, "Controller name"); + uiButSetFunc(but, sca_move_controller, cont, NULL); + ycoo= yco; + } + + but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, ""); + uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR); + + uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, cont, LINK_CONTROLLER, 0, 0, 0, ""); + /* offset is >0 if at least one controller was displayed */ + offset++; + yco-=20; + } + cont= cont->next; + } + } yco-= 6; } } /* ******************************* */ - xco= 985; yco= 170; width= 280; + xco= 375; yco= 170; width= 250; + + uiBlockSetEmboss(block, UI_EMBOSSP); + uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 70, 19, ""); + uiBlockSetEmboss(block, UI_EMBOSS); + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+80, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects"); + uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+80+(width-70)/4, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object"); + uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+80+2*(width-70)/4, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller"); + uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "Sta", xco+80+3*(width-70)/4, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states"); + uiBlockEndAlign(block); + + for(a=0; ascavisflag & OB_VIS_SENS) == 0) continue; + + /* presume it is only objects for now */ + uiBlockSetEmboss(block, UI_EMBOSS); + uiBlockBeginAlign(block); + if(ob->sensors.first) uiSetCurFont(block, UI_HELVB); + uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors"); + if(ob->sensors.first) uiSetCurFont(block, UI_HELV); + uiDefButBitS(block, TOG, OB_ADDSENS, B_ADD_SENS, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor"); + uiBlockEndAlign(block); + yco-=20; + + if(ob->scaflag & OB_SHOWSENS) { + + sens= ob->sensors.first; + while(sens) { + if (!(G.buts->scaflag & BUTS_SENS_STATE) || + sens->totlinks == 0 || /* always display sensor without links so that is can be edited */ + is_sensor_linked(block, sens)) { + sens->flag |= SENS_VISIBLE; + uiBlockSetEmboss(block, UI_EMBOSSM); + uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor"); + uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Sensor settings"); + + ycoo= yco; + if(sens->flag & SENS_SHOW) + { + uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(), (short)(xco+22), yco, 100, 19, &sens->type, 0, 0, 0, 0, "Sensor type"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, sens->name, 0, 31, 0, 0, "Sensor name"); + uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0); + + sens->otype= sens->type; + yco= draw_sensorbuttons(sens, block, xco, yco, width,ob->id.name); + if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; + } + else { + set_col_sensor(sens->type, 1); + glRecti(xco+22, yco, xco+width-22,yco+19); + but= uiDefBut(block, LABEL, 0, sensor_name(sens->type), (short)(xco+22), yco, 100, 19, sens, 0, 0, 0, 0, ""); + uiButSetFunc(but, sca_move_sensor, sens, NULL); + but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+122), yco, (short)(width-144), 19, sens, 0, 31, 0, 0, ""); + uiButSetFunc(but, sca_move_sensor, sens, NULL); + } + + but= uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, ""); + uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER); + + yco-=20; + } + sens= sens->next; + } + yco-= 6; + } + } + + /* ******************************* */ + xco= 1040; yco= 170; width= 280; uiBlockSetEmboss(block, UI_EMBOSSP); - uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 100, 19, ""); + uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 90, 19, ""); uiBlockSetEmboss(block, UI_EMBOSS); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, BUTS_ACT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects"); - uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-110)/3, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object"); - uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-110)/3, yco+35, (width-110)/3, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller"); + uiDefButBitS(block, TOG, BUTS_ACT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects"); + uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-100)/4, yco+35, (width-100)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object"); + uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-100)/4, yco+35, (width-100)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller"); + uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "Sta", xco+110+3*(width-100)/4, yco+35, (width-100)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states"); uiBlockEndAlign(block); for(a=0; aactuators.first; while(act) { - uiBlockSetEmboss(block, UI_EMBOSSM); - uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator"); - uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Actuator settings"); + if (!(G.buts->scaflag & BUTS_ACT_STATE) || + !(act->flag & ACT_LINKED) || /* always display actuators without links so that is can be edited */ + (act->flag & ACT_VISIBLE)) { /* this actuator has visible connection, display it */ + act->flag |= ACT_VISIBLE; /* mark the actuator as visible to help implementing the up/down action */ + uiBlockSetEmboss(block, UI_EMBOSSM); + uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator"); + uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Actuator settings"); - if(act->flag & ACT_SHOW) { - act->otype= act->type; - uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob), (short)(xco+22), yco, 100, 19, &act->type, 0, 0, 0, 0, "Actuator type"); - but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, act->name, 0, 31, 0, 0, "Actuator name"); - uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0); + if(act->flag & ACT_SHOW) { + act->otype= act->type; + uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob), (short)(xco+22), yco, 100, 19, &act->type, 0, 0, 0, 0, "Actuator type"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-144), 19, act->name, 0, 31, 0, 0, "Actuator name"); + uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0); - ycoo= yco; - yco= draw_actuatorbuttons(act, block, xco, yco, width); - if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; + ycoo= yco; + yco= draw_actuatorbuttons(ob, act, block, xco, yco, width); + if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; + } + else { + set_col_actuator(act->type, 1); + glRecti((short)(xco+22), yco, (short)(xco+width-22),(short)(yco+19)); + but= uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 100, 19, act, 0, 0, 0, 0, "Actuator type"); + uiButSetFunc(but, sca_move_actuator, act, NULL); + but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+122), yco, (short)(width-144), 19, act, 0, 0, 0, 0, "Actuator name"); + uiButSetFunc(but, sca_move_actuator, act, NULL); + ycoo= yco; + } + + uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, act, LINK_ACTUATOR, 0, 0, 0, ""); + + yco-=20; } - else { - set_col_actuator(act->type, 1); - glRecti((short)(xco+22), yco, (short)(xco+width-22),(short)(yco+19)); - but= uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 100, 19, act, 0, 0, 0, 0, "Actuator type"); - uiButSetFunc(but, sca_move_actuator, act, NULL); - but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+122), yco, (short)(width-144), 19, act, 0, 0, 0, 0, "Actuator name"); - uiButSetFunc(but, sca_move_actuator, act, NULL); - ycoo= yco; - } - - uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, act, LINK_ACTUATOR, 0, 0, 0, ""); - - yco-=20; - act= act->next; } yco-= 6; diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 3797a92f16f..1c98950080a 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -900,7 +900,7 @@ static void seq_panel_filter_video() "Convert input to float data"); uiDefButBitI(block, TOG, SEQ_FILTERY, - B_SEQ_BUT_RELOAD, "FilterY", + B_SEQ_BUT_RELOAD_FILE, "De-Inter", 170,110,80,19, &last_seq->flag, 0.0, 21.0, 100, 0, "For video movies to remove fields"); diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 8c4958a651a..89466151a39 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -474,10 +474,13 @@ static void draw_channel_names(void) indent= 0; special= -1; - if (EXPANDED_AGRP(agrp)) - expand = ICON_TRIA_DOWN; - else - expand = ICON_TRIA_RIGHT; + /* only show expand if there are any channels */ + if (agrp->channels.first) { + if (EXPANDED_AGRP(agrp)) + expand = ICON_TRIA_DOWN; + else + expand = ICON_TRIA_RIGHT; + } if (EDITABLE_AGRP(agrp)) protect = ICON_UNLOCKED; diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index deb7ddc068d..2f1cdb8b951 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -246,7 +246,8 @@ void default_gl_light(void) glDisable(GL_COLOR_MATERIAL); } -/* also called when render 'ogl' */ +/* also called when render 'ogl' + keep synced with Myinit_gl_stuff in the game engine! */ void init_gl_stuff(void) { float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 40b6b7ba6fe..f93a1526e3c 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -390,7 +390,7 @@ static void actdata_filter_actionchannel (ListBase *act_data, bActionChannel *ac static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_mode) { - bActListElem *ale; + bActListElem *ale=NULL; bActionGroup *agrp; bActionChannel *achan, *lastchan=NULL; @@ -429,6 +429,15 @@ static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_ for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { actdata_filter_actionchannel(act_data, achan, filter_mode); } + + /* remove group from filtered list if last element is group + * (i.e. only if group had channels, which were all hidden) + */ + if ( (ale) && (act_data->last == ale) && + (ale->data == agrp) && (agrp->channels.first) ) + { + BLI_freelinkN(act_data, ale); + } } } } @@ -3648,7 +3657,7 @@ static void mouse_actionchannels (short mval[]) { bActionGroup *agrp= (bActionGroup *)act_channel; - if (mval[0] < 16) { + if ((mval[0] < 16) && (agrp->channels.first)) { /* toggle expand */ agrp->flag ^= AGRP_EXPANDED; } diff --git a/source/blender/src/editfont.c b/source/blender/src/editfont.c index cb245867c89..a3b05a008c8 100644 --- a/source/blender/src/editfont.c +++ b/source/blender/src/editfont.c @@ -354,7 +354,7 @@ void txt_export_to_object(struct Text *text) // char sdir[FILE_MAXDIR]; // char sfile[FILE_MAXFILE]; - if(!text) return; + if(!text || !text->lines.first) return; id = (ID *)text; @@ -429,7 +429,7 @@ void txt_export_to_objects(struct Text *text) int linenum = 0; float offset[3] = {0.0,0.0,0.0}; - if(!text) return; + if(!text || !text->lines.first) return; id = (ID *)text; diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index d5e34779173..c7a75b32df1 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -2307,7 +2307,7 @@ void selectconnected_mesh(void) if(em->edges.first==0) return; if( unified_findnearest(&eve, &eed, &efa)==0 ) { - error("Nothing indicated "); + /* error("Nothing indicated "); */ /* this is mostly annoying, eps with occluded geometry */ return; } @@ -2407,7 +2407,7 @@ static void selectconnected_delimit_mesh__internal(short all, short sel) EditFace *efa_mouse = findnearestface(&dist); if( !efa_mouse ) { - error("Nothing indicated "); + /* error("Nothing indicated "); */ /* this is mostly annoying, eps with occluded geometry */ return; } diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 3c945775b5b..2e5785eaab8 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -5942,7 +5942,7 @@ void hide_objects(int select) Base *base; short changed = 0, changed_act = 0; for(base = FIRSTBASE; base; base=base->next){ - if(TESTBASELIB(base)==select){ + if ((base->lay & G.vd->lay) && (TESTBASELIB(base)==select)) { base->flag &= ~SELECT; base->object->flag = base->flag; base->object->restrictflag |= OB_RESTRICT_VIEW; diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index fb0fac4489d..b9351f82d1e 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -2634,12 +2634,13 @@ void set_filter_seq(void) ed= G.scene->ed; if(ed==0) return; - if(okee("Set FilterY")==0) return; + if(okee("Set Deinterlace")==0) return; WHILE_SEQ(ed->seqbasep) { if(seq->flag & SELECT) { if(seq->type==SEQ_MOVIE) { seq->flag |= SEQ_FILTERY; + reload_sequence_new_file(seq); } } diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index 5f8485267bc..18a9803dcae 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -2690,15 +2690,17 @@ void image_changed(SpaceImage *sima, Image *image) if(image->id.us==0) id_us_plus(&image->id); else id_lib_extern(&image->id); - +#if 0 /* GE People dont like us messing with their face modes */ if (tface->transp==TF_ADD) {} /* they obviously know what they are doing! - leave as is */ else if (ibuf && ibuf->depth == 32) tface->transp = TF_ALPHA; else tface->transp = TF_SOLID; - +#endif } else { tface->tpage= NULL; tface->mode &= ~TF_TEX; +#if 0 tface->transp = TF_SOLID; +#endif } change = 1; } diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 6582866d9a1..4fbf92d646e 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -2797,6 +2797,10 @@ static void ui_add_link_line(ListBase *listb, uiBut *but, uiBut *bt) line->to= bt; } +uiBut *uiFindInlink(uiBlock *block, void *poin) +{ + return ui_find_inlink(block, poin); +} void uiComposeLinks(uiBlock *block) { diff --git a/source/blender/src/oops.c b/source/blender/src/oops.c index 99645b5e71f..51d83eff3e6 100644 --- a/source/blender/src/oops.c +++ b/source/blender/src/oops.c @@ -1153,7 +1153,6 @@ void build_oops() } } else if(type==ID_AR && G.soops->visiflag & OOPS_AR) { - bArmature *ar= ob->data; oops= add_test_oops(ob->data); } } diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index dcceea971f7..cc08bf53a72 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -1627,6 +1627,8 @@ void pose_flipquats(void) pchan->quat[3]= -pchan->quat[3]; } } - + + /* do autokey */ + autokeyframe_pose_cb_func(ob, TFM_ROTATION, 0); } diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index bf519dd6e9c..6851929bbc2 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -445,7 +445,10 @@ void reload_sequence_new_file(Sequence * seq) seq->strip->len = seq->len; } else if (seq->type == SEQ_MOVIE) { if(seq->anim) IMB_free_anim(seq->anim); - seq->anim = openanim(str, IB_rect); + seq->anim = openanim( + str, IB_rect | + ((seq->flag & SEQ_FILTERY) + ? IB_animdeinterlace : 0)); if (!seq->anim) { return; @@ -1445,7 +1448,7 @@ static void input_preprocess(Sequence * seq, TStripElem* se, int cfra) seq->strip->orx= se->ibuf->x; seq->strip->ory= se->ibuf->y; - if(seq->flag & SEQ_FILTERY) { + if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) { IMB_filtery(se->ibuf); } @@ -1772,8 +1775,11 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra, BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name); BLI_convertstringcode(name, G.sce); BLI_convertstringframe(name, G.scene->r.cfra); - - seq->anim = openanim(name, IB_rect); + + seq->anim = openanim( + name, IB_rect | + ((seq->flag & SEQ_FILTERY) + ? IB_animdeinterlace : 0)); } if(seq->anim) { IMB_anim_set_preseek(seq->anim, seq->anim_preseek); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index c49486a6294..4422411b1c5 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -378,9 +378,6 @@ void space_set_commmandline_options(void) { if ( (syshandle = SYS_GetSystem()) ) { /* User defined settings */ - a= (U.gameflags & USER_VERTEX_ARRAYS); - SYS_WriteCommandLineInt(syshandle, "vertexarrays", a); - a= (U.gameflags & USER_DISABLE_SOUND); SYS_WriteCommandLineInt(syshandle, "noaudio", a); @@ -437,9 +434,6 @@ static void SaveState(void) if(G.f & G_TEXTUREPAINT) texpaint_enable_mipmap(); - if(G.scene->camera==0 || G.scene->camera->type!=OB_CAMERA) - error("no (correct) camera"); - waitcursor(1); } @@ -4258,15 +4252,11 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiDefButS(block, MENU, B_GLRESLIMITCHANGED, "GL Texture Clamp Off%x0|%l|GL Texture Clamp 8192%x8192|GL Texture Clamp 4096%x4096|GL Texture Clamp 2048%x2048|GL Texture Clamp 1024%x1024|GL Texture Clamp 512%x512|GL Texture Clamp 256%x256|GL Texture Clamp 128%x128", (xpos+edgsp+(5*mpref)+(5*midsp)),y4,mpref,buth, &(U.glreslimit), 0, 0, 0, 0, "Limit the texture size to save graphics memory"); - uiDefButBitI(block, TOG, USER_VERTEX_ARRAYS, 0, "Vertex Arrays", - (xpos+edgsp+(5*mpref)+(5*midsp)),y3,mpref,buth, - &(U.gameflags), 0, 0, 0, 0, "Toggles between vertex arrays on (less reliable) and off (more reliable)"); - uiDefButI(block, NUM, 0, "Time Out ", - (xpos+edgsp+(5*mpref)+(5*midsp)), y2, mpref, buth, + (xpos+edgsp+(5*mpref)+(5*midsp)), y3, mpref, buth, &U.textimeout, 0.0, 3600.0, 30, 2, "Time since last access of a GL texture in seconds after which it is freed. (Set to 0 to keep textures allocated)"); uiDefButI(block, NUM, 0, "Collect Rate ", - (xpos+edgsp+(5*mpref)+(5*midsp)), y1, mpref, buth, + (xpos+edgsp+(5*mpref)+(5*midsp)), y2, mpref, buth, &U.texcollectrate, 1.0, 3600.0, 30, 2, "Number of seconds between each run of the GL texture garbage collector."); /* *** */ @@ -4976,11 +4966,13 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } break; case DKEY: - if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) + if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) { duplicate_marker(); - else if ((G.qual==LR_SHIFTKEY)) { + } else if ((G.qual==LR_SHIFTKEY)) { if(sseq->mainb) break; add_duplicate_seq(); + } else if (G.qual == 0) { + set_filter_seq(); } break; case EKEY: @@ -4988,10 +4980,6 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if((G.qual==0)) transform_seq('e', 0); break; - case FKEY: - if((G.qual==0)) - set_filter_seq(); - break; case GKEY: if (G.qual & LR_CTRLKEY) transform_markers('g', 0); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 4270ce6a069..705a5f868e7 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -2621,7 +2621,7 @@ static void applyRotation(TransInfo *t, float angle, float axis[3]) continue; if (t->con.applyRot) { - t->con.applyRot(t, td, axis); + t->con.applyRot(t, td, axis, NULL); VecRotToMat3(axis, angle * td->factor, mat); } else if (t->flag & T_PROP_EDIT) { @@ -2654,7 +2654,7 @@ int Rotation(TransInfo *t, short mval[2]) snapGrid(t, &final); if (t->con.applyRot) { - t->con.applyRot(t, NULL, axis); + t->con.applyRot(t, NULL, axis, &final); } applySnapping(t, &final); @@ -3314,7 +3314,7 @@ int PushPull(TransInfo *t, short mval[2]) } if (t->con.applyRot && t->con.mode & CON_APPLY) { - t->con.applyRot(t, NULL, axis); + t->con.applyRot(t, NULL, axis, NULL); } for(i = 0 ; i < t->total; i++, td++) { @@ -3326,7 +3326,7 @@ int PushPull(TransInfo *t, short mval[2]) VecSubf(vec, t->center, td->center); if (t->con.applyRot && t->con.mode & CON_APPLY) { - t->con.applyRot(t, td, axis); + t->con.applyRot(t, td, axis, NULL); if (isLockConstraint(t)) { float dvec[3]; Projf(dvec, vec, axis); diff --git a/source/blender/src/transform_constraints.c b/source/blender/src/transform_constraints.c index 2d01c2303fc..796b013cb88 100644 --- a/source/blender/src/transform_constraints.c +++ b/source/blender/src/transform_constraints.c @@ -393,7 +393,7 @@ static void applyObjectConstraintSize(TransInfo *t, TransData *td, float smat[3] * (ie: not doing counterclockwise rotations when the mouse moves clockwise). */ -static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3]) +static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3], float *angle) { if (!td && t->con.mode & CON_APPLY) { int mode = t->con.mode & (CON_AXIS0|CON_AXIS1|CON_AXIS2); @@ -413,9 +413,9 @@ static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3]) break; } /* don't flip axis if asked to or if num input */ - if (!(mode & CON_NOFLIP) && hasNumInput(&t->num) == 0) { + if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) { if (Inpf(vec, t->viewinv[2]) > 0.0f) { - VecMulf(vec, -1.0f); + *angle = -(*angle); } } } @@ -435,10 +435,15 @@ static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3]) * (ie: not doing counterclockwise rotations when the mouse moves clockwise). */ -static void applyObjectConstraintRot(TransInfo *t, TransData *td, float vec[3]) +static void applyObjectConstraintRot(TransInfo *t, TransData *td, float vec[3], float *angle) { - if (td && t->con.mode & CON_APPLY) { + if (t->con.mode & CON_APPLY) { int mode = t->con.mode & (CON_AXIS0|CON_AXIS1|CON_AXIS2); + + /* on setup call, use first object */ + if (td == NULL) { + td= t->data; + } switch(mode) { case CON_AXIS0: @@ -454,9 +459,9 @@ static void applyObjectConstraintRot(TransInfo *t, TransData *td, float vec[3]) VECCOPY(vec, td->axismtx[2]); break; } - if (!(mode & CON_NOFLIP)) { + if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) { if (Inpf(vec, t->viewinv[2]) > 0.0f) { - VecMulf(vec, -1.0f); + *angle = -(*angle); } } } diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index eaa4a1d0ecf..6cb7a34d1bc 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -325,7 +325,7 @@ void recalcData(TransInfo *t) else { for (base=G.scene->base.first; base; base=base->next) { /* recalculate scale of selected nla-strips */ - if (base->object->nlastrips.first) { + if (base->object && base->object->nlastrips.first) { Object *bob= base->object; bActionStrip *strip; @@ -398,8 +398,15 @@ void recalcData(TransInfo *t) } } else if(G.sipo->blocktype==ID_OB) { + Object *ob= OBACT; Base *base= FIRSTBASE; + /* only if this if active object has this ipo in an action (assumes that current ipo is in action) */ + if ((ob) && (ob->ipoflag & OB_ACTION_OB) && (G.sipo->pin==0)) { + ob->ctime= -1234567.0f; + DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); + } + while(base) { if(base->object->ipo==G.sipo->ipo) { do_ob_ipo(base->object); diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 295cfa4574c..d16308f17ae 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -412,7 +412,7 @@ float RotationBetween(TransInfo *t, float p1[3], float p2[3]) if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { float axis[3], tmp[3]; - t->con.applyRot(t, NULL, axis); + t->con.applyRot(t, NULL, axis, NULL); Projf(tmp, end, axis); VecSubf(end, end, tmp); @@ -737,136 +737,6 @@ void TargetSnapClosest(TransInfo *t) } /*================================================================*/ - -/* find snapping point on face, return 1 on success */ -int snapFace(MFace *face, EditFace *efa, MVert *verts, float *intersect, float *loc, float *no) -{ - MVert *v[4]; - EditVert *eve[4]; - int totvert; - int result = 0; - - v[0] = verts + face->v1; - v[1] = verts + face->v2; - v[2] = verts + face->v3; - - if (face->v4) - { - v[3] = verts + face->v4; - totvert = 4; - } - else - { - v[3] = NULL; - totvert = 3; - } - - if (efa) - { - eve[0] = efa->v1; - eve[1] = efa->v2; - eve[2] = efa->v3; - eve[3] = efa->v4; - } - - switch(G.scene->snap_mode) - { - case SCE_SNAP_MODE_VERTEX: - { - float min_dist = FLT_MAX; - int i; - - for(i = 0; i < totvert; i++) - { - - if (efa == NULL || (eve[i]->f1 & SELECT) == 0) - { - float vert_dist = VecLenf(v[i]->co, intersect); - - if (vert_dist < min_dist) - { - result = 1; - - min_dist = vert_dist; - - VECCOPY(loc, v[i]->co); - NormalShortToFloat(no, v[i]->no); - } - } - } - break; - } - case SCE_SNAP_MODE_EDGE: - { - float min_dist = FLT_MAX; - int i; - - for(i = 0; i < totvert; i++) - { - MVert *v1, *v2; - EditVert *eve1, *eve2; - - v1 = v[i]; - v2 = v[(i + 1) % totvert]; - - eve1 = eve[i]; - eve2 = eve[(i + 1) % totvert]; - - if (efa == NULL || ((eve1->f1 & SELECT) == 0 && (eve2->f1 & SELECT) == 0)) - { - float edge_loc[3]; - float vec[3]; - float mul; - float edge_dist; - - VecSubf(edge_loc, v2->co, v1->co); - VecSubf(vec, intersect, v1->co); - - mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); - - VecMulf(edge_loc, mul); - VecAddf(edge_loc, edge_loc, v1->co); - - edge_dist = VecLenf(edge_loc, intersect); - - if (edge_dist < min_dist) - { - float n1[3], n2[3]; - result = 1; - - min_dist = edge_dist; - - VECCOPY(loc, edge_loc); - - NormalShortToFloat(n1, v1->no); - NormalShortToFloat(n2, v2->no); - VecLerpf(no, n1, n2, mul); - Normalize(no); - } - } - } - break; - } - case SCE_SNAP_MODE_FACE: - { - if (efa == NULL || ((efa->f1 & SELECT) == 0)) - { - result = 1; - - VECCOPY(loc, intersect); - - if (totvert == 4) - CalcNormFloat4(v[0]->co, v[1]->co, v[2]->co, v[3]->co, no); - else - CalcNormFloat(v[0]->co, v[1]->co, v[2]->co, no); - } - break; - } - } - - return result; -} - int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth, short EditMesh) { int retval = 0; @@ -891,7 +761,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta Mat4Mul3Vecfl(imat, ray_normal_local); - /* If number of vert is more than an arbitrary limit, + /* If number of vert is more than an arbitrary limit, * test against boundbox first * */ if (totface > 16) { @@ -900,117 +770,83 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta } if (test == 1) { - MVert *verts = dm->getVertArray(dm); - MFace *faces = dm->getFaceArray(dm); - int *index_array = NULL; - int index = 0; - int i; - if (EditMesh) + switch (G.scene->snap_mode) { - index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); - EM_init_index_arrays(0, 0, 1); - } - - for( i = 0; i < totface; i++) { - EditFace *efa = NULL; - MFace *f = faces + i; - float lambda; - int result; - - test = 1; /* reset for every face */ - - if (EditMesh) - { - if (index_array) + case SCE_SNAP_MODE_FACE: + { + MVert *verts = dm->getVertArray(dm); + MFace *faces = dm->getFaceArray(dm); + int *index_array = NULL; + int index = 0; + int i; + + if (EditMesh) { - index = index_array[i]; - } - else - { - index = i; + index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); + EM_init_index_arrays(0, 0, 1); } - if (index == ORIGINDEX_NONE) - { - test = 0; - } - else - { - efa = EM_get_face_for_index(index); + for( i = 0; i < totface; i++) { + EditFace *efa = NULL; + MFace *f = faces + i; + float lambda; + int result; - if (efa && efa->f1 & SELECT) + test = 1; /* reset for every face */ + + if (EditMesh) { - test = 0; - } - } - } - - - if (test) - { - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL); - - if (result) { - float location[3], normal[3]; - float intersect[3]; - - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - if (snapFace(f, efa, verts, intersect, location, normal)) - { - float new_depth; - int screen_loc[2]; - int new_dist; - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) + if (index_array) { - *depth = new_depth; - retval = 1; - - VECCOPY(loc, location); - VECCOPY(no, normal); - - Mat3MulVecfl(timat, no); - Normalize(no); - - project_int(loc, screen_loc); - - *dist = new_dist; - } - } - } - - if (f->v4 && result == 0) - { - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL); - - if (result) { - float location[3], normal[3]; - float intersect[3]; + index = index_array[i]; + } + else + { + index = i; + } - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - if (snapFace(f, efa, verts, intersect, location, normal)) - { + if (index == ORIGINDEX_NONE) + { + test = 0; + } + else + { + efa = EM_get_face_for_index(index); + + if (efa && efa->f & SELECT) + { + test = 0; + } + } + } + + + if (test) + { + result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL); + + if (result) { + float location[3], normal[3]; + float intersect[3]; float new_depth; int screen_loc[2]; int new_dist; + VECCOPY(intersect, ray_normal_local); + VecMulf(intersect, lambda); + VecAddf(intersect, intersect, ray_start_local); + + VECCOPY(location, intersect); + + if (f->v4) + CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); + else + CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); + Mat4MulVecfl(obmat, location); - new_depth = VecLenf(location, ray_start); + new_depth = VecLenf(location, ray_start); project_int(location, screen_loc); new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); @@ -1029,14 +865,283 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta *dist = new_dist; } } + + if (f->v4 && result == 0) + { + result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL); + + if (result) { + float location[3], normal[3]; + float intersect[3]; + float new_depth; + int screen_loc[2]; + int new_dist; + + VECCOPY(intersect, ray_normal_local); + VecMulf(intersect, lambda); + VecAddf(intersect, intersect, ray_start_local); + + VECCOPY(location, intersect); + + if (f->v4) + CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); + else + CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + project_int(location, screen_loc); + new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); + + if (new_dist <= *dist && new_depth < *depth) + { + *depth = new_depth; + retval = 1; + + VECCOPY(loc, location); + VECCOPY(no, normal); + + Mat3MulVecfl(timat, no); + Normalize(no); + + *dist = new_dist; + } + } + } } } + + if (EditMesh) + { + EM_free_index_arrays(); + } + break; + } + case SCE_SNAP_MODE_VERTEX: + { + MVert *verts = dm->getVertArray(dm); + int *index_array = NULL; + int index = 0; + int i; + + if (EditMesh) + { + index_array = dm->getVertDataArray(dm, CD_ORIGINDEX); + EM_init_index_arrays(1, 0, 0); + } + + for( i = 0; i < totvert; i++) { + EditVert *eve = NULL; + MVert *v = verts + i; + + test = 1; /* reset for every vert */ + + if (EditMesh) + { + if (index_array) + { + index = index_array[i]; + } + else + { + index = i; + } + + if (index == ORIGINDEX_NONE) + { + test = 0; + } + else + { + eve = EM_get_vert_for_index(index); + + if (eve && eve->f & SELECT) + { + test = 0; + } + } + } + + + if (test) + { + float dvec[3]; + + VecSubf(dvec, v->co, ray_start_local); + + if (Inpf(ray_normal_local, dvec) > 0) + { + float location[3]; + float new_depth; + int screen_loc[2]; + int new_dist; + + VECCOPY(location, v->co); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + project_int(location, screen_loc); + new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); + + if (new_dist <= *dist && new_depth < *depth) + { + *depth = new_depth; + retval = 1; + + VECCOPY(loc, location); + + NormalShortToFloat(no, v->no); + Mat3MulVecfl(timat, no); + Normalize(no); + + *dist = new_dist; + } + } + } + } + + if (EditMesh) + { + EM_free_index_arrays(); + } + break; + } + case SCE_SNAP_MODE_EDGE: + { + MVert *verts = dm->getVertArray(dm); + MEdge *edges = dm->getEdgeArray(dm); + int totedge = dm->getNumEdges(dm); + int *index_array = NULL; + int index = 0; + int i; + + if (EditMesh) + { + index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX); + EM_init_index_arrays(0, 1, 0); + } + + for( i = 0; i < totedge; i++) { + EditEdge *eed = NULL; + MEdge *e = edges + i; + + test = 1; /* reset for every vert */ + + if (EditMesh) + { + if (index_array) + { + index = index_array[i]; + } + else + { + index = i; + } + + if (index == ORIGINDEX_NONE) + { + test = 0; + } + else + { + eed = EM_get_edge_for_index(index); + + if (eed && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT))) + { + test = 0; + } + } + } + + + if (test) + { + float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; + int result; + + VECCOPY(ray_end, ray_normal_local); + VecMulf(ray_end, 2000); + VecAddf(ray_end, ray_start_local, ray_end); + + result = LineIntersectLine(verts[e->v1].co, verts[e->v2].co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */ + + if (result) + { + float edge_loc[3], vec[3]; + float mul; + + /* check for behind ray_start */ + VecSubf(dvec, intersect, ray_start_local); + + VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co); + VecSubf(vec, intersect, verts[e->v2].co); + + mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); + + if (mul > 1) { + mul = 1; + VECCOPY(intersect, verts[e->v1].co); + } + else if (mul < 0) { + mul = 0; + VECCOPY(intersect, verts[e->v2].co); + } + + if (Inpf(ray_normal_local, dvec) > 0) + { + float location[3]; + float new_depth; + int screen_loc[2]; + int new_dist; + + VECCOPY(location, intersect); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + project_int(location, screen_loc); + new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); + + if (new_dist <= *dist && new_depth < *depth) + { + float n1[3], n2[3]; + + *depth = new_depth; + retval = 1; + + VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co); + VecSubf(vec, intersect, verts[e->v2].co); + + mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); + + NormalShortToFloat(n1, verts[e->v1].no); + NormalShortToFloat(n2, verts[e->v2].no); + VecLerpf(no, n2, n1, mul); + Normalize(no); + + VECCOPY(loc, location); + + Mat3MulVecfl(timat, no); + Normalize(no); + + *dist = new_dist; + } + } + } + } + } + + if (EditMesh) + { + EM_free_index_arrays(); + } + break; } - } - - if (EditMesh) - { - EM_free_index_arrays(); } } } diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 356a297b284..f457f9203ff 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -689,10 +689,6 @@ void viewmoveNDOFfly(int mode) if (G.vd->ndoffilter) filterNDOFvalues(fval); -// for(i=0;i<7;i++) printf("%f ",dval[i]); -// printf("\n"); - - // Scale input values // if(dval[6] == 0) return; // guard against divide by zero @@ -701,12 +697,6 @@ void viewmoveNDOFfly(int mode) // user scaling dval[i] = dval[i] * ndof_axis_scale[i]; - - // non-linear scaling - if(dval[i]<0.0f) - dval[i] = -1.0f * dval[i] * dval[i]; - else - dval[i] = dval[i] * dval[i]; } @@ -1216,18 +1206,16 @@ void viewmoveNDOF(int mode) // prevTime = now; // sbadjust *= 60 * frametime; /* normalize ndof device adjustments to 100Hz for framerate independence */ - /* fetch the current state of the ndof device */ + /* fetch the current state of the ndof device & enforce dominant mode if selected */ getndof(fval); - // printf(" motion command %f %f %f %f %f %f %f \n", fval[0], fval[1], fval[2], - // fval[3], fval[4], fval[5], fval[6]); - if (G.vd->ndoffilter) - filterNDOFvalues(fval); + if (G.vd->ndoffilter) + filterNDOFvalues(fval); // put scaling back here, was previously in ghostwinlay - fval[0] = fval[0] * (1.0f/1200.0f); - fval[1] = fval[1] * (1.0f/1200.0f); - fval[2] = fval[2] * (1.0f/1200.0f); + fval[0] = fval[0] * (1.0f/600.0f); + fval[1] = fval[1] * (1.0f/600.0f); + fval[2] = fval[2] * (1.0f/1100.0f); fval[3] = fval[3] * 0.00005f; fval[4] =-fval[4] * 0.00005f; fval[5] = fval[5] * 0.00005f; @@ -1255,14 +1243,16 @@ void viewmoveNDOF(int mode) VECCOPY(obofs, G.vd->ofs); } - /* calc an adjustment based on distance from camera */ - if (ob) { + /* calc an adjustment based on distance from camera + disabled per patch 14402 */ + d = 1.0f; + +/* if (ob) { VecSubf(diff, obofs, G.vd->ofs); d = VecLength(diff); } - else { - d = 1.0f; - } +*/ + reverse = (G.vd->persmat[2][1] < 0.0f) ? -1.0f : 1.0f; /*---------------------------------------------------- diff --git a/source/creator/creator.c b/source/creator/creator.c index 2e6b5d7353e..9589f1e3e94 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -195,7 +195,7 @@ static void print_help(void) printf (" (formats that can be compiled into blender, not available on all systems)\n"); printf (" \tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS\n"); printf (" -x \tSet option to add the file extension to the end of the file.\n"); - printf (" -t \tUse amount of for rendering.\n"); + printf (" -t \tUse amount of for rendering (background mode only).\n"); printf (" [1-8], 0 for systems processor count.\n"); printf ("\nAnimation playback options:\n"); printf (" -a \tPlayback , only operates this way when -b is not used.\n"); @@ -723,6 +723,8 @@ int main(int argc, char **argv) a++; if(G.background) { RE_set_max_threads(atoi(argv[a])); + } else { + printf("Warning: threads can only be set in background mode\n"); } break; case 'x': /* extension */ diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 06aa0609ad9..4af5ac4d5d2 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -165,20 +165,14 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, RAS_IRenderTools* rendertools = new KX_BlenderRenderTools(); RAS_IRasterizer* rasterizer = NULL; - // let's see if we want to use vertexarrays or not - int usevta = SYS_GetCommandLineInt(syshandle,"vertexarrays",1); - bool useVertexArrays = (usevta > 0); - - bool lock_arrays = (displaylists && useVertexArrays); - - if(displaylists){ - if (useVertexArrays) - rasterizer = new RAS_ListRasterizer(canvas, true, lock_arrays); + if(displaylists) { + if (GLEW_VERSION_1_1) + rasterizer = new RAS_ListRasterizer(canvas, true, true); else rasterizer = new RAS_ListRasterizer(canvas); } - else if (useVertexArrays && GLEW_VERSION_1_1) - rasterizer = new RAS_VAOpenGLRasterizer(canvas, lock_arrays); + else if (GLEW_VERSION_1_1) + rasterizer = new RAS_VAOpenGLRasterizer(canvas, false); else rasterizer = new RAS_OpenGLRasterizer(canvas); @@ -513,16 +507,14 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, RAS_IRenderTools* rendertools = new KX_BlenderRenderTools(); RAS_IRasterizer* rasterizer = NULL; - // let's see if we want to use vertexarrays or not - int usevta = SYS_GetCommandLineInt(syshandle,"vertexarrays",1); - bool useVertexArrays = (usevta > 0); - - bool lock_arrays = (displaylists && useVertexArrays); - - if(displaylists && !useVertexArrays) - rasterizer = new RAS_ListRasterizer(canvas); - else if (useVertexArrays && GLEW_VERSION_1_1) - rasterizer = new RAS_VAOpenGLRasterizer(canvas, lock_arrays); + if(displaylists) { + if (GLEW_VERSION_1_1) + rasterizer = new RAS_ListRasterizer(canvas, true, true); + else + rasterizer = new RAS_ListRasterizer(canvas); + } + else if (GLEW_VERSION_1_1) + rasterizer = new RAS_VAOpenGLRasterizer(canvas, false); else rasterizer = new RAS_OpenGLRasterizer(canvas); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 07a3649aa0f..73d2870720a 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -483,9 +483,9 @@ void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer) } } -void KX_BlenderRenderTools::Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text) +void KX_BlenderRenderTools::Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short texture_flag) { - m_filtermanager.EnableFilter(filtermode, pass, text); + m_filtermanager.EnableFilter(filtermode, pass, text, texture_flag); } void KX_BlenderRenderTools::Render2DFilters(RAS_ICanvas* canvas) diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index 31eaa14d66b..7748e31156d 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -101,7 +101,7 @@ public: virtual void MotionBlur(RAS_IRasterizer* rasterizer); - virtual void Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text); + virtual void Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short texture_flag); virtual void Render2DFilters(RAS_ICanvas* canvas); diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index ad126ebf123..5050da3fe7f 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -49,6 +49,7 @@ #include "BLI_arithb.h" #include "MT_Matrix4x4.h" #include "BKE_utildefines.h" +#include "FloatValue.h" #ifdef HAVE_CONFIG_H #include @@ -348,6 +349,18 @@ bool BL_ActionActuator::Update(double curtime, bool frame) break; } + /* Set the property if its defined */ + if (m_framepropname[0] != '\0') { + CValue* propowner = GetParent(); + CValue* oldprop = propowner->GetProperty(m_framepropname); + CValue* newval = new CFloatValue(m_localtime); + if (oldprop) { + oldprop->SetValue(newval); + } else { + propowner->SetProperty(m_framepropname, newval); + } + newval->Release(); + } if (bNegativeEvent) m_blendframe=0.0; @@ -446,6 +459,7 @@ PyMethodDef BL_ActionActuator::Methods[] = { {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, SetPriority_doc}, {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, SetFrame_doc}, {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc}, + {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, SetFrameProperty_doc}, {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc}, {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, GetAction_doc}, @@ -455,6 +469,7 @@ PyMethodDef BL_ActionActuator::Methods[] = { {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, GetPriority_doc}, {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, GetFrame_doc}, {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc}, + {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, GetFrameProperty_doc}, {"setChannel", (PyCFunction) BL_ActionActuator::sPySetChannel, METH_VARARGS, SetChannel_doc}, // {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS}, {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, GetType_doc}, @@ -502,6 +517,21 @@ PyObject* BL_ActionActuator::PyGetProperty(PyObject* self, return result; } +/* getProperty */ +char BL_ActionActuator::GetFrameProperty_doc[] = +"getFrameProperty()\n" +"\tReturns the name of the property, that is set to the current frame number.\n"; + +PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* self, + PyObject* args, + PyObject* kwds) { + PyObject *result; + + result = Py_BuildValue("s", (const char *)m_framepropname); + + return result; +} + /* getFrame */ char BL_ActionActuator::GetFrame_doc[] = "getFrame()\n" @@ -763,6 +793,25 @@ PyObject* BL_ActionActuator::PySetProperty(PyObject* self, return Py_None; } +/* setFrameProperty */ +char BL_ActionActuator::SetFrameProperty_doc[] = +"setFrameProperty(prop)\n" +"\t - prop : A string specifying the property of the frame set up update.\n"; + +PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* self, + PyObject* args, + PyObject* kwds) { + char *string; + + if (PyArg_ParseTuple(args,"s",&string)) + { + m_framepropname = string; + } + + Py_INCREF(Py_None); + return Py_None; +} + /* PyObject* BL_ActionActuator::PyGetChannel(PyObject* self, PyObject* args, diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 62edcc7fad7..190f727c9c3 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -40,6 +40,7 @@ public: Py_Header; BL_ActionActuator(SCA_IObject* gameobj, const STR_String& propname, + const STR_String& framepropname, float starttime, float endtime, struct bAction *action, @@ -67,7 +68,8 @@ public: m_blendpose(NULL), m_userpose(NULL), m_action(action), - m_propname(propname) + m_propname(propname), + m_framepropname(framepropname) { }; virtual ~BL_ActionActuator(); @@ -84,6 +86,7 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,SetEnd); KX_PYMETHOD_DOC(BL_ActionActuator,SetFrame); KX_PYMETHOD_DOC(BL_ActionActuator,SetProperty); + KX_PYMETHOD_DOC(BL_ActionActuator,SetFrameProperty); KX_PYMETHOD_DOC(BL_ActionActuator,SetBlendtime); KX_PYMETHOD_DOC(BL_ActionActuator,SetChannel); @@ -94,6 +97,7 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,GetEnd); KX_PYMETHOD_DOC(BL_ActionActuator,GetFrame); KX_PYMETHOD_DOC(BL_ActionActuator,GetProperty); + KX_PYMETHOD_DOC(BL_ActionActuator,GetFrameProperty); // KX_PYMETHOD(BL_ActionActuator,GetChannel); KX_PYMETHOD_DOC(BL_ActionActuator,GetType); KX_PYMETHOD_DOC(BL_ActionActuator,SetType); @@ -138,6 +142,7 @@ protected: struct bPose* m_userpose; struct bAction *m_action; STR_String m_propname; + STR_String m_framepropname; }; enum { diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 32946267202..665783a1ba5 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1668,6 +1668,8 @@ static KX_GameObject *gameobject_from_blenderobject( BL_ShapeDeformer *dcont = new BL_ShapeDeformer((BL_DeformableGameObject*)gameobj, ob, (BL_SkinMeshObject*)meshobj); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; + if (bHasArmature) + dcont->LoadShapeDrivers(ob->parent); } else if (bHasArmature) { BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj ); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; @@ -2324,6 +2326,14 @@ void BL_ConvertBlenderObjects(struct Main* maggie, bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,activeLayerBitInfo,isInActiveLayer,canvas,converter); } + // apply the initial state to controllers + for ( i=0;iGetCount();i++) + { + KX_GameObject* gameobj = static_cast(logicbrick_conversionlist->GetValue(i)); + struct Object* blenderobj = converter->FindBlenderObject(gameobj); + gameobj->SetState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); + } + #endif //CONVERT_LOGIC logicbrick_conversionlist->Release(); diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index 3ae634905b9..eb5c1467ea5 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -44,9 +44,12 @@ #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_ipo_types.h" +#include "DNA_curve_types.h" #include "BKE_armature.h" #include "BKE_action.h" #include "BKE_key.h" +#include "BKE_ipo.h" #include "MT_Point3.h" extern "C"{ @@ -78,11 +81,55 @@ void BL_ShapeDeformer::ProcessReplica() { } +bool BL_ShapeDeformer::LoadShapeDrivers(Object* arma) +{ + IpoCurve *icu; + + m_shapeDrivers.clear(); + // check if this mesh has armature driven shape keys + if (m_bmesh->key->ipo) { + for(icu= (IpoCurve*)m_bmesh->key->ipo->curve.first; icu; icu= (IpoCurve*)icu->next) { + if(icu->driver && + (icu->flag & IPO_MUTE) == 0 && + icu->driver->type == IPO_DRIVER_TYPE_NORMAL && + icu->driver->ob == arma && + icu->driver->blocktype == ID_AR) { + // this shape key ipo curve has a driver on the parent armature + // record this curve in the shape deformer so that the corresponding + m_shapeDrivers.push_back(icu); + } + } + } + return !m_shapeDrivers.empty(); +} + +bool BL_ShapeDeformer::ExecuteShapeDrivers(void) +{ + if (!m_shapeDrivers.empty() && PoseUpdated()) { + vector::iterator it; + void *poin; + int type; + for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) { + // no need to set a specific time: this curve has a driver + IpoCurve *icu = *it; + calc_icu(icu, 1.0f); + poin = get_ipo_poin((ID*)m_bmesh->key, icu, &type); + if (poin) + write_ipo_poin(poin, type, icu->curval); + } + ForceUpdate(); + return true; + } + return false; +} + bool BL_ShapeDeformer::Update(void) { bool bShapeUpdate = false; bool bSkinUpdate = false; + ExecuteShapeDrivers(); + /* See if the object shape has changed */ if (m_lastShapeUpdate != m_gameobj->GetLastFrame()) { /* the key coefficient have been set already, we just need to blend the keys */ diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 9bbdde3fb2c..9f8361dbaca 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -38,6 +38,7 @@ #include "BL_DeformableGameObject.h" #include +struct IpoCurve; class BL_ShapeDeformer : public BL_SkinDeformer { @@ -82,8 +83,16 @@ public: virtual ~BL_ShapeDeformer(); bool Update (void); + bool LoadShapeDrivers(Object* arma); + bool ExecuteShapeDrivers(void); + + void ForceUpdate() + { + m_lastShapeUpdate = -1.0; + }; protected: + vector m_shapeDrivers; double m_lastShapeUpdate; BL_DeformableGameObject* m_gameobj; diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index 1015221c392..dd7119b1031 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -149,12 +149,9 @@ void BL_SkinDeformer::ProcessReplica() bool BL_SkinDeformer::Update(void) { /* See if the armature has been updated for this frame */ - if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()){ + if (PoseUpdated()){ float obmat[4][4]; // the original object matrice - /* Do all of the posing necessary */ - m_armobj->ApplyPose(); - /* XXX note: where_is_pose() (from BKE_armature.h) calculates all matrices needed to start deforming */ /* but it requires the blender object pointer... */ diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index 603e716fb1e..c5568c049cb 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -79,6 +79,14 @@ public: virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); + bool PoseUpdated(void) + { + if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) { + m_armobj->ApplyPose(); + return true; + } + return false; + } void ForceUpdate() { diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index f219c3a1472..ea26c55a44e 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -56,11 +56,13 @@ #include "KX_ConstraintActuator.h" #include "KX_CameraActuator.h" #include "KX_GameActuator.h" +#include "KX_StateActuator.h" #include "KX_VisibilityActuator.h" #include "KX_SCA_AddObjectActuator.h" #include "KX_SCA_EndObjectActuator.h" #include "KX_SCA_ReplaceMeshActuator.h" #include "KX_ParentActuator.h" +#include "KX_SCA_DynamicActuator.h" #include "KX_Scene.h" #include "KX_KetsjiEngine.h" @@ -136,6 +138,7 @@ void BL_ConvertActuators(char* maggiename, MT_Vector3 angvelvec ( KX_BLENDERTRUNC(obact->angularvelocity[0]), KX_BLENDERTRUNC(obact->angularvelocity[1]), KX_BLENDERTRUNC(obact->angularvelocity[2])); + short damping = obact->damping; drotvec /= BLENDER_HACK_DTIME; //drotvec /= BLENDER_HACK_DTIME; @@ -156,7 +159,7 @@ void BL_ConvertActuators(char* maggiename, bitLocalFlag.DRot = bool((obact->flag & ACT_DROT_LOCAL)!=0); bitLocalFlag.LinearVelocity = bool((obact->flag & ACT_LIN_VEL_LOCAL)!=0); bitLocalFlag.AngularVelocity = bool((obact->flag & ACT_ANG_VEL_LOCAL)!=0); - + bitLocalFlag.ClampVelocity = bool((obact->flag & ACT_CLAMP_VEL)!=0); bitLocalFlag.AddOrSetLinV = bool((obact->flag & ACT_ADD_LIN_VEL)!=0); @@ -167,6 +170,7 @@ void BL_ConvertActuators(char* maggiename, drotvec.getValue(), linvelvec.getValue(), angvelvec.getValue(), + damping, bitLocalFlag ); baseact = tmpbaseact; @@ -177,10 +181,12 @@ void BL_ConvertActuators(char* maggiename, if (blenderobject->type==OB_ARMATURE){ bActionActuator* actact = (bActionActuator*) bact->data; STR_String propname = (actact->name ? actact->name : ""); + STR_String propframe = (actact->frameProp ? actact->frameProp : ""); BL_ActionActuator* tmpbaseact = new BL_ActionActuator( gameobj, propname, + propframe, actact->sta, actact->end, actact->act, @@ -597,6 +603,15 @@ void BL_ConvertActuators(char* maggiename, blenderobject->upflag ); baseact = tmptrackact; + break; + } + case ACT_EDOB_DYNAMICS: + { + KX_SCA_DynamicActuator* tmpdynact + = new KX_SCA_DynamicActuator(gameobj, + editobact->dyn_operation + ); + baseact = tmpdynact; } } break; @@ -857,7 +872,19 @@ void BL_ConvertActuators(char* maggiename, baseact = tmp_vis_act; } break; - + + case ACT_STATE: + { + bStateActuator *sta_act = (bStateActuator *) bact->data; + KX_StateActuator * tmp_sta_act = NULL; + + tmp_sta_act = + new KX_StateActuator(gameobj, sta_act->type, sta_act->mask); + + baseact = tmp_sta_act; + } + break; + case ACT_2DFILTER: { bTwoDFilterActuator *_2dfilter = (bTwoDFilterActuator*) bact->data; @@ -917,7 +944,7 @@ void BL_ConvertActuators(char* maggiename, } tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, - _2dfilter->float_arg,_2dfilter->int_arg,ketsjiEngine->GetRasterizer(),rendertools); + _2dfilter->float_arg,_2dfilter->int_arg,_2dfilter->texture_flag,ketsjiEngine->GetRasterizer(),rendertools); if (_2dfilter->text) { diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp index a26cfa95b6d..da490b4ee85 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.cpp +++ b/source/gameengine/Converter/KX_ConvertControllers.cpp @@ -35,6 +35,10 @@ // Controller #include "SCA_ANDController.h" #include "SCA_ORController.h" +#include "SCA_NANDController.h" +#include "SCA_NORController.h" +#include "SCA_XORController.h" +#include "SCA_XNORController.h" #include "SCA_PythonController.h" #include "SCA_ExpressionController.h" @@ -112,6 +116,30 @@ void BL_ConvertControllers( LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); break; } + case CONT_LOGIC_NAND: + { + gamecontroller = new SCA_NANDController(gameobj); + LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); + break; + } + case CONT_LOGIC_NOR: + { + gamecontroller = new SCA_NORController(gameobj); + LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); + break; + } + case CONT_LOGIC_XOR: + { + gamecontroller = new SCA_XORController(gameobj); + LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); + break; + } + case CONT_LOGIC_XNOR: + { + gamecontroller = new SCA_XNORController(gameobj); + LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); + break; + } case CONT_EXPRESSION: { bExpressionCont* bexpcont = (bExpressionCont*) bcontr->data; @@ -161,6 +189,7 @@ void BL_ConvertControllers( if (gamecontroller) { gamecontroller->SetExecutePriority(executePriority++); + gamecontroller->SetState(bcontr->state_mask); STR_String uniquename = bcontr->name; uniquename += "#CONTR#"; uniqueint++; diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 80fa3838d60..e7e4eeae7d2 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -251,6 +251,7 @@ void BL_ConvertSensors(struct Object* blenderobject, bool neg_pulsemode = false; int frequency = 0; bool invert = false; + bool level = false; while(sens) { @@ -263,7 +264,8 @@ void BL_ConvertSensors(struct Object* blenderobject, frequency = sens->freq; invert = !(sens->invert == 0); - + level = !(sens->level == 0); + switch (sens->type) { case SENS_ALWAYS: @@ -711,6 +713,7 @@ void BL_ConvertSensors(struct Object* blenderobject, neg_pulsemode, frequency); gamesensor->SetInvert(invert); + gamesensor->SetLevel(level); gamesensor->SetName(STR_String(sens->name)); gameobj->AddSensor(gamesensor); diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 56208ab4ad5..f0195d5df82 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -520,11 +520,6 @@ void CValue::CloneProperties(CValue *replica) } - - - - - double* CValue::GetVector3(bool bGetTransformedVec) { assertd(false); // don;t get vector from me @@ -775,6 +770,25 @@ int CValue::_setattr(const STR_String& attr,PyObject* pyobj) //PyObjectPlus::_setattr(attr,value); return 0; }; + +PyObject* CValue::ConvertKeysToPython( void ) +{ + PyObject *pylist = PyList_New( 0 ); + PyObject *pystr; + + if (m_pNamedPropertyArray) + { + for ( std::map::iterator it = m_pNamedPropertyArray->begin(); + !(it == m_pNamedPropertyArray->end());it++) + { + pystr = PyString_FromString( (*it).first ); + PyList_Append(pylist, pystr); + Py_DECREF( pystr ); + } + } + return pylist; +} + /* PyObject* CValue::PyMake(PyObject* ignored,PyObject* args) { diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index ccb9c34749d..561e5521d60 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -253,6 +253,8 @@ public: virtual int _delattr(const STR_String& attr); virtual int _setattr(const STR_String& attr,PyObject* value); + virtual PyObject* ConvertKeysToPython( void ); + KX_PYMETHOD(CValue,GetName); #else diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index f3b5b1fdda2..56249bb52ec 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -18,6 +18,7 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( short flag, float float_arg, int int_arg, + short texture_flag, RAS_IRasterizer* rasterizer, RAS_IRenderTools* rendertools, PyTypeObject* T) @@ -25,6 +26,7 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( m_type(type), m_flag(flag), m_int_arg(int_arg), + m_texture_flag(texture_flag), m_float_arg(float_arg), m_rasterizer(rasterizer), m_rendertools(rendertools) @@ -72,7 +74,7 @@ bool SCA_2DFilterActuator::Update() } else if(m_type < RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS) { - m_rendertools->Update2DFilter(m_type, m_int_arg, m_shaderText); + m_rendertools->Update2DFilter(m_type, m_int_arg, m_shaderText, m_texture_flag); } return true; } diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h index 7b0cfff951e..451a7b9491a 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h @@ -16,6 +16,7 @@ private: short m_flag; float m_float_arg; int m_int_arg; + short m_texture_flag; STR_String m_shaderText; RAS_IRasterizer* m_rasterizer; RAS_IRenderTools* m_rendertools; @@ -28,6 +29,7 @@ public: short flag, float float_arg, int int_arg, + short texture_flag, RAS_IRasterizer* rasterizer, RAS_IRenderTools* rendertools, PyTypeObject* T=&Type diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index 67df5d091ab..f9fbf2387c4 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -53,10 +53,13 @@ SCA_AlwaysSensor::SCA_AlwaysSensor(class SCA_EventManager* eventmgr, : SCA_ISensor(gameobj,eventmgr, T) { //SetDrawColor(255,0,0); - m_alwaysresult = true; + Init(); } - +void SCA_AlwaysSensor::Init() +{ + m_alwaysresult = true; +} SCA_AlwaysSensor::~SCA_AlwaysSensor() { diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h index 474ed025432..8bf2a8aa98e 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h @@ -45,6 +45,8 @@ public: virtual CValue* GetReplica(); virtual bool Evaluate(CValue* event); virtual bool IsPositiveTrigger(); + virtual void Init(); + /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp index 568d0eb4a89..eeca2d7b44c 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.cpp +++ b/source/gameengine/GameLogic/SCA_IActuator.cpp @@ -36,6 +36,7 @@ using namespace std; SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj, PyTypeObject* T) : + m_links(0), SCA_ILogicBrick(gameobj,T) { // nothing to do @@ -109,3 +110,12 @@ SCA_IActuator::~SCA_IActuator() RemoveAllEvents(); } +void SCA_IActuator::DecLink() +{ + m_links--; + if (m_links < 0) + { + printf("Warning: actuator %s has negative m_links: %d\n", m_name.Ptr(), m_links); + m_links = 0; + } +} diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index b802aa4b298..774b27c5ad4 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -34,8 +34,11 @@ class SCA_IActuator : public SCA_ILogicBrick { + friend class SCA_LogicManager; protected: std::vector m_events; + int m_links; // number of active links to controllers + // when 0, the actuator is automatically stopped void RemoveAllEvents(); public: @@ -83,6 +86,10 @@ public: */ bool IsNegativeEvent() const; virtual ~SCA_IActuator(); + + void IncLink() { m_links++; } + void DecLink(); + bool IsNoLink() const { return !m_links; } }; #endif //__KX_IACTUATOR diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index 5cb62678c6b..bbe5a51db3c 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -29,6 +29,7 @@ #include "SCA_IController.h" #include "SCA_LogicManager.h" #include "SCA_IActuator.h" +#include "SCA_ISensor.h" #ifdef HAVE_CONFIG_H #include @@ -37,6 +38,7 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj, PyTypeObject* T) : + m_statemask(0), SCA_ILogicBrick(gameobj,T) { } @@ -45,6 +47,7 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj, SCA_IController::~SCA_IController() { + UnlinkAllActuators(); } @@ -65,6 +68,14 @@ const std::vector& SCA_IController::GetLinkedActuators() void SCA_IController::UnlinkAllSensors() { + if (IsActive()) + { + std::vector::iterator sensit; + for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) + { + (*sensit)->DecLink(); + } + } m_linkedsensors.clear(); } @@ -72,6 +83,14 @@ void SCA_IController::UnlinkAllSensors() void SCA_IController::UnlinkAllActuators() { + if (IsActive()) + { + std::vector::iterator actit; + for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit) + { + (*actit)->DecLink(); + } + } m_linkedactuators.clear(); } @@ -95,26 +114,94 @@ void SCA_IController::Trigger(SCA_LogicManager* logicmgr) void SCA_IController::LinkToActuator(SCA_IActuator* actua) { m_linkedactuators.push_back(actua); + if (IsActive()) + { + actua->IncLink(); + } } void SCA_IController::UnlinkActuator(class SCA_IActuator* actua) { std::vector::iterator actit; - std::vector::iterator actfound = m_linkedactuators.end(); for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit) { if ((*actit) == actua) - actfound = actit; + { + break; + } } - if (!(actfound==m_linkedactuators.end())) + if (!(actit==m_linkedactuators.end())) { - m_linkedactuators.erase(actfound); + m_linkedactuators.erase(actit); + if (IsActive()) + { + (*actit)->DecLink(); + } } - } void SCA_IController::LinkToSensor(SCA_ISensor* sensor) { m_linkedsensors.push_back(sensor); + if (IsActive()) + { + sensor->IncLink(); + } } + +void SCA_IController::UnlinkSensor(class SCA_ISensor* sensor) +{ + std::vector::iterator sensit; + for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) + { + if ((*sensit) == sensor) + { + break; + } + + } + if (!(sensit==m_linkedsensors.end())) + { + m_linkedsensors.erase(sensit); + if (IsActive()) + { + (*sensit)->DecLink(); + } + } +} + +void SCA_IController::ApplyState(unsigned int state) +{ + std::vector::iterator actit; + std::vector::iterator sensit; + + if (m_statemask & state) + { + if (!IsActive()) + { + // reactive the controller, all the links to actuator are valid again + for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit) + { + (*actit)->IncLink(); + } + for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) + { + (*sensit)->IncLink(); + } + SetActive(true); + } + } else if (IsActive()) + { + for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit) + { + (*actit)->DecLink(); + } + for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) + { + (*sensit)->DecLink(); + } + SetActive(false); + } +} + diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h index 79e956dec4e..f67c0942eb4 100644 --- a/source/gameengine/GameLogic/SCA_IController.h +++ b/source/gameengine/GameLogic/SCA_IController.h @@ -36,6 +36,7 @@ class SCA_IController : public SCA_ILogicBrick protected: std::vector m_linkedsensors; std::vector m_linkedactuators; + unsigned int m_statemask; public: SCA_IController(SCA_IObject* gameobj,PyTypeObject* T); virtual ~SCA_IController(); @@ -47,6 +48,9 @@ public: void UnlinkAllSensors(); void UnlinkAllActuators(); void UnlinkActuator(class SCA_IActuator* actua); + void UnlinkSensor(class SCA_ISensor* sensor); + void SetState(unsigned int state) { m_statemask = state; } + void ApplyState(unsigned int state); }; diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 6df9e23f3fa..826e7bbdf0e 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -40,7 +40,7 @@ MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); -SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T) +SCA_IObject::SCA_IObject(PyTypeObject* T): m_state(0), CValue(T) { m_suspended = false; } @@ -329,6 +329,17 @@ void SCA_IObject::Resume(void) } } +void SCA_IObject::SetState(unsigned int state) +{ + m_state = state; + // update the status of the controllers + SCA_ControllerList::iterator contit; + for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + { + (*contit)->ApplyState(m_state); + } +} + /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index e8251e0ceaa..07b4310a91e 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -67,7 +67,12 @@ protected: * Ignore updates? */ bool m_suspended; - + + /** + * current state = bit mask of state that are active + */ + unsigned int m_state; + public: SCA_IObject(PyTypeObject* T=&Type); @@ -111,7 +116,17 @@ public: * Resume progress */ void Resume(void); - + + /** + * Set the object state + */ + void SetState(unsigned int state); + + /** + * Get the object state + */ + unsigned int GetState(void) { return m_state; } + // const class MT_Point3& ConvertPythonPylist(PyObject* pylist); // here come the python forwarded methods diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 9fdee0c19da..6cfae9d8919 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -52,8 +52,10 @@ SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj, SCA_ILogicBrick(gameobj,T), m_triggered(false) { + m_links = 0; m_suspended = false; m_invert = false; + m_level = false; m_pos_ticks = 0; m_neg_ticks = 0; m_pos_pulsemode = false; @@ -94,6 +96,10 @@ void SCA_ISensor::SetInvert(bool inv) { m_invert = inv; } +void SCA_ISensor::SetLevel(bool lvl) { + m_level = lvl; +} + float SCA_ISensor::GetNumber() { return IsPositiveTrigger(); @@ -111,6 +117,25 @@ void SCA_ISensor::Resume() { m_suspended = false; } +void SCA_ISensor::Init() { + printf("Sensor %s has no init function, please report this bug to Blender.org\n", m_name); +} + +void SCA_ISensor::DecLink() { + m_links--; + if (m_links < 0) + { + printf("Warning: sensor %s has negative m_links: %d\n", m_name.Ptr(), m_links); + m_links = 0; + } + if (!m_links) + { + // sensor is detached from all controllers, initialize it so that it + // is fresh as at startup when it is reattached again. + Init(); + } +} + /* python integration */ PyTypeObject SCA_ISensor::Type = { @@ -157,6 +182,10 @@ PyMethodDef SCA_ISensor::Methods[] = { METH_VARARGS, GetInvert_doc}, {"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert, METH_VARARGS, SetInvert_doc}, + {"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel, + METH_VARARGS, GetLevel_doc}, + {"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel, + METH_VARARGS, SetLevel_doc}, {NULL,NULL} //Sentinel }; @@ -177,7 +206,8 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) { // calculate if a __triggering__ is wanted - if (!m_suspended) { + // don't evaluate a sensor that is not connected to any controller + if (m_links && !m_suspended) { bool result = this->Evaluate(event); if (result) { logicmgr->AddActivatedSensor(this); @@ -307,6 +337,31 @@ PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwd Py_Return; } +char SCA_ISensor::GetLevel_doc[] = +"getLevel()\n" +"\tReturns whether this sensor is a level detector or a edge detector.\n" +"\tIt makes a difference only in case of logic state transition (state actuator).\n" +"\tA level detector will immediately generate a pulse if the condition for the\n" +"\tdetector is met when entering the state. A edge detector will wait for an off-on\n" +"\ttransition to occur.\n" +"\tOnly some sensors implement this feature: keyboard.\n"; +PyObject* SCA_ISensor::PyGetLevel(PyObject* self, PyObject* args, PyObject* kwds) +{ + return BoolToPyArg(m_level); +} + +char SCA_ISensor::SetLevel_doc[] = +"setLevel(level?)\n" +"\t- level?: Detect level instead of edge? (KX_TRUE, KX_FALSE)\n" +"\tSet whether to detect level or edge transition when entering a state.\n"; +PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds) +{ + int pyarg = 0; + if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } + m_level = PyArgToBool(pyarg); + Py_Return; +} + char SCA_ISensor::GetUseNegPulseMode_doc[] = "getUseNegPulseMode()\n" "\tReturns whether negative pulse mode is active.\n"; diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index e14fb34241a..3527b87ebdb 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -61,9 +61,15 @@ class SCA_ISensor : public SCA_ILogicBrick /** invert the output signal*/ bool m_invert; + /** detect level instead of edge*/ + bool m_level; + /** Sensor must ignore updates? */ bool m_suspended; + /** number of connections to controller */ + int m_links; + /** Pass the activation on to the logic manager.*/ void SignalActivation(class SCA_LogicManager* logicmgr); @@ -81,6 +87,7 @@ public: void Activate(class SCA_LogicManager* logicmgr,CValue* event); virtual bool Evaluate(CValue* event) = 0; virtual bool IsPositiveTrigger(); + virtual void Init(); virtual PyObject* _getattr(const STR_String& attr); virtual CValue* GetReplica()=0; @@ -101,6 +108,8 @@ public: virtual void Delete() { Release(); } /** Set inversion of pulses on or off. */ void SetInvert(bool inv); + /** set the level detection on or off */ + void SetLevel(bool lvl); void RegisterToManager(); virtual float GetNumber(); @@ -114,6 +123,12 @@ public: /** Resume sensing. */ void Resume(); + void IncLink() + { m_links++; } + void DecLink(); + bool IsNoLink() const + { return !m_links; } + /* Python functions: */ KX_PYMETHOD_DOC(SCA_ISensor,IsPositive); KX_PYMETHOD_DOC(SCA_ISensor,GetUsePosPulseMode); @@ -124,6 +139,8 @@ public: KX_PYMETHOD_DOC(SCA_ISensor,SetUseNegPulseMode); KX_PYMETHOD_DOC(SCA_ISensor,GetInvert); KX_PYMETHOD_DOC(SCA_ISensor,SetInvert); + KX_PYMETHOD_DOC(SCA_ISensor,GetLevel); + KX_PYMETHOD_DOC(SCA_ISensor,SetLevel); }; diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index b0e7fee130d..8668c22f044 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -64,9 +64,13 @@ std::cout << " button flag "<< m_buttonf << std::endl; std::cout << " hat " << m_hat << std::endl; std::cout << " hat flag " << m_hatf << std::endl; */ - m_istrig=0; + Init(); } +void SCA_JoystickSensor::Init() +{ + m_istrig=(m_invert)?1:0; +} SCA_JoystickSensor::~SCA_JoystickSensor() { diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index 2fbe1edf1e7..69068da6494 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -95,6 +95,7 @@ public: virtual bool Evaluate(CValue* event); virtual bool IsPositiveTrigger(); + virtual void Init(); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index f13b1bcf4c9..43ce25f94df 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -62,7 +62,7 @@ SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr, if (hotkey == SCA_IInputDevice::KX_ESCKEY) keybdmgr->GetInputDevice()->HookEscape(); // SetDrawColor(0xff0000ff); - m_val=0; + Init(); } @@ -71,7 +71,14 @@ SCA_KeyboardSensor::~SCA_KeyboardSensor() { } - +void SCA_KeyboardSensor::Init() +{ + // this function is used when the sensor is disconnected from all controllers + // by the state engine. It reinitializes the sensor as if it was just created. + // However, if the target key is pressed when the sensor is reactivated, it + // will not generated an event (see remark in Evaluate()). + m_val = (m_invert)?1:0; +} CValue* SCA_KeyboardSensor::GetReplica() { @@ -169,10 +176,10 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval) { if (m_val == 0) { - //see comment below - //m_val = 1; - //result = true; - ; + if (m_level) { + m_val = 1; + result = true; + } } } else { @@ -222,15 +229,11 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval) { if (m_val == 0) { - //hmm, this abnormal situation may occur in the following cases: - //- the key was pressed while the scene was suspended - //- this is a new scene and the key is active from the start - //In the second case, it's dangerous to activate the sensor - //(think of a key to go to next scene) - //What we really need is a edge/level flag in the key sensor - //m_val = 1; - //result = true; - ; + if (m_level) + { + m_val = 1; + result = true; + } } } } diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index e87eddecd32..b86f6931d27 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -114,6 +114,8 @@ public: PyTypeObject* T=&Type ); virtual ~SCA_KeyboardSensor(); virtual CValue* GetReplica(); + virtual void Init(); + short int GetHotkey(); virtual bool Evaluate(CValue* event); diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index 49f01d643e5..fb1a2c29eb6 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -165,6 +165,11 @@ void* SCA_LogicManager::FindBlendObjByGameMeshName(const STR_String& gamemeshnam void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor) { + controllerlist contlist = m_sensorcontrollermapje[sensor]; + for (controllerlist::const_iterator c= contlist.begin();!(c==contlist.end());c++) + { + (*c)->UnlinkSensor(sensor); + } m_sensorcontrollermapje.erase(sensor); for (vector::const_iterator ie=m_eventmanagers.begin(); @@ -176,6 +181,8 @@ void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor) void SCA_LogicManager::RemoveController(SCA_IController* controller) { + controller->UnlinkAllSensors(); + controller->UnlinkAllActuators(); std::map::iterator sit; for (sit = m_sensorcontrollermapje.begin();!(sit==m_sensorcontrollermapje.end());++sit) { @@ -236,7 +243,8 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) !(c==contlist.end());c++) { SCA_IController* contr = *c;//controllerarray->at(c); - triggeredControllerSet.insert(SmartControllerPtr(contr,0)); + if (contr->IsActive()) + triggeredControllerSet.insert(SmartControllerPtr(contr,0)); } //sensor->SetActive(false); } @@ -273,6 +281,16 @@ void SCA_LogicManager::UpdateFrame(double curtime, bool frame) (*ia)->SetActive(false); //m_activeactuators.pop_back(); + } else if ((*ia)->IsNoLink()) + { + // This actuator has no more links but it still active + // make sure it will get a negative event on next frame to stop it + // Do this check after Update() rather than before to make sure + // that all the actuators that are activated at same time than a state + // actuator have a chance to execute. + CValue* event = new CBoolValue(false); + (*ia)->RemoveAllEvents(); + (*ia)->AddEvent(event); } } diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 8810b7470ed..42d35837489 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -58,7 +58,6 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, { m_mousemode = mousemode; m_triggermode = true; - m_val = 0; /* stores the latest attribute */ switch (m_mousemode) { case KX_MOUSESENSORMODE_LEFTBUTTON: @@ -79,7 +78,12 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, default: ; /* ignore, no hotkey */ } + Init(); +} +void SCA_MouseSensor::Init() +{ + m_val = (m_invert)?1:0; /* stores the latest attribute */ } SCA_MouseSensor::~SCA_MouseSensor() @@ -164,10 +168,11 @@ bool SCA_MouseSensor::Evaluate(CValue* event) { if (m_val == 0) { - //dangerous - //m_val = 1; - //result = true; - ; + if (m_level) + { + m_val = 1; + result = true; + } } } else { diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 86c9d96a800..26a1c5e3fd2 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -96,7 +96,7 @@ class SCA_MouseSensor : public SCA_ISensor virtual ~SCA_MouseSensor(); virtual CValue* GetReplica(); virtual bool Evaluate(CValue* event); - + virtual void Init(); virtual bool IsPositiveTrigger(); short int GetModeKey(); SCA_IInputDevice::KX_EnumInputs GetHotKey(); diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp new file mode 100644 index 00000000000..5b869ee8298 --- /dev/null +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -0,0 +1,144 @@ +/** + * 'Nand' together all inputs + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "SCA_NANDController.h" +#include "SCA_ISensor.h" +#include "SCA_LogicManager.h" +#include "BoolValue.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* ------------------------------------------------------------------------- */ +/* Native functions */ +/* ------------------------------------------------------------------------- */ + +SCA_NANDController::SCA_NANDController(SCA_IObject* gameobj, + PyTypeObject* T) + : + SCA_IController(gameobj,T) +{ +} + + + +SCA_NANDController::~SCA_NANDController() +{ +} + + + +void SCA_NANDController::Trigger(SCA_LogicManager* logicmgr) +{ + + bool sensorresult = false; + + for (vector::const_iterator is=m_linkedsensors.begin(); + !(is==m_linkedsensors.end());is++) + { + SCA_ISensor* sensor = *is; + if (!sensor->IsPositiveTrigger()) + { + sensorresult = true; + break; + } + } + + CValue* newevent = new CBoolValue(sensorresult); + + for (vector::const_iterator i=m_linkedactuators.begin(); + !(i==m_linkedactuators.end());i++) + { + SCA_IActuator* actua = *i;//m_linkedactuators.at(i); + logicmgr->AddActiveActuator(actua,newevent); + } + + // every actuator that needs the event, has a it's own reference to it now so + // release it (so to be clear: if there is no actuator, it's deleted right now) + newevent->Release(); + +} + + + +CValue* SCA_NANDController::GetReplica() +{ + CValue* replica = new SCA_NANDController(*this); + // this will copy properties and so on... + CValue::AddDataToReplica(replica); + + return replica; +} + + + +/* ------------------------------------------------------------------------- */ +/* Python functions */ +/* ------------------------------------------------------------------------- */ + +/* Integration hooks ------------------------------------------------------- */ +PyTypeObject SCA_NANDController::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "SCA_NANDController", + sizeof(SCA_NANDController), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject SCA_NANDController::Parents[] = { + &SCA_NANDController::Type, + &SCA_IController::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; + +PyMethodDef SCA_NANDController::Methods[] = { + {NULL,NULL} //Sentinel +}; + +PyObject* SCA_NANDController::_getattr(const STR_String& attr) { + _getattr_up(SCA_IController); +} + +/* eof */ diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h new file mode 100644 index 00000000000..1193ff64f07 --- /dev/null +++ b/source/gameengine/GameLogic/SCA_NANDController.h @@ -0,0 +1,56 @@ +/** + * SCA_NANDController.h + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_NANDCONTROLLER +#define __KX_NANDCONTROLLER + +#include "SCA_IController.h" + +class SCA_NANDController : public SCA_IController +{ + Py_Header; + //virtual void Trigger(class SCA_LogicManager* logicmgr); +public: + SCA_NANDController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + virtual ~SCA_NANDController(); + virtual CValue* GetReplica(); + virtual void Trigger(SCA_LogicManager* logicmgr); + + /* --------------------------------------------------------------------- */ + /* Python interface ---------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + virtual PyObject* _getattr(const STR_String& attr); + +}; + +#endif //__KX_NANDCONTROLLER + diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp new file mode 100644 index 00000000000..2866dec0b74 --- /dev/null +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -0,0 +1,144 @@ +/** + * 'Nor' together all inputs + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "SCA_NORController.h" +#include "SCA_ISensor.h" +#include "SCA_LogicManager.h" +#include "BoolValue.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* ------------------------------------------------------------------------- */ +/* Native functions */ +/* ------------------------------------------------------------------------- */ + +SCA_NORController::SCA_NORController(SCA_IObject* gameobj, + PyTypeObject* T) + : + SCA_IController(gameobj,T) +{ +} + + + +SCA_NORController::~SCA_NORController() +{ +} + + + +void SCA_NORController::Trigger(SCA_LogicManager* logicmgr) +{ + + bool sensorresult = true; + + for (vector::const_iterator is=m_linkedsensors.begin(); + !(is==m_linkedsensors.end());is++) + { + SCA_ISensor* sensor = *is; + if (sensor->IsPositiveTrigger()) + { + sensorresult = false; + break; + } + } + + CValue* newevent = new CBoolValue(sensorresult); + + for (vector::const_iterator i=m_linkedactuators.begin(); + !(i==m_linkedactuators.end());i++) + { + SCA_IActuator* actua = *i;//m_linkedactuators.at(i); + logicmgr->AddActiveActuator(actua,newevent); + } + + // every actuator that needs the event, has a it's own reference to it now so + // release it (so to be clear: if there is no actuator, it's deleted right now) + newevent->Release(); + +} + + + +CValue* SCA_NORController::GetReplica() +{ + CValue* replica = new SCA_NORController(*this); + // this will copy properties and so on... + CValue::AddDataToReplica(replica); + + return replica; +} + + + +/* ------------------------------------------------------------------------- */ +/* Python functions */ +/* ------------------------------------------------------------------------- */ + +/* Integration hooks ------------------------------------------------------- */ +PyTypeObject SCA_NORController::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "SCA_NORController", + sizeof(SCA_NORController), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject SCA_NORController::Parents[] = { + &SCA_NORController::Type, + &SCA_IController::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; + +PyMethodDef SCA_NORController::Methods[] = { + {NULL,NULL} //Sentinel +}; + +PyObject* SCA_NORController::_getattr(const STR_String& attr) { + _getattr_up(SCA_IController); +} + +/* eof */ diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h new file mode 100644 index 00000000000..aab59e3d46c --- /dev/null +++ b/source/gameengine/GameLogic/SCA_NORController.h @@ -0,0 +1,56 @@ +/** + * SCA_NORController.h + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_NORCONTROLLER +#define __KX_NORCONTROLLER + +#include "SCA_IController.h" + +class SCA_NORController : public SCA_IController +{ + Py_Header; + //virtual void Trigger(class SCA_LogicManager* logicmgr); +public: + SCA_NORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + virtual ~SCA_NORController(); + virtual CValue* GetReplica(); + virtual void Trigger(SCA_LogicManager* logicmgr); + + /* --------------------------------------------------------------------- */ + /* Python interface ---------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + virtual PyObject* _getattr(const STR_String& attr); + +}; + +#endif //__KX_NORCONTROLLER + diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index f1fcb18d32e..655e9060238 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -54,10 +54,8 @@ SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr, m_checkpropval(propval), m_checkpropmaxval(propmaxval), m_checkpropname(propname), - m_lastresult(false), m_range_expr(NULL) { - m_recentresult=false; //CParser pars; //pars.SetContext(this->AddRef()); //CValue* resultval = m_rightexpr->Calculate(); @@ -73,7 +71,13 @@ SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr, { PrecalculateRangeExpression(); } + Init(); +} +void SCA_PropertySensor::Init() +{ + m_recentresult = false; + m_lastresult = m_invert?true:false; } void SCA_PropertySensor::PrecalculateRangeExpression() diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index 81c9b958f25..6871cb3afdc 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -77,6 +77,7 @@ public: virtual void Delete(); virtual ~SCA_PropertySensor(); virtual CValue* GetReplica(); + virtual void Init(); void PrecalculateRangeExpression(); bool CheckPropertyCondition(); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 44cdc0a7de5..be00117cd21 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -232,6 +232,7 @@ PyMethodDef SCA_PythonController::Methods[] = { METH_VARARGS, SCA_PythonController::GetSensor_doc}, {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_VARARGS}, {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_VARARGS}, + {"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_VARARGS}, {NULL,NULL} //Sentinel }; @@ -442,4 +443,12 @@ PyObject* SCA_PythonController::PySetScript(PyObject* self, Py_Return; } +/* 1. getScript */ +PyObject* SCA_PythonController::PyGetState(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + return PyInt_FromLong(m_statemask); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 63975234da9..f3af54f402f 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -81,6 +81,7 @@ class SCA_PythonController : public SCA_IController KX_PYMETHOD_DOC(SCA_PythonController,GetActuators); KX_PYMETHOD(SCA_PythonController,SetScript); KX_PYMETHOD(SCA_PythonController,GetScript); + KX_PYMETHOD(SCA_PythonController,GetState); }; diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 0e856e0d6bb..3626522e49a 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -50,16 +50,9 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, PyTypeObject* T) : SCA_ISensor(gameobj,eventmgr, T) { - m_iteration = 0; - m_interval = 0; - m_lastdraw = false; - // m_basegenerator is never deleted => memory leak m_basegenerator = new SCA_RandomNumberGenerator(startseed); - m_currentDraw = m_basegenerator->Draw(); - //registration is done globally, don't do it here - //Note: it was probably done to work around a bug in Evaluate(). It is now fixed - //RegisterToManager(); + Init(); } @@ -69,6 +62,13 @@ SCA_RandomSensor::~SCA_RandomSensor() /* Nothing to be done here. */ } +void SCA_RandomSensor::Init() +{ + m_iteration = 0; + m_interval = 0; + m_lastdraw = false; + m_currentDraw = m_basegenerator->Draw(); +} CValue* SCA_RandomSensor::GetReplica() diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index cc54179aa4e..d29bfb6837a 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -54,6 +54,7 @@ public: virtual CValue* GetReplica(); virtual bool Evaluate(CValue* event); virtual bool IsPositiveTrigger(); + virtual void Init(); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp new file mode 100644 index 00000000000..3ef7c07fe0a --- /dev/null +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -0,0 +1,148 @@ +/** + * 'Xnor' together all inputs + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "SCA_XNORController.h" +#include "SCA_ISensor.h" +#include "SCA_LogicManager.h" +#include "BoolValue.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* ------------------------------------------------------------------------- */ +/* Native functions */ +/* ------------------------------------------------------------------------- */ + +SCA_XNORController::SCA_XNORController(SCA_IObject* gameobj, + PyTypeObject* T) + : + SCA_IController(gameobj,T) +{ +} + + + +SCA_XNORController::~SCA_XNORController() +{ +} + + + +void SCA_XNORController::Trigger(SCA_LogicManager* logicmgr) +{ + + bool sensorresult = true; + + for (vector::const_iterator is=m_linkedsensors.begin(); + !(is==m_linkedsensors.end());is++) + { + SCA_ISensor* sensor = *is; + if (sensor->IsPositiveTrigger()) + { + if (sensorresult == false) + { + sensorresult = true; + break; + } + sensorresult = false; + } + } + + CValue* newevent = new CBoolValue(sensorresult); + + for (vector::const_iterator i=m_linkedactuators.begin(); + !(i==m_linkedactuators.end());i++) + { + SCA_IActuator* actua = *i;//m_linkedactuators.at(i); + logicmgr->AddActiveActuator(actua,newevent); + } + + // every actuator that needs the event, has a it's own reference to it now so + // release it (so to be clear: if there is no actuator, it's deleted right now) + newevent->Release(); + +} + + + +CValue* SCA_XNORController::GetReplica() +{ + CValue* replica = new SCA_XNORController(*this); + // this will copy properties and so on... + CValue::AddDataToReplica(replica); + + return replica; +} + + + +/* ------------------------------------------------------------------------- */ +/* Python functions */ +/* ------------------------------------------------------------------------- */ + +/* Integration hooks ------------------------------------------------------- */ +PyTypeObject SCA_XNORController::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "SCA_XNORController", + sizeof(SCA_XNORController), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject SCA_XNORController::Parents[] = { + &SCA_XNORController::Type, + &SCA_IController::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; + +PyMethodDef SCA_XNORController::Methods[] = { + {NULL,NULL} //Sentinel +}; + +PyObject* SCA_XNORController::_getattr(const STR_String& attr) { + _getattr_up(SCA_IController); +} + +/* eof */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h new file mode 100644 index 00000000000..4b1eaee95d8 --- /dev/null +++ b/source/gameengine/GameLogic/SCA_XNORController.h @@ -0,0 +1,56 @@ +/** + * SCA_XNORController.h + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_XNORCONTROLLER +#define __KX_XNORCONTROLLER + +#include "SCA_IController.h" + +class SCA_XNORController : public SCA_IController +{ + Py_Header; + //virtual void Trigger(class SCA_LogicManager* logicmgr); +public: + SCA_XNORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + virtual ~SCA_XNORController(); + virtual CValue* GetReplica(); + virtual void Trigger(SCA_LogicManager* logicmgr); + + /* --------------------------------------------------------------------- */ + /* Python interface ---------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + virtual PyObject* _getattr(const STR_String& attr); + +}; + +#endif //__KX_XNORCONTROLLER + diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp new file mode 100644 index 00000000000..6499c62f5f2 --- /dev/null +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -0,0 +1,148 @@ +/** + * 'Xor' together all inputs + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "SCA_XORController.h" +#include "SCA_ISensor.h" +#include "SCA_LogicManager.h" +#include "BoolValue.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* ------------------------------------------------------------------------- */ +/* Native functions */ +/* ------------------------------------------------------------------------- */ + +SCA_XORController::SCA_XORController(SCA_IObject* gameobj, + PyTypeObject* T) + : + SCA_IController(gameobj,T) +{ +} + + + +SCA_XORController::~SCA_XORController() +{ +} + + + +void SCA_XORController::Trigger(SCA_LogicManager* logicmgr) +{ + + bool sensorresult = false; + + for (vector::const_iterator is=m_linkedsensors.begin(); + !(is==m_linkedsensors.end());is++) + { + SCA_ISensor* sensor = *is; + if (sensor->IsPositiveTrigger()) + { + if (sensorresult == true) + { + sensorresult = false; + break; + } + sensorresult = true; + } + } + + CValue* newevent = new CBoolValue(sensorresult); + + for (vector::const_iterator i=m_linkedactuators.begin(); + !(i==m_linkedactuators.end());i++) + { + SCA_IActuator* actua = *i;//m_linkedactuators.at(i); + logicmgr->AddActiveActuator(actua,newevent); + } + + // every actuator that needs the event, has a it's own reference to it now so + // release it (so to be clear: if there is no actuator, it's deleted right now) + newevent->Release(); + +} + + + +CValue* SCA_XORController::GetReplica() +{ + CValue* replica = new SCA_XORController(*this); + // this will copy properties and so on... + CValue::AddDataToReplica(replica); + + return replica; +} + + + +/* ------------------------------------------------------------------------- */ +/* Python functions */ +/* ------------------------------------------------------------------------- */ + +/* Integration hooks ------------------------------------------------------- */ +PyTypeObject SCA_XORController::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "SCA_XORController", + sizeof(SCA_XORController), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject SCA_XORController::Parents[] = { + &SCA_XORController::Type, + &SCA_IController::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; + +PyMethodDef SCA_XORController::Methods[] = { + {NULL,NULL} //Sentinel +}; + +PyObject* SCA_XORController::_getattr(const STR_String& attr) { + _getattr_up(SCA_IController); +} + +/* eof */ diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h new file mode 100644 index 00000000000..f50cd33c125 --- /dev/null +++ b/source/gameengine/GameLogic/SCA_XORController.h @@ -0,0 +1,56 @@ +/** + * SCA_XORController.h + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_XORCONTROLLER +#define __KX_XORCONTROLLER + +#include "SCA_IController.h" + +class SCA_XORController : public SCA_IController +{ + Py_Header; + //virtual void Trigger(class SCA_LogicManager* logicmgr); +public: + SCA_XORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + virtual ~SCA_XORController(); + virtual CValue* GetReplica(); + virtual void Trigger(SCA_LogicManager* logicmgr); + + /* --------------------------------------------------------------------- */ + /* Python interface ---------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + virtual PyObject* _getattr(const STR_String& attr); + +}; + +#endif //__KX_XORCONTROLLER + diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index 44eeccedbd1..a5017574873 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -602,9 +602,9 @@ void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer) } } -void GPC_RenderTools::Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text) +void GPC_RenderTools::Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short texture_flag) { - m_filtermanager.EnableFilter(filtermode, pass, text); + m_filtermanager.EnableFilter(filtermode, pass, text, texture_flag); } void GPC_RenderTools::Render2DFilters(RAS_ICanvas* canvas) diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index f7230cb0865..cb7193f3513 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -142,7 +142,7 @@ public: virtual void MotionBlur(RAS_IRasterizer* rasterizer); - virtual void Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text); + virtual void Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short texture_flag); virtual void Render2DFilters(RAS_ICanvas* canvas); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index c4cf698d5ee..d6908b53d40 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -496,7 +496,6 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); - bool useVertexArrays = SYS_GetCommandLineInt(syshandle,"vertexarrays",1) != 0; bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DIAPLAY_LISTS) != 0); if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) { @@ -514,16 +513,17 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) if (!m_rendertools) goto initFailed; - if(useLists) - if (useVertexArrays) { + if(useLists) { + if(GLEW_VERSION_1_1) m_rasterizer = new RAS_ListRasterizer(m_canvas, true); - } else { + else m_rasterizer = new RAS_ListRasterizer(m_canvas); - } - else if (useVertexArrays && GLEW_VERSION_1_1) + } + else if (GLEW_VERSION_1_1) m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas); else m_rasterizer = new RAS_OpenGLRasterizer(m_canvas); + m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode); if (!m_rasterizer) goto initFailed; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index bc80c0a7612..8222e5c8bac 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -187,11 +187,10 @@ void usage(char* program) printf(" show_framerate 0 Show the frame rate\n"); printf(" show_properties 0 Show debug properties\n"); printf(" show_profile 0 Show profiling information\n"); - printf(" vertexarrays 1 Enable vertex arrays\n"); printf(" blender_material 0 Enable material settings\n"); printf("\n"); printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program); - printf("example: %s -g vertexarrays = 0 c:\\loadtest.blend\n", program); + printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } char *get_filename(int argc, char **argv) { diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index e320453b7aa..027cb2a0ffa 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -58,10 +58,15 @@ KX_NetworkMessageSensor::KX_NetworkMessageSensor( m_NetworkScene(NetworkScene), m_subject(subject), m_frame_message_count (0), - m_IsUp(false), m_BodyList(NULL), m_SubjectList(NULL) { + Init(); +} + +void KX_NetworkMessageSensor::Init() +{ + m_IsUp = false; } KX_NetworkMessageSensor::~KX_NetworkMessageSensor() diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index d051b715aab..6fd92d17be3 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -65,6 +65,7 @@ public: virtual CValue* GetReplica(); virtual bool Evaluate(CValue* event); virtual bool IsPositiveTrigger(); + virtual void Init(); void EndFrame(); /* ------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index aa7c75e9633..70443ced7a9 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -102,6 +102,13 @@ MT_Vector3 KX_BulletPhysicsController::GetLinearVelocity() CcdPhysicsController::GetLinearVelocity(angVel[0],angVel[1],angVel[2]);//rcruiz return MT_Vector3(angVel[0],angVel[1],angVel[2]); } +MT_Vector3 KX_BulletPhysicsController::GetAngularVelocity() +{ + float angVel[3]; + //CcdPhysicsController::GetAngularVelocity(angVel[0],angVel[1],angVel[2]); + CcdPhysicsController::GetAngularVelocity(angVel[0],angVel[1],angVel[2]);//rcruiz + return MT_Vector3(angVel[0],angVel[1],angVel[2]); +} MT_Vector3 KX_BulletPhysicsController::GetVelocity(const MT_Point3& pos) { float linVel[3]; diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index 619ac42503f..0853755dffa 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -25,6 +25,7 @@ public: virtual void ApplyTorque(const MT_Vector3& torque,bool local); virtual void ApplyForce(const MT_Vector3& force,bool local); virtual MT_Vector3 GetLinearVelocity(); + virtual MT_Vector3 GetAngularVelocity(); virtual MT_Vector3 GetVelocity(const MT_Point3& pos); virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local); virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index eaa6564ba84..b7750e68e8f 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -664,6 +664,27 @@ MT_Vector3 KX_GameObject::GetLinearVelocity(bool local) return velocity; } +MT_Vector3 KX_GameObject::GetAngularVelocity(bool local) +{ + MT_Vector3 velocity(0.0,0.0,0.0), locvel; + MT_Matrix3x3 ori; + int i, j; + if (m_pPhysicsController1) + { + velocity = m_pPhysicsController1->GetAngularVelocity(); + + if (local) + { + ori = GetSGNode()->GetWorldOrientation(); + + locvel = velocity * ori; + return locvel; + } + } + return velocity; +} + + // scenegraph node stuff @@ -782,6 +803,9 @@ void KX_GameObject::Suspend(void) PyMethodDef KX_GameObject::Methods[] = { {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, + {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_VARARGS}, + {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_VARARGS}, + {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_VARARGS}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_VARARGS}, {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_VARARGS}, @@ -802,6 +826,8 @@ PyMethodDef KX_GameObject::Methods[] = { {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_VARARGS}, {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS}, {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS}, + {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_VARARGS}, + {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_VARARGS}, KX_PYMETHODTABLE(KX_GameObject, getDistanceTo), KX_PYMETHODTABLE(KX_GameObject, rayCastTo), KX_PYMETHODTABLE(KX_GameObject, rayCast), @@ -835,6 +861,18 @@ PyObject* KX_GameObject::sPySetPosition(PyObject* self, } +PyObject* KX_GameObject::PyEndObject(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + + KX_Scene *scene = PHY_GetActiveScene(); + scene->DelayedRemoveObject(this); + + return Py_None; + +} + PyObject* KX_GameObject::PyGetPosition(PyObject* self, PyObject* args, @@ -1074,6 +1112,45 @@ PyObject* KX_GameObject::PySetVisible(PyObject* self, } +PyObject* KX_GameObject::PyGetVisible(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + return PyInt_FromLong(m_bVisible); +} + +PyObject* KX_GameObject::PyGetState(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + int state = 0; + state |= GetState(); + return PyInt_FromLong(state); +} + +PyObject* KX_GameObject::PySetState(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + int state_i; + unsigned int state = 0; + + if (PyArg_ParseTuple(args,"i",&state_i)) + { + state |= state_i; + if ((state & ((1<<30)-1)) == 0) { + PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)"); + return NULL; + } + SetState(state); + } + else + { + return NULL; + } + Py_Return; +} + PyObject* KX_GameObject::PyGetVelocity(PyObject* self, @@ -1262,17 +1339,7 @@ PyObject* KX_GameObject::PySuspendDynamics(PyObject* self, PyObject* args, PyObject* kwds) { - if (m_bSuspendDynamics) - { - Py_Return; - } - - if (m_pPhysicsController1) - { - m_pPhysicsController1->SuspendDynamics(); - } - m_bSuspendDynamics = true; - + SuspendDynamics(); Py_Return; } @@ -1282,18 +1349,7 @@ PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self, PyObject* args, PyObject* kwds) { - - if (!m_bSuspendDynamics) - { - Py_Return; - } - - if (m_pPhysicsController1) - { - m_pPhysicsController1->RestoreDynamics(); - } - m_bSuspendDynamics = false; - + RestoreDynamics(); Py_Return; } @@ -1383,6 +1439,13 @@ PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self, return PyInt_FromLong((long)physid); } +PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + return ConvertKeysToPython(); +} + KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo, "getDistanceTo(other): get distance to another point/KX_GameObject") { diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 63a660617c4..89f4cb396d1 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -46,7 +46,7 @@ #include "GEN_HashedPtr.h" #include "KX_Scene.h" #include "KX_KetsjiEngine.h" /* for m_anim_framerate */ - +#include "KX_IPhysicsController.h" /* for suspend/resume */ #define KX_OB_DYNAMIC 1 @@ -258,6 +258,14 @@ public: bool local=false ); + /** + * Return the angular velocity of the game object. + */ + MT_Vector3 + GetAngularVelocity( + bool local=false + ); + /** * Align the object to a given normal. */ @@ -644,6 +652,32 @@ public: */ void Resume(void); + void SuspendDynamics(void) { + if (m_bSuspendDynamics) + { + return; + } + + if (m_pPhysicsController1) + { + m_pPhysicsController1->SuspendDynamics(); + } + m_bSuspendDynamics = true; + } + + void RestoreDynamics(void) { + if (!m_bSuspendDynamics) + { + return; + } + + if (m_pPhysicsController1) + { + m_pPhysicsController1->RestoreDynamics(); + } + m_bSuspendDynamics = false; + } + KX_ClientObjectInfo* getClientInfo() { return m_pClient_info; } /** * @section Python interface functions. @@ -676,7 +710,7 @@ public: PyObject* args, PyObject* kwds ); - + KX_PYMETHOD(KX_GameObject,GetPosition); KX_PYMETHOD(KX_GameObject,GetLinearVelocity); KX_PYMETHOD(KX_GameObject,GetVelocity); @@ -684,7 +718,10 @@ public: KX_PYMETHOD(KX_GameObject,GetReactionForce); KX_PYMETHOD(KX_GameObject,GetOrientation); KX_PYMETHOD(KX_GameObject,SetOrientation); + KX_PYMETHOD(KX_GameObject,GetVisible); KX_PYMETHOD(KX_GameObject,SetVisible); + KX_PYMETHOD(KX_GameObject,GetState); + KX_PYMETHOD(KX_GameObject,SetState); KX_PYMETHOD(KX_GameObject,AlignAxisToVect); KX_PYMETHOD(KX_GameObject,SuspendDynamics); KX_PYMETHOD(KX_GameObject,RestoreDynamics); @@ -697,9 +734,12 @@ public: KX_PYMETHOD(KX_GameObject,SetParent); KX_PYMETHOD(KX_GameObject,RemoveParent); KX_PYMETHOD(KX_GameObject,GetPhysicsId); + KX_PYMETHOD(KX_GameObject,GetPropertyNames); + KX_PYMETHOD(KX_GameObject,EndObject); KX_PYMETHOD_DOC(KX_GameObject,rayCastTo); KX_PYMETHOD_DOC(KX_GameObject,rayCast); KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo); + private : /** diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index 009db40d3e8..2ec66a883eb 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -64,6 +64,7 @@ public: virtual void ApplyTorque(const MT_Vector3& torque,bool local)=0; virtual void ApplyForce(const MT_Vector3& force,bool local)=0; virtual MT_Vector3 GetLinearVelocity()=0; + virtual MT_Vector3 GetAngularVelocity()=0; virtual MT_Vector3 GetVelocity(const MT_Point3& pos)=0; virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local)=0; virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local)=0; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 60b90138abe..f89d32bbe66 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -69,11 +69,14 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr, m_gp_canvas(canvas), m_kxscene(kxscene) { + Init(); +} - m_mouse_over_in_previous_frame = false; +void KX_MouseFocusSensor::Init() +{ + m_mouse_over_in_previous_frame = (m_invert)?true:false; m_positive_event = false; m_hitObject = 0; - } bool KX_MouseFocusSensor::Evaluate(CValue* event) @@ -89,13 +92,13 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event) obHasFocus = ParentObjectHasFocus(); if (!obHasFocus) { + m_positive_event = false; if (m_mouse_over_in_previous_frame) { - m_positive_event = false; - result = true; + result = true; } } else { + m_positive_event = true; if (!m_mouse_over_in_previous_frame) { - m_positive_event = true; result = true; } } diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index 86f32fbf4be..b011ebe1288 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -68,6 +68,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor * @attention Overrides default evaluate. */ virtual bool Evaluate(CValue* event); + virtual void Init(); virtual bool IsPositiveTrigger() { bool result = m_positive_event; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 22a406792f9..03ae14997ab 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -50,6 +50,7 @@ KX_ObjectActuator( const MT_Vector3& drot, const MT_Vector3& linV, const MT_Vector3& angV, + const short damping, const KX_LocalFlags& flag, PyTypeObject* T ) : @@ -60,9 +61,16 @@ KX_ObjectActuator( m_drot(drot), m_linear_velocity(linV), m_angular_velocity(angV), + m_linear_length2(0.0), + m_current_linear_factor(0.0), + m_current_angular_factor(0.0), + m_damping(damping), m_bitLocalFlag (flag), - m_active_combined_velocity (false) + m_active_combined_velocity (false), + m_linear_damping_active(false), + m_angular_damping_active(false) { + UpdateFuzzyFlags(); } bool KX_ObjectActuator::Update() @@ -87,42 +95,98 @@ bool KX_ObjectActuator::Update() ); m_active_combined_velocity = false; } + m_linear_damping_active = false; return false; } else if (parent) { - /* Probably better to use some flags, so these MT_zero tests can be */ - /* skipped. */ - if (!MT_fuzzyZero(m_force)) + if (!m_bitLocalFlag.ZeroForce) { - parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0); + if (m_bitLocalFlag.ClampVelocity && !m_bitLocalFlag.ZeroLinearVelocity) + { + // The user is requesting not to exceed the velocity set in m_linear_velocity + // The verification is done by projecting the actual speed along the linV direction + // and comparing it with the linV vector length + MT_Vector3 linV; + linV = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity); + if (linV.dot(m_linear_velocity) < m_linear_length2) + parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0); + } else + { + parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0); + } } - if (!MT_fuzzyZero(m_torque)) + if (!m_bitLocalFlag.ZeroTorque) { - parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0); + if (m_bitLocalFlag.ClampVelocity && !m_bitLocalFlag.ZeroAngularVelocity) + { + // The user is requesting not to exceed the velocity set in m_angular_velocity + // The verification is done by projecting the actual speed in the + MT_Vector3 angV; + angV = parent->GetAngularVelocity(m_bitLocalFlag.AngularVelocity); + if (angV.dot(m_angular_velocity) < m_angular_velocity.length2()) + parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0); + } else + { + parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0); + } } - if (!MT_fuzzyZero(m_dloc)) + if (!m_bitLocalFlag.ZeroDLoc) { parent->ApplyMovement(m_dloc,(m_bitLocalFlag.DLoc) != 0); } - if (!MT_fuzzyZero(m_drot)) + if (!m_bitLocalFlag.ZeroDRot) { parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0); } - if (!MT_fuzzyZero(m_linear_velocity)) + if (!m_bitLocalFlag.ZeroLinearVelocity && !m_bitLocalFlag.ClampVelocity) { if (m_bitLocalFlag.AddOrSetLinV) { parent->addLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0); } else { m_active_combined_velocity = true; - parent->setLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0); + if (m_damping > 0) { + MT_Vector3 linV; + if (!m_linear_damping_active) { + // delta and the start speed (depends on the existing speed in that direction) + linV = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity); + // keep only the projection along the desired direction + m_current_linear_factor = linV.dot(m_linear_velocity)/m_linear_length2; + m_linear_damping_active = true; + } + if (m_current_linear_factor < 1.0) + m_current_linear_factor += 1.0/m_damping; + if (m_current_linear_factor > 1.0) + m_current_linear_factor = 1.0; + linV = m_current_linear_factor * m_linear_velocity; + parent->setLinearVelocity(linV,(m_bitLocalFlag.LinearVelocity) != 0); + } else { + parent->setLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0); + } } } - if (!MT_fuzzyZero(m_angular_velocity)) + if (!m_bitLocalFlag.ZeroAngularVelocity && !m_bitLocalFlag.ClampVelocity) { - parent->setAngularVelocity(m_angular_velocity,(m_bitLocalFlag.AngularVelocity) != 0); m_active_combined_velocity = true; + if (m_damping > 0) { + MT_Vector3 angV; + if (!m_angular_damping_active) { + // delta and the start speed (depends on the existing speed in that direction) + angV = parent->GetAngularVelocity(m_bitLocalFlag.AngularVelocity); + // keep only the projection along the desired direction + m_current_angular_factor = angV.dot(m_angular_velocity)/m_angular_length2; + m_angular_damping_active = true; + } + if (m_current_angular_factor < 1.0) + m_current_angular_factor += 1.0/m_damping; + if (m_current_angular_factor > 1.0) + m_current_angular_factor = 1.0; + angV = m_current_angular_factor * m_angular_velocity; + parent->setAngularVelocity(angV,(m_bitLocalFlag.AngularVelocity) != 0); + } else { + parent->setAngularVelocity(m_angular_velocity,(m_bitLocalFlag.AngularVelocity) != 0); + } } } @@ -199,6 +263,8 @@ PyMethodDef KX_ObjectActuator::Methods[] = { {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS}, {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_VARARGS}, {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS}, + {"setVelocityDamping", (PyCFunction) KX_ObjectActuator::sPySetVelocityDamping, METH_VARARGS}, + {"getVelocityDamping", (PyCFunction) KX_ObjectActuator::sPyGetVelocityDamping, METH_VARARGS}, {NULL,NULL} //Sentinel @@ -238,6 +304,7 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self, } m_force.setValue(vecArg); m_bitLocalFlag.Force = PyArgToBool(bToggle); + UpdateFuzzyFlags(); Py_Return; } @@ -268,6 +335,7 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, } m_torque.setValue(vecArg); m_bitLocalFlag.Torque = PyArgToBool(bToggle); + UpdateFuzzyFlags(); Py_Return; } @@ -298,6 +366,7 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, } m_dloc.setValue(vecArg); m_bitLocalFlag.DLoc = PyArgToBool(bToggle); + UpdateFuzzyFlags(); Py_Return; } @@ -328,6 +397,7 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, } m_drot.setValue(vecArg); m_bitLocalFlag.DRot = PyArgToBool(bToggle); + UpdateFuzzyFlags(); Py_Return; } @@ -341,6 +411,7 @@ PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self, PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity)); + PyList_SetItem(retVal, 4, BoolToPyArg(m_bitLocalFlag.ClampVelocity)); return retVal; } @@ -351,12 +422,15 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, PyObject* kwds) { float vecArg[3]; int bToggle = 0; - if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], - &vecArg[2], &bToggle)) { + int bClamp = 0; + if (!PyArg_ParseTuple(args, "fffi|i", &vecArg[0], &vecArg[1], + &vecArg[2], &bToggle, &bClamp)) { return NULL; } m_linear_velocity.setValue(vecArg); m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle); + m_bitLocalFlag.ClampVelocity = PyArgToBool(bClamp); + UpdateFuzzyFlags(); Py_Return; } @@ -371,6 +445,7 @@ PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self, PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1])); PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2])); PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity)); + PyList_SetItem(retVal, 4, BoolToPyArg(m_bitLocalFlag.ClampVelocity)); return retVal; } @@ -380,15 +455,37 @@ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, PyObject* kwds) { float vecArg[3]; int bToggle = 0; - if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], - &vecArg[2], &bToggle)) { + int bClamp = 0; + if (!PyArg_ParseTuple(args, "fffi|i", &vecArg[0], &vecArg[1], + &vecArg[2], &bToggle, &bClamp)) { return NULL; } m_angular_velocity.setValue(vecArg); m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle); + m_bitLocalFlag.ClampVelocity = PyArgToBool(bClamp); + UpdateFuzzyFlags(); Py_Return; } +/* 13. setVelocityDamping */ +PyObject* KX_ObjectActuator::PySetVelocityDamping(PyObject* self, + PyObject* args, + PyObject* kwds) { + int damping = 0; + if (!PyArg_ParseTuple(args, "i", &damping) || damping < 0 || damping > 1000) { + return NULL; + } + m_damping = damping; + Py_Return; +} + +/* 13. getVelocityDamping */ +PyObject* KX_ObjectActuator::PyGetVelocityDamping(PyObject* self, + PyObject* args, + PyObject* kwds) { + return Py_BuildValue("i",m_damping); +} + diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index edbae154b8b..ec6dab5cd48 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -46,7 +46,13 @@ struct KX_LocalFlags { DLoc(false), LinearVelocity(false), AngularVelocity(false), - AddOrSetLinV(false) + AddOrSetLinV(false), + ClampVelocity(false), + ZeroForce(false), + ZeroDRot(false), + ZeroDLoc(false), + ZeroLinearVelocity(false), + ZeroAngularVelocity(false) { } @@ -57,6 +63,13 @@ struct KX_LocalFlags { unsigned short LinearVelocity : 1; unsigned short AngularVelocity : 1; unsigned short AddOrSetLinV : 1; + unsigned short ClampVelocity : 1; + unsigned short ZeroForce : 1; + unsigned short ZeroTorque : 1; + unsigned short ZeroDRot : 1; + unsigned short ZeroDLoc : 1; + unsigned short ZeroLinearVelocity : 1; + unsigned short ZeroAngularVelocity : 1; }; class KX_ObjectActuator : public SCA_IActuator @@ -69,6 +82,11 @@ class KX_ObjectActuator : public SCA_IActuator MT_Vector3 m_drot; MT_Vector3 m_linear_velocity; MT_Vector3 m_angular_velocity; + MT_Scalar m_linear_length2; + MT_Scalar m_angular_length2; + MT_Scalar m_current_linear_factor; + MT_Scalar m_current_angular_factor; + short m_damping; KX_LocalFlags m_bitLocalFlag; // A hack bool -- oh no sorry everyone @@ -77,6 +95,8 @@ class KX_ObjectActuator : public SCA_IActuator // setting linear velocity. bool m_active_combined_velocity; + bool m_linear_damping_active; + bool m_angular_damping_active; public: enum KX_OBJECT_ACT_VEC_TYPE { @@ -103,6 +123,7 @@ public: const MT_Vector3& drot, const MT_Vector3& linV, const MT_Vector3& angV, + const short damping, const KX_LocalFlags& flag, PyTypeObject* T=&Type ); @@ -110,6 +131,17 @@ public: CValue* GetReplica(); void SetForceLoc(const double force[3]) { /*m_force=force;*/ } + void UpdateFuzzyFlags() + { + m_bitLocalFlag.ZeroForce = MT_fuzzyZero(m_force); + m_bitLocalFlag.ZeroTorque = MT_fuzzyZero(m_torque); + m_bitLocalFlag.ZeroDLoc = MT_fuzzyZero(m_dloc); + m_bitLocalFlag.ZeroDRot = MT_fuzzyZero(m_drot); + m_bitLocalFlag.ZeroLinearVelocity = MT_fuzzyZero(m_linear_velocity); + m_linear_length2 = (m_bitLocalFlag.ZeroLinearVelocity) ? 0.0 : m_linear_velocity.length2(); + m_bitLocalFlag.ZeroAngularVelocity = MT_fuzzyZero(m_angular_velocity); + m_angular_length2 = (m_bitLocalFlag.ZeroAngularVelocity) ? 0.0 : m_angular_velocity.length2(); + } virtual bool Update(); @@ -132,6 +164,8 @@ public: KX_PYMETHOD(KX_ObjectActuator,SetLinearVelocity); KX_PYMETHOD(KX_ObjectActuator,GetAngularVelocity); KX_PYMETHOD(KX_ObjectActuator,SetAngularVelocity); + KX_PYMETHOD(KX_ObjectActuator,SetVelocityDamping); + KX_PYMETHOD(KX_ObjectActuator,GetVelocityDamping); }; #endif //__KX_OBJECTACTUATOR diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 31fffffa3c1..987e0b946b2 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -71,7 +71,6 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr, //sumoObj->setClientObject(&m_client_info); } - KX_RadarSensor::~KX_RadarSensor() { diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index a85dc61cac8..e847c59bae1 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -60,17 +60,19 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, m_bFindMaterial(bFindMaterial), m_distance(distance), m_scene(ketsjiScene), - m_bTriggered(false), - m_axis(axis), - m_rayHit(false), - m_hitObject(NULL) + m_axis(axis) { - + Init(); } - +void KX_RaySensor::Init() +{ + m_bTriggered = (m_invert)?true:false; + m_rayHit = false; + m_hitObject = NULL; +} KX_RaySensor::~KX_RaySensor() { diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index 8a317ffaa07..f4305b053d1 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -66,6 +66,7 @@ public: virtual bool Evaluate(CValue* event); virtual bool IsPositiveTrigger(); + virtual void Init(); bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp new file mode 100644 index 00000000000..d44ab477749 --- /dev/null +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -0,0 +1,206 @@ +// +// Adjust dynamics settins for this object +// +// $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 ***** + +// +// Previously existed as: + +// \source\gameengine\GameLogic\SCA_DynamicActuator.cpp + +// Please look here for revision history. + +#include "KX_SCA_DynamicActuator.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* ------------------------------------------------------------------------- */ +/* Python functions */ +/* ------------------------------------------------------------------------- */ + +/* Integration hooks ------------------------------------------------------- */ + + PyTypeObject + +KX_SCA_DynamicActuator:: + +Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "KX_SCA_DynamicActuator", + sizeof(KX_SCA_DynamicActuator), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, + __repr, + 0, + 0, + 0, + 0, + 0 +}; + +PyParentObject KX_SCA_DynamicActuator::Parents[] = { + &KX_SCA_DynamicActuator::Type, + &SCA_IActuator::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; + + +PyMethodDef KX_SCA_DynamicActuator::Methods[] = { + KX_PYMETHODTABLE(KX_SCA_DynamicActuator, setOperation), + KX_PYMETHODTABLE(KX_SCA_DynamicActuator, getOperation), + {NULL,NULL} //Sentinel +}; + + + +PyObject* KX_SCA_DynamicActuator::_getattr(const STR_String& attr) +{ + _getattr_up(SCA_IActuator); +} + + + +/* 1. setOperation */ +KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation, +"setOperation(operation?)\n" +"\t - operation? : type of dynamic operation\n" +"\t 0 = restore dynamics\n" +"\t 1 = disable dynamics\n" +"\t 2 = enable rigid body\n" +"\t 3 = disable rigid body\n" +"Change the dynamic status of the parent object.\n") +{ + int dyn_operation; + + if (!PyArg_ParseTuple(args, "i", &dyn_operation)) + { + return NULL; + } + if (dyn_operation <0 || dyn_operation>3) { + PyErr_SetString(PyExc_IndexError, "Dynamic Actuator's setOperation() range must be between 0 and 3"); + return NULL; + } + m_dyn_operation= dyn_operation; + Py_Return; +} + +KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, +"getOperation() -> integer\n" +"Returns the operation type of this actuator.\n" +) +{ + return PyInt_FromLong((long)m_dyn_operation); +} + + +/* ------------------------------------------------------------------------- */ +/* Native functions */ +/* ------------------------------------------------------------------------- */ + +KX_SCA_DynamicActuator::KX_SCA_DynamicActuator(SCA_IObject *gameobj, + short dyn_operation, + PyTypeObject* T) : + + SCA_IActuator(gameobj, T), + m_dyn_operation(dyn_operation) +{ +} /* End of constructor */ + + +KX_SCA_DynamicActuator::~KX_SCA_DynamicActuator() +{ + // there's nothing to be done here, really.... +} /* end of destructor */ + + + +bool KX_SCA_DynamicActuator::Update() +{ + // bool result = false; /*unused*/ + KX_GameObject *obj = (KX_GameObject*) GetParent(); + bool bNegativeEvent = IsNegativeEvent(); + KX_IPhysicsController* controller; + RemoveAllEvents(); + + if (bNegativeEvent) + return false; // do nothing on negative events + + if (!obj) + return false; // object not accessible, shouldnt happen + controller = obj->GetPhysicsController(); + if (!controller) + return false; // no physic object + + switch (m_dyn_operation) + { + case 0: + obj->RestoreDynamics(); + break; + case 1: + obj->SuspendDynamics(); + break; + case 2: + controller->setRigidBody(true); + break; + case 3: + controller->setRigidBody(false); + break; + } + + return false; +} + + + +CValue* KX_SCA_DynamicActuator::GetReplica() +{ + KX_SCA_DynamicActuator* replica = + new KX_SCA_DynamicActuator(*this); + + if (replica == NULL) + return NULL; + + replica->ProcessReplica(); + + // this will copy properties and so on... + CValue::AddDataToReplica(replica); + + return replica; +}; + + +/* eof */ diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h new file mode 100644 index 00000000000..b47c3a511d9 --- /dev/null +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h @@ -0,0 +1,76 @@ +// +// Add object to the game world on action of this actuator +// +// $Id$ +// +// ***** BEGIN GPL LICENSE BLOCK ***** +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +// All rights reserved. +// +// The Original Code is: all of this file. +// +// Contributor(s): Campbell Barton +// +// ***** END GPL LICENSE BLOCK ***** +// + +#ifndef __KX_SCA_DYNAMICACTUATOR +#define __KX_SCA_DYNAMICACTUATOR + +#include "SCA_IActuator.h" +#include "SCA_PropertyActuator.h" +#include "SCA_LogicManager.h" + +#include "KX_GameObject.h" +#include "KX_IPhysicsController.h" + +class KX_SCA_DynamicActuator : public SCA_IActuator +{ + Py_Header; + + // dynamics operation to apply to the game object + short m_dyn_operation; + public: + KX_SCA_DynamicActuator( + SCA_IObject* gameobj, + short dyn_operation, + PyTypeObject* T=&Type + ); + + ~KX_SCA_DynamicActuator( + ); + + CValue* + GetReplica( + ); + + virtual bool + Update(); + + virtual PyObject* + _getattr( + const STR_String& attr + ); + + /* 1. setOperation */ + KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,setOperation); + KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,getOperation); + +}; + +#endif diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index fff33ca82fd..a7e91e27df3 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -754,8 +754,6 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) for (SCA_ControllerList::iterator itc = controllers.begin(); !(itc==controllers.end());itc++) { - (*itc)->UnlinkAllSensors(); - (*itc)->UnlinkAllActuators(); m_logicmgr->RemoveController(*itc); } @@ -868,6 +866,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) static_cast( parentobj ) ); releaseParent= false; + shapeDeformer->LoadShapeDrivers(blendobj->parent); } else { diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp new file mode 100644 index 00000000000..95a79f0c480 --- /dev/null +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -0,0 +1,207 @@ +/* + * $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 ***** + * Actuator to toggle visibility/invisibility of objects + */ + +#include "KX_StateActuator.h" +#include "KX_GameObject.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +KX_StateActuator::KX_StateActuator( + SCA_IObject* gameobj, + int operation, + unsigned int mask, + PyTypeObject* T + ) + : SCA_IActuator(gameobj,T), + m_operation(operation), + m_mask(mask) +{ + // intentionally empty +} + +KX_StateActuator::~KX_StateActuator( + void + ) +{ + // intentionally empty +} + +CValue* +KX_StateActuator::GetReplica( + void + ) +{ + KX_StateActuator* replica = new KX_StateActuator(*this); + replica->ProcessReplica(); + // this will copy properties and so on... + CValue::AddDataToReplica(replica); + return replica; +} + +bool +KX_StateActuator::Update() +{ + bool bNegativeEvent = IsNegativeEvent(); + unsigned int objMask; + + RemoveAllEvents(); + if (bNegativeEvent) return false; + + KX_GameObject *obj = (KX_GameObject*) GetParent(); + + objMask = obj->GetState(); + switch (m_operation) + { + case OP_CPY: + objMask = m_mask; + break; + case OP_SET: + objMask |= m_mask; + break; + case OP_CLR: + objMask &= ~m_mask; + break; + case OP_NEG: + objMask ^= m_mask; + break; + default: + // unsupported operation, no nothing + return false; + } + obj->SetState(objMask); + return false; +} + +/* ------------------------------------------------------------------------- */ +/* Python functions */ +/* ------------------------------------------------------------------------- */ + + + +/* Integration hooks ------------------------------------------------------- */ +PyTypeObject +KX_StateActuator::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "KX_StateActuator", + sizeof(KX_StateActuator), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject +KX_StateActuator::Parents[] = { + &KX_StateActuator::Type, + &SCA_IActuator::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; + +PyMethodDef +KX_StateActuator::Methods[] = { + {"setOperation", (PyCFunction) KX_StateActuator::sPySetOperation, + METH_VARARGS, SetOperation_doc}, + {"setMask", (PyCFunction) KX_StateActuator::sPySetMask, + METH_VARARGS, SetMask_doc}, + {NULL,NULL} //Sentinel +}; + +PyObject* +KX_StateActuator::_getattr( + const STR_String& attr + ) +{ + _getattr_up(SCA_IActuator); +}; + + + +/* set operation ---------------------------------------------------------- */ +char +KX_StateActuator::SetOperation_doc[] = +"setOperation(op)\n" +"\t - op : bit operation (0=Copy, 1=Set, 2=Clear, 3=Negate)" +"\tSet the type of bit operation to be applied on object state mask.\n" +"\tUse setMask() to specify the bits that will be modified.\n"; +PyObject* + +KX_StateActuator::PySetOperation(PyObject* self, + PyObject* args, + PyObject* kwds) { + int oper; + + if(!PyArg_ParseTuple(args, "i", &oper)) { + return NULL; + } + + m_operation = oper; + + Py_Return; +} + +/* set mask ---------------------------------------------------------- */ +char +KX_StateActuator::SetMask_doc[] = +"setMask(mask)\n" +"\t - mask : bits that will be modified" +"\tSet the value that defines the bits that will be modified by the operation.\n" +"\tThe bits that are 1 in the value will be updated in the object state,\n" +"\tthe bits that are 0 are will be left unmodified expect for the Copy operation\n" +"\twhich copies the value to the object state.\n"; +PyObject* + +KX_StateActuator::PySetMask(PyObject* self, + PyObject* args, + PyObject* kwds) { + int mask; + + if(!PyArg_ParseTuple(args, "i", &mask)) { + return NULL; + } + + m_mask = mask; + + Py_Return; +} + + diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h new file mode 100644 index 00000000000..8698e51b2c1 --- /dev/null +++ b/source/gameengine/Ketsji/KX_StateActuator.h @@ -0,0 +1,83 @@ +/* + * $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 ***** + * Actuator to toggle visibility/invisibility of objects + */ + +#ifndef __KX_STATEACTUATOR +#define __KX_STATEACTUATOR + +#include "SCA_IActuator.h" + +class KX_StateActuator : public SCA_IActuator +{ + Py_Header; + + /** Make visible? */ + enum { + OP_CPY = 0, + OP_SET, + OP_CLR, + OP_NEG + }; + int m_operation; + unsigned int m_mask; + + public: + + KX_StateActuator( + SCA_IObject* gameobj, + int operation, + unsigned int mask, + PyTypeObject* T=&Type + ); + + virtual + ~KX_StateActuator( + void + ); + + virtual CValue* + GetReplica( + void + ); + + virtual bool + Update(); + + /* --------------------------------------------------------------------- */ + /* Python interface ---------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + virtual PyObject* _getattr(const STR_String& attr); + //KX_PYMETHOD_DOC + KX_PYMETHOD_DOC(KX_StateActuator,SetOperation); + KX_PYMETHOD_DOC(KX_StateActuator,SetMask); +}; + +#endif + diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h index 868465c8f10..8c061ae4056 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h @@ -68,6 +68,8 @@ public: void ApplyTorque(const MT_Vector3& torque,bool local); void ApplyForce(const MT_Vector3& force,bool local); MT_Vector3 GetLinearVelocity(); + MT_Vector3 GetAngularVelocity() // to keep compiler happy + { return MT_Vector3(0.0,0.0,0.0); } MT_Vector3 GetVelocity(const MT_Point3& pos); void SetAngularVelocity(const MT_Vector3& ang_vel,bool local); void SetLinearVelocity(const MT_Vector3& lin_vel,bool local); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 3f185359de0..5311f059f03 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -77,18 +77,14 @@ KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj :SCA_ISensor(gameobj,eventmgr,T), m_touchedpropname(touchedpropname), m_bFindMaterial(bFindMaterial), -m_eventmgr(eventmgr), +m_eventmgr(eventmgr) /*m_sumoObj(sumoObj),*/ -m_bCollision(false), -m_bTriggered(false), -m_bLastTriggered(false) { // KX_TouchEventManager* touchmgr = (KX_TouchEventManager*) eventmgr; // m_resptable = touchmgr->GetResponseTable(); // m_solidHandle = m_sumoObj->getObjectHandle(); - m_hitObject = NULL; m_colliders = new CListValue(); KX_ClientObjectInfo *client_info = gameobj->getClientInfo(); @@ -98,8 +94,16 @@ m_bLastTriggered(false) m_physCtrl = dynamic_cast(gameobj->GetPhysicsController()); MT_assert( !gameobj->GetPhysicsController() || m_physCtrl ); + Init(); } +void KX_TouchSensor::Init() +{ + m_bCollision = false; + m_bTriggered = false; + m_bLastTriggered = (m_invert)?true:false; + m_hitObject = NULL; +} KX_TouchSensor::~KX_TouchSensor() { diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index f594196628a..056440ccd6c 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -72,6 +72,7 @@ public: virtual CValue* GetReplica(); virtual void SynchronizeTransform(); virtual bool Evaluate(CValue* event); + virtual void Init(); virtual void ReParent(SCA_IObject* parent); virtual void RegisterSumo(KX_TouchEventManager* touchman); diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index ff55f975543..ec7496daa75 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -25,11 +25,35 @@ class KX_GameObject: @ivar timeOffset: adjust the slowparent delay at runtime. @type timeOffset: float """ - + def endObject(visible): + """ + Delete this object, can be used inpace of the EndObject Actuator. + The actual removal of the object from the scene is delayed. + """ + def getVisible(visible): + """ + Gets the game object's visible flag. + + @type visible: boolean + """ def setVisible(visible): """ Sets the game object's visible flag. + @type visible: boolean + """ + def getState(): + """ + Gets the game object's state bitmask. + + @rtype: int + @return: the objects state. + """ + def setState(): + """ + Sets the game object's visible flag. + The bitmasks for states from 1 to 30 can be set with (1<<0, 1<<1, 1<<2 ... 1<<29) + @type visible: boolean """ def setPosition(pos): @@ -50,8 +74,9 @@ class KX_GameObject: """ Sets the game object's orientation. - @type orn: 3x3 inverted rotation matrix, or Quaternion. + @type orn: 3x3 rotation matrix, or Quaternion. @param orn: a rotation matrix specifying the new rotation. + @note: When using this matrix with Blender.Mathutils.Matrix() types, it will need to be transposed. """ def alignAxisToVect(vect, axis): """ @@ -71,6 +96,7 @@ class KX_GameObject: @rtype: 3x3 inverted rotation matrix @return: The game object's rotation matrix + @note: When using this matrix with Blender.Mathutils.Matrix() types, it will need to be transposed. """ def getLinearVelocity(local): """ @@ -174,6 +200,12 @@ class KX_GameObject: """ Returns the user data object associated with this game object's physics controller. """ + def getPropertyNames(): + """ + Gets a list of all property names. + @rtype: list + @return: All property names for this object. + """ def getDistanceTo(other): """ Returns the distance to another object or point. @@ -214,7 +246,7 @@ class KX_GameObject: If is casted from/to object center or explicit [x,y,z] points. The ray does not have X-Ray capability: the first object hit (other than self object) stops the ray If a property was specified and the first object hit does not have that property, there is no hit - The ray ignores collision-free objects + The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. @param to: [x,y,z] or object to which the ray is casted @type to: L{KX_GameObject} or 3-tuple diff --git a/source/gameengine/PyDoc/SCA_PythonController.py b/source/gameengine/PyDoc/SCA_PythonController.py index eb9e57c0819..6d91736d636 100644 --- a/source/gameengine/PyDoc/SCA_PythonController.py +++ b/source/gameengine/PyDoc/SCA_PythonController.py @@ -46,4 +46,12 @@ class SCA_PythonController(SCA_IController): @type script: string. """ + def getState(): + """ + Get the controllers state bitmask, this can be used with the GameObject's state to test if the the controller is active. + This for instance will always be true however you could compare with a previous state to see when the state was activated. + GameLogic.getCurrentController().getState() & GameLogic.getCurrentController().getOwner().getState() + + @rtype: int + """ diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index e9ab4ccca8d..23153fcd86c 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -54,7 +54,7 @@ RAS_2DFilterManager::RAS_2DFilterManager(): -texname(-1), texturewidth(-1), textureheight(-1), +texturewidth(-1), textureheight(-1), canvaswidth(-1), canvasheight(-1), numberoffilters(0) { @@ -72,8 +72,9 @@ numberoffilters(0) { m_filters[passindex] = 0; m_enabled[passindex] = 0; + texflag[passindex] = 0; } - + texname[0] = texname[1] = texname[2] = -1; } RAS_2DFilterManager::~RAS_2DFilterManager() @@ -150,30 +151,54 @@ unsigned int RAS_2DFilterManager::CreateShaderProgram(int filtermode) return 0; } -void RAS_2DFilterManager::StartShaderProgram(unsigned int shaderprogram) +void RAS_2DFilterManager::StartShaderProgram(int passindex) { GLint uniformLoc; - glUseProgramObjectARB(shaderprogram); - uniformLoc = glGetUniformLocationARB(shaderprogram, "bgl_RenderedTexture"); + glUseProgramObjectARB(m_filters[passindex]); + uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_RenderedTexture"); glActiveTextureARB(GL_TEXTURE0); - //glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texname); + glBindTexture(GL_TEXTURE_2D, texname[0]); if (uniformLoc != -1) { glUniform1iARB(uniformLoc, 0); } - uniformLoc = glGetUniformLocationARB(shaderprogram, "bgl_TextureCoordinateOffset"); + + /* send depth texture to glsl program if it needs */ + if(texflag[passindex] & 0x1){ + uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture"); + glActiveTextureARB(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, texname[1]); + + if (uniformLoc != -1) + { + glUniform1iARB(uniformLoc, 1); + } + } + + /* send luminance texture to glsl program if it needs */ + if(texflag[passindex] & 0x1){ + uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_LuminanceTexture"); + glActiveTextureARB(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, texname[2]); + + if (uniformLoc != -1) + { + glUniform1iARB(uniformLoc, 2); + } + } + + uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_TextureCoordinateOffset"); if (uniformLoc != -1) { glUniform2fvARB(uniformLoc, 9, textureoffsets); } - uniformLoc = glGetUniformLocationARB(shaderprogram, "bgl_RenderedTextureWidth"); + uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_RenderedTextureWidth"); if (uniformLoc != -1) { glUniform1fARB(uniformLoc,texturewidth); } - uniformLoc = glGetUniformLocationARB(shaderprogram, "bgl_RenderedTextureHeight"); + uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_RenderedTextureHeight"); if (uniformLoc != -1) { glUniform1fARB(uniformLoc,textureheight); @@ -187,14 +212,33 @@ void RAS_2DFilterManager::EndShaderProgram() void RAS_2DFilterManager::SetupTexture() { - if(texname!=-1) + if(texname[0]!=-1 || texname[1]!=-1) { - glDeleteTextures(1,(const GLuint *)&texname); + glDeleteTextures(2, (GLuint*)texname); } - glGenTextures(1, (GLuint *)&texname); - glBindTexture(GL_TEXTURE_2D, texname); + glGenTextures(3, (GLuint*)texname); + + glBindTexture(GL_TEXTURE_2D, texname[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texturewidth, textureheight, 0, GL_RGB, - GL_UNSIGNED_BYTE, 0); + GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + glBindTexture(GL_TEXTURE_2D, texname[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, texturewidth,textureheight, 0, GL_DEPTH_COMPONENT, + GL_FLOAT,NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, + GL_NONE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + glBindTexture(GL_TEXTURE_2D, texname[2]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE16, texturewidth, textureheight, 0, GL_LUMINANCE, + GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); @@ -246,12 +290,27 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) int passindex; bool first = true; + for(passindex =0; passindex