From b2be0a181f26b5bf55ad377936cab424e3de6577 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 27 Jul 2008 11:41:39 +0000 Subject: [PATCH 01/58] Bugfix #17334: This bug-report revealed a critical error made in the menus for Constraints Owner/Target spaces. It seems that the wrong values have been used for 'pose space' and 'local with parent' space. This has now been rectified, so that old rigs won't break (just that the labels will be a bit different). --- source/blender/makesdna/DNA_constraint_types.h | 10 ++++++---- source/blender/src/buttons_object.c | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 0fe0dace016..fa5b5a75941 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -375,11 +375,13 @@ typedef enum B_CONSTRAINT_SPACETYPES { /* for objects (relative to parent/without parent influence), * for bones (along normals of bone, without parent/restpositions) */ - CONSTRAINT_SPACE_LOCAL, + CONSTRAINT_SPACE_LOCAL, /* = 1 */ /* for posechannels - pose space */ - CONSTRAINT_SPACE_POSE, - /* for posechannels - local with parent */ - CONSTRAINT_SPACE_PARLOCAL, + CONSTRAINT_SPACE_POSE, /* = 2 */ + /* for posechannels - local with parent */ + CONSTRAINT_SPACE_PARLOCAL, /* = 3 */ + /* for files from between 2.43-2.46 (should have been parlocal) */ + CONSTRAINT_SPACE_INVALID, /* = 4. do not exchange for anything! */ } B_CONSTRAINT_SPACETYPES; /* bConstraintChannel.flag */ diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index ebe770c89e7..2c7802c3302 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -480,7 +480,7 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short /* Target-Space */ if (target == 1) { - uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1", + uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x2|Local with Parent %x3|Local Space %x1", tarx, yco, bwidth, 18, &con->tarspace, 0, 0, 0, 0, "Choose space that target is evaluated in"); } else if (target == 0) { @@ -490,7 +490,7 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short /* Owner-Space */ if (owner == 1) { - uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1", + uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Pose Space %x2|Local with Parent %x3|Local Space %x1", ownx, yco, bwidth, 18, &con->ownspace, 0, 0, 0, 0, "Choose space that owner is evaluated in"); } else if (owner == 0) { From f4def51cd3c225cf3bbe7895f729a29a5d4067e5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 27 Jul 2008 12:48:46 +0000 Subject: [PATCH 02/58] #17309: Copy/pasting bone names (without editing text) doesn't update bone/pose names The pasting code for text-buttons (when hovering over the button), was incorrectly using the drawstr (i.e. the string that is displayed in the text-button, and includes the 'name' of the button) as the old value. This meant that the renaming code could not correctly detect matches to rename. --- source/blender/src/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 18e596abcc7..e7b5b176979 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -532,7 +532,7 @@ static int ui_but_copy_paste(uiBut *but, char mode) /* give butfunc the original text too */ /* feature used for bone renaming, channels, etc */ if(but->func_arg2==NULL) { - strncpy(backstr, but->drawstr, UI_MAX_DRAW_STR); + strncpy(backstr, but->poin, UI_MAX_DRAW_STR); but->func_arg2= backstr; } strncpy(but->poin, but_copypaste_str, but->max); From edf557cb1c98c76fe56bcd21d7e8e461ce89d0d9 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Mon, 28 Jul 2008 00:21:34 +0000 Subject: [PATCH 03/58] * Fix for Aligorith's fix for my mistaken uninitialised variable in outliner.c - it was never needed in the first place. --- source/blender/src/outliner.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index a8e864998b1..3f328a0cfb2 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -3718,13 +3718,6 @@ static void outliner_draw_restrictbuts(uiBlock *block, SpaceOops *soops, ListBas uiButSetFunc(bt, restrictbutton_modifier_cb, ob, NULL); uiButSetFlag(bt, UI_NO_HILITE); - /* - bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Editmode, REDRAWALL, VICON_EDIT, - (int)soops->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); - uiButSetFunc(bt, restrictbutton_modifier_cb, ob, NULL); - uiButSetFlag(bt, UI_NO_HILITE); - */ - bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, REDRAWALL, ICON_RESTRICT_RENDER_OFF, (int)soops->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability"); uiButSetFunc(bt, restrictbutton_modifier_cb, ob, NULL); @@ -3733,24 +3726,20 @@ static void outliner_draw_restrictbuts(uiBlock *block, SpaceOops *soops, ListBas else if(tselem->type==TSE_POSE_CHANNEL) { bPoseChannel *pchan= (bPoseChannel *)te->directdata; Bone *bone = pchan->bone; - - ob = (Object *)tselem->id; - + uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, REDRAWALL, ICON_RESTRICT_VIEW_OFF, (int)soops->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); - uiButSetFunc(bt, restrictbutton_bone_cb, ob, NULL); + uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); uiButSetFlag(bt, UI_NO_HILITE); } else if(tselem->type==TSE_EBONE) { EditBone *ebone= (EditBone *)te->directdata; - - ob = (Object *)tselem->id; - + uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, REDRAWALL, ICON_RESTRICT_VIEW_OFF, (int)soops->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); - uiButSetFunc(bt, restrictbutton_bone_cb, ob, NULL); + uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); uiButSetFlag(bt, UI_NO_HILITE); } } From 8162215f2a749edcb2fa24e5cc9d7de179ac1cb9 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 28 Jul 2008 04:08:46 +0000 Subject: [PATCH 04/58] Bugfix: Bone-locking should only be set if the bone (and not its parent/children) are selected. Transposition error from the patch (I had to manually apply as there were some oddities about the patch file). --- source/blender/src/editarmature.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index d0f44263fb7..3d0f26960d6 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -2717,7 +2717,7 @@ void set_locks_armature_bones(short lock) for (ebone = G.edbo.first; ebone; ebone=ebone->next) { if (arm->layer & ebone->layer) { - if (ebone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL)) { + if (ebone->flag & BONE_SELECTED) { if (lock) ebone->flag |= BONE_EDITMODE_LOCKED; else From 91ece746b8a2bbf0bc3a801ece502f8a4977d5ca Mon Sep 17 00:00:00 2001 From: Remigiusz Fiedler Date: Mon, 28 Jul 2008 10:13:56 +0000 Subject: [PATCH 05/58] commit by jms: Rvk1 to rvk2 script python did not work anymore with the softbodie in blender 2.46. Only one line needs to be removed. --- release/scripts/rvk1_torvk2.py | 64 +++++++++++++++++----------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/release/scripts/rvk1_torvk2.py b/release/scripts/rvk1_torvk2.py index c723efb61a7..a48d065813a 100644 --- a/release/scripts/rvk1_torvk2.py +++ b/release/scripts/rvk1_torvk2.py @@ -14,7 +14,7 @@ __url__ = ("blender", "blenderartists.org", __version__ = "2007/04/27" __bpydoc__ = """\ -"DEFORM to RVK2" copies deform data (except EDGESPLIT,DECIMATE,SUBSURF,BOOLEAN, +"DEFORM to RVK2" copies deform data (except EDGESPLIT,DECIMATE,SUBSURF,BOOLEAN, BUILD,MIRROR,ARRAY) of the active object to the RVK (relative vertex key) of the other selected object. @@ -25,7 +25,7 @@ key. The new version of this scrit (Blender 2.43) manages the modifier changes. There are a lot of modifiers but only the ones which just deforms the shape can be used : LATTICE, CURVE, WAVE, ARMATURE. You can unset these modifiers -from the script. +from the script. Usage: @@ -35,7 +35,7 @@ the 3d View. If the active object has subsurf turned on and nonzero subdiv level, the script will ask if it should change that. Before copying data to the rvk it will also ask whether it should replace or add a new vertex group. - + """ #---------------------------------------------- @@ -70,7 +70,7 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ # Copy the rvk (1, or armature, lattice, or # any mesh deformation except surface @@ -83,7 +83,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # download the script : # http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py # Communicate upon problems or errors: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender +# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender #---------------------------------------------- # Page officielle : # http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py @@ -101,22 +101,22 @@ def Value(t): exec "t=Modifier.Types.%s"%t return t -def deform2rvk(): +def deform2rvk(): POSSMOD_list=['EDGESPLIT', 'DECIMATE', - 'SUBSURF', - 'BOOLEAN', + 'SUBSURF', + 'BOOLEAN', 'BUILD', - 'MIRROR', + 'MIRROR', 'ARRAY'] AUTHMOD_list=['LATTICE', - 'CURVE', + 'CURVE', 'WAVE', 'ARMATURE'] MODIFIERS=0 - + BMOD=[['Possible Modifiers'], ['Allowed Modifiers']] @@ -129,8 +129,8 @@ def deform2rvk(): # ============================================================= # must be 2 meshes ============================================ # ============================================================= - if RVK1.getType()=='Mesh' and RVK2.getType()=='Mesh': - FRAME=Blender.Get('curframe') + if RVK1.getType()=='Mesh' and RVK2.getType()=='Mesh': + FRAME=Blender.Get('curframe') DATA2=RVK2.getData() if DEBUG: print DATA2.getKey() # ============================================================ @@ -151,7 +151,7 @@ def deform2rvk(): # === Bloc Menu Modifiers ===1 doc ================= # =================================================== m=0 - for mod in MODRVK1: + for mod in MODRVK1: if DEBUG: print mod.type if mod.type in POSSMOD: BMOD[0].append([Draw.Create(0),mod.type, @@ -183,7 +183,7 @@ def deform2rvk(): retval = Blender.Draw.PupBlock("MESH 2 RVK", block) # =================================================== # === unset Modifiers ============================= - # =================================================== + # =================================================== for B in BMOD[0][1:]: if DEBUG: print B[2] MODRVK1[B[2]][Modifier.Settings.RENDER]=0 @@ -193,12 +193,12 @@ def deform2rvk(): # =================================================== # === update Modifiers ============================= # =================================================== - RVK1.makeDisplayList() + #RVK1.makeDisplayList() # ======================================================= # === get deformed mesh ================================ # ======================================================= RVK1NAME=Object.GetSelected()[0].getName() - meshrvk1=NMesh.GetRawFromObject(RVK1NAME) + meshrvk1=NMesh.GetRawFromObject(RVK1NAME) if DEBUG: print len(meshrvk1.verts) # ======================================================= # === get normal mesh for vertex group ================= @@ -209,18 +209,18 @@ def deform2rvk(): # ======================================================= DATA2=RVK2.getData() if DEBUG: print len(meshrvk1.verts) - if DEBUG: print len(DATA2.verts) + if DEBUG: print len(DATA2.verts) # ======================================================== # ===== is there the same number of vertices ============= # ======================================================== - if len(meshrvk1.verts)==len(DATA2.verts): - name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 " + if len(meshrvk1.verts)==len(DATA2.verts): + name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 " result = Draw.PupMenu(name) - if result==1: + if result==1: # ===================================================== # ===== Do we save vertex groups ? =================== # ===================================================== - GROUPNAME2=DATA2.getVertGroupNames() + GROUPNAME2=DATA2.getVertGroupNames() if len(GROUPNAME2)!=0: for GROUP2 in GROUPNAME2: DATA2.removeVertGroup(GROUP2) @@ -233,11 +233,11 @@ def deform2rvk(): # ===== now copy the vertices coords ===================== # ======================================================== for v in meshrvk1.verts: - i= meshrvk1.verts.index(v) + i= meshrvk1.verts.index(v) v1=DATA2.verts[i] for n in [0,1,2]: v1.co[n]=v.co[n] - DATA2.update() + DATA2.update() DATA2.insertKey(FRAME,'relative') DATA2.update() RVK2.makeDisplayList() @@ -251,23 +251,23 @@ def deform2rvk(): if not B[1]: MODRVK1[B[2]][Modifier.Settings.RENDER]|=B[-2] else: - name = "Meshes Objects must the same number of vertices %t| Ok. %x1" + name = "Meshes Objects must the same number of vertices %t| Ok. %x1" result = Draw.PupMenu(name) return else: - name = "Second Object must have at least a shape key %t| Ok. %x1" + name = "Second Object must have at least a shape key %t| Ok. %x1" result = Draw.PupMenu(name) return - else: - name = "Object must be Meshes %t| Ok. %x1" + else: + name = "Object must be Meshes %t| Ok. %x1" result = Draw.PupMenu(name) - return + return else : - name = "At least 2 Meshes as to be selected %t| Ok. %x1" + name = "At least 2 Meshes as to be selected %t| Ok. %x1" result = Draw.PupMenu(name) return - Blender.Redraw() + Blender.Redraw() EDITMODE=Blender.Window.EditMode() Blender.Window.EditMode(0) deform2rvk() -Blender.Window.EditMode(EDITMODE) +Blender.Window.EditMode(EDITMODE) \ No newline at end of file From bc85f11e68d1c1af9e5d48afbe38c26686badcf3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 28 Jul 2008 14:28:19 +0000 Subject: [PATCH 06/58] Bugfix: game engine does not support non-camera type objects as a camera, would crash, so disabled using the object as a camera then. --- source/gameengine/Converter/BL_BlenderDataConversion.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 31a055fc734..320921722e1 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2258,7 +2258,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } } - if (blenderscene->camera) { + // non-camera objects not supported as camera currently + if (blenderscene->camera && blenderscene->camera->type == OB_CAMERA) { KX_Camera *gamecamera= (KX_Camera*) converter->FindGameObject(blenderscene->camera); if(gamecamera) From 3120af6f34b3c2dc5007eb8bb4d1031d6b6dfde0 Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Mon, 28 Jul 2008 22:10:32 +0000 Subject: [PATCH 07/58] Bugfix for #17396. Adding a text object would segfault when using freetype 2.3.6 or later. Thanks to Cyril Brulebois for a one-line patch, which was sent to the ML a while back. --- source/blender/blenlib/intern/freetypefont.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 8b979f9ed23..74f152ac635 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -405,7 +405,7 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf) lcode = charcode; } - err = FT_Set_Charmap( face, (FT_CharMap) FT_ENCODING_UNICODE ); + err = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); return vfd; } From b0c513e83a638533b117d8b14b169b4fdd7a0369 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 28 Jul 2008 22:36:27 +0000 Subject: [PATCH 08/58] BGE patch: fix support of group hidden layer in dupli group instantiation: only the objects in layers matching the group layer mask will be instantiated. This is equivalent to the 3D view --- source/gameengine/Ketsji/KX_Scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 2d84d8f035d..648a6ca31d5 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -657,7 +657,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // Should not happen as dupli group are created automatically continue; } - if (blenderobj->lay & group->layer==0) + if ((blenderobj->lay & group->layer)==0) { // object is not visible in the 3D view, will not be instantiated continue; From 908337bee11f6b55c34a5880ea241b3975c35287 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 29 Jul 2008 15:48:31 +0000 Subject: [PATCH 09/58] Game Engine: alpha blending and sorting ======================================= Alpha blending + sorting was revised, to fix bugs and get it to work more predictable. * A new per texture face "Sort" setting defines if the face is alpha sorted or not, instead of abusing the "ZTransp" setting as it did before. * Existing files are converted to hopefully match the old behavior as much as possible with a version patch. * On new meshes the Sort flag is disabled by the default, to avoid unexpected and hard to find slowdowns. * Alpha sorting for faces was incredibly slow. Sorting faces in a mesh with 600 faces lowered the framerate from 200 to 70 fps in my test.. the sorting there case goes about 15x faster now, but it is still advised to use Clip Alpha if possible instead of regular Alpha. * There still various limitations in the alpha sorting code, I've added some comments to the code about this. Some docs at the bottom of the page: http://www.blender.org/development/current-projects/changes-since-246/realtime-glsl-materials/ Merged some fixes from the apricot branch, most important change is that tangents are now exactly the same as the rest of Blender, instead of being computed in the game engine with a different algorithm. Also, the subversion was bumped to 1. --- source/blender/blenkernel/BKE_DerivedMesh.h | 2 + source/blender/blenkernel/BKE_blender.h | 2 +- .../blender/blenkernel/intern/DerivedMesh.c | 122 ++++ source/blender/blenkernel/intern/customdata.c | 7 +- source/blender/blenloader/intern/readfile.c | 53 +- .../blender/makesdna/DNA_customdata_types.h | 4 +- source/blender/makesdna/DNA_meshdata_types.h | 2 +- source/blender/src/buttons_editing.c | 1 + .../BlenderRoutines/KX_BlenderGL.cpp | 1 + .../KX_BlenderPolyMaterial.cpp | 114 --- .../BlenderRoutines/KX_BlenderPolyMaterial.h | 99 --- .../BlenderRoutines/KX_BlenderRenderTools.cpp | 1 - .../Converter/BL_BlenderDataConversion.cpp | 653 ++++++++---------- source/gameengine/Ketsji/BL_BlenderShader.cpp | 85 ++- source/gameengine/Ketsji/BL_BlenderShader.h | 14 +- source/gameengine/Ketsji/BL_Material.h | 5 +- source/gameengine/Ketsji/BL_Texture.cpp | 2 - .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 121 ++-- source/gameengine/Ketsji/KX_BlenderMaterial.h | 9 +- source/gameengine/Ketsji/KX_GameObject.cpp | 12 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 3 +- .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 10 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 3 +- source/gameengine/Ketsji/KX_Scene.cpp | 22 +- .../Rasterizer/RAS_BucketManager.cpp | 43 +- .../gameengine/Rasterizer/RAS_BucketManager.h | 3 +- .../Rasterizer/RAS_IPolygonMaterial.cpp | 14 +- .../Rasterizer/RAS_IPolygonMaterial.h | 10 +- .../gameengine/Rasterizer/RAS_IRasterizer.h | 10 +- .../Rasterizer/RAS_MaterialBucket.cpp | 24 +- .../Rasterizer/RAS_MaterialBucket.h | 7 +- .../gameengine/Rasterizer/RAS_MeshObject.cpp | 188 +++-- source/gameengine/Rasterizer/RAS_MeshObject.h | 29 +- .../RAS_OpenGLRasterizer.cpp | 48 +- .../RAS_OpenGLRasterizer.h | 9 +- source/gameengine/Rasterizer/RAS_Polygon.cpp | 18 - 36 files changed, 868 insertions(+), 882 deletions(-) delete mode 100644 source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp delete mode 100644 source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index f61b300f708..7dc10c53e22 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -437,5 +437,7 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb); /* determines required DerivedMesh data according to view and edit modes */ CustomDataMask get_viewedit_datamask(); +void DM_add_tangent_layer(DerivedMesh *dm); + #endif diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f76cdbc64b7..d951c8401e3 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 246 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 4d3f9143b85..67cf89d5ee2 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -59,6 +59,7 @@ #include "BLI_edgehash.h" #include "BLI_editVert.h" #include "BLI_linklist.h" +#include "BLI_memarena.h" #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" @@ -2844,6 +2845,127 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo return numleft; } +void DM_add_tangent_layer(DerivedMesh *dm) +{ + /* mesh vars */ + MTFace *mtface, *tf; + MFace *mface, *mf; + MVert *mvert, *v1, *v2, *v3, *v4; + MemArena *arena= NULL; + VertexTangent **vtangents= NULL; + float (*orco)[3]= NULL, (*tangent)[3]; + float *uv1, *uv2, *uv3, *uv4, *vtang; + float fno[3], tang[3], uv[4][2]; + int i, j, len, mf_vi[4], totvert, totface; + + if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1) + return; + + /* check we have all the needed layers */ + totvert= dm->getNumVerts(dm); + totface= dm->getNumFaces(dm); + + mvert= dm->getVertArray(dm); + mface= dm->getFaceArray(dm); + mtface= dm->getFaceDataArray(dm, CD_MTFACE); + + if(!mtface) { + orco= dm->getVertDataArray(dm, CD_ORCO); + if(!orco) + return; + } + + /* create tangent layer */ + DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL); + tangent= DM_get_face_data_layer(dm, CD_TANGENT); + + /* allocate some space */ + arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_calloc(arena); + vtangents= MEM_callocN(sizeof(VertexTangent*)*totvert, "VertexTangent"); + + /* sum tangents at connected vertices */ + for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) { + v1= &mvert[mf->v1]; + v2= &mvert[mf->v2]; + v3= &mvert[mf->v3]; + + if (mf->v4) { + v4= &mvert[mf->v4]; + CalcNormFloat4(v4->co, v3->co, v2->co, v1->co, fno); + } + else { + v4= NULL; + CalcNormFloat(v3->co, v2->co, v1->co, fno); + } + + if(mtface) { + uv1= tf->uv[0]; + uv2= tf->uv[1]; + uv3= tf->uv[2]; + uv4= tf->uv[3]; + } + else { + uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; + spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]); + spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]); + spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]); + if(v4) + spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]); + } + + tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); + + if(mf->v4) { + v4= &mvert[mf->v4]; + + tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4); + } + } + + /* write tangent to layer */ + for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) { + len= (mf->v4)? 4 : 3; + + if(mtface) { + uv1= tf->uv[0]; + uv2= tf->uv[1]; + uv3= tf->uv[2]; + uv4= tf->uv[3]; + } + else { + uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; + spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]); + spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]); + spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]); + if(len==4) + spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]); + } + + mf_vi[0]= mf->v1; + mf_vi[1]= mf->v2; + mf_vi[2]= mf->v3; + mf_vi[3]= mf->v4; + + for(j=0; juv[j] : uv[j]); + + VECCOPY(tangent[j], vtang); + Normalize(tangent[j]); + } + } + + BLI_memarena_free(arena); + MEM_freeN(vtangents); +} + + /* ************************* fluidsim bobj file handling **************************** */ #ifndef DISABLE_ELBEEM diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 501293ecd81..9012adb09b7 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -532,13 +532,14 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, - {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol} + {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, + {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL} }; const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty", - "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol"}; + "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent"}; const CustomDataMask CD_MASK_BAREMESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE; @@ -552,7 +553,7 @@ const CustomDataMask CD_MASK_EDITMESH = const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | - CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO; + CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT; const CustomDataMask CD_MASK_BMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; const CustomDataMask CD_MASK_FACECORNERS = diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ad004dd5c82..ad19cde3c9b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4870,6 +4870,49 @@ void idproperties_fix_group_lengths(ListBase idlist) } } +void alphasort_version_246(FileData *fd, Library *lib, Mesh *me) +{ + Material *ma; + MFace *mf; + MTFace *tf; + int a, b, texalpha; + + /* verify we have a tface layer */ + for(b=0; bfdata.totlayer; b++) + if(me->fdata.layers[b].type == CD_MTFACE) + break; + + if(b == me->fdata.totlayer) + return; + + /* if we do, set alpha sort if the game engine did it before */ + for(a=0, mf=me->mface; atotface; a++, mf++) { + if(mf->mat_nr < me->totcol) { + ma= newlibadr(fd, lib, me->mat[mf->mat_nr]); + texalpha = 0; + + for(b=0; ma && bmtex && ma->mtex[b] && ma->mtex[b]->mapto & MAP_ALPHA) + texalpha = 1; + } + else { + ma= NULL; + texalpha = 0; + } + + for(b=0; bfdata.totlayer; b++) { + if(me->fdata.layers[b].type == CD_MTFACE) { + tf = ((MTFace*)me->fdata.layers[b].data) + a; + + tf->mode &= ~TF_ALPHASORT; + if(ma && (ma->mode & MA_ZTRA)) + if(ELEM(tf->transp, TF_ALPHA, TF_ADD) || (texalpha && (tf->transp != TF_CLIP))) + tf->mode |= TF_ALPHASORT; + } + } + } +} + static void do_versions(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ @@ -7714,8 +7757,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } /* sun/sky */ - if ((main->versionfile < 246) ){ + if(main->versionfile < 246) { Lamp *la; + for(la=main->lamp.first; la; la= la->id.next) { la->sun_effect_type = 0; la->horizon_brightness = 1.0; @@ -7731,6 +7775,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if(main->versionfile <= 246 && main->subversionfile < 1){ + Mesh *me; + + for(me=main->mesh.first; me; me= me->id.next) + alphasort_version_246(fd, lib, me); + } + /* 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/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 72557145270..6c098e220bb 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -71,7 +71,8 @@ typedef struct CustomData { #define CD_MTEXPOLY 15 #define CD_MLOOPUV 16 #define CD_MLOOPCOL 17 -#define CD_NUMTYPES 18 +#define CD_TANGENT 18 +#define CD_NUMTYPES 19 /* Bits for CustomDataMask */ #define CD_MASK_MVERT (1 << CD_MVERT) @@ -92,6 +93,7 @@ typedef struct CustomData { #define CD_MASK_MTEXPOLY (1 << CD_MTEXPOLY) #define CD_MASK_MLOOPUV (1 << CD_MLOOPUV) #define CD_MASK_MLOOPCOL (1 << CD_MLOOPCOL) +#define CD_MASK_TANGENT (1 << CD_TANGENT) /* CustomData.flag */ diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 6d025839ac8..4e427ed733c 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -228,7 +228,7 @@ typedef struct PartialVisibility { /* mtface->mode */ #define TF_DYNAMIC 1 -#define TF_DEPRECATED 2 +#define TF_ALPHASORT 2 #define TF_TEX 4 #define TF_SHAREDVERT 8 #define TF_LIGHT 16 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 180fdc852ae..b26c52a92e2 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -6189,6 +6189,7 @@ static void editing_panel_mesh_texface(void) uiDefButBitS(block, TOG, TF_BILLBOARD2, B_TFACE_BILLB, "Billboard",660,110,60,19, &tf->mode, 0, 0, 0, 0, "Billboard with Z-axis constraint"); uiDefButBitS(block, TOG, TF_SHADOW, REDRAWVIEW3D, "Shadow", 720,110,60,19, &tf->mode, 0, 0, 0, 0, "Face is used for shadow"); uiDefButBitS(block, TOG, TF_BMFONT, REDRAWVIEW3D, "Text", 780,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable bitmap text on face"); + uiDefButBitS(block, TOG, TF_ALPHASORT, REDRAWVIEW3D, "Sort", 840,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable sorting of faces for correct alpha drawing (slow, use Clip Alpha instead when possible)"); uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index ed6ea7c5f6a..da52be56d1b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -170,6 +170,7 @@ void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface void DisableForText() { if(glIsEnabled(GL_BLEND)) glDisable(GL_BLEND); + if(glIsEnabled(GL_ALPHA_TEST)) glDisable(GL_ALPHA_TEST); if(glIsEnabled(GL_LIGHTING)) { glDisable(GL_LIGHTING); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp deleted file mode 100644 index d173b1c66d9..00000000000 --- a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "KX_BlenderPolyMaterial.h" -#include "BKE_mesh.h" - -#ifdef HAVE_CONFIG_H -#include -#endif -#if 0 -KX_BlenderPolyMaterial::KX_BlenderPolyMaterial(const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - struct MTFace* tface) - : RAS_IPolyMaterial(texname, - false, - matname, - tile, - tilexrep, - tileyrep, - mode, - transparant, - zsort, - lightlayer, - bIsTriangle, - clientobject), - m_tface(tface) -{ -} - -void KX_BlenderPolyMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const -{ - - - if (GetCachingInfo() != cachingInfo) - { - if (!cachingInfo) - { - set_tpage(NULL); - } - cachingInfo = GetCachingInfo(); - - if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)) - { - update_realtime_texture((struct MTFace*) m_tface, rasty->GetTime()); - set_tpage(m_tface); - rasty->EnableTextures(true); - } - else - { - set_tpage(NULL); - rasty->EnableTextures(false); - } - - if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE) - { - rasty->SetCullFace(false); - } - else - { - rasty->SetCullFace(true); - } - - if (m_drawingmode & RAS_IRasterizer::KX_LINES) { - rasty->SetLines(true); - } - else { - rasty->SetLines(false); - } - } - - rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity); - rasty->SetShinyness(m_shininess); - rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0); -} - - -#endif - - diff --git a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h deleted file mode 100644 index 35823b2125b..00000000000 --- a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __KX_BLENDERPOLYMATERIAL -#define __KX_BLENDERPOLYMATERIAL - -#include "RAS_MaterialBucket.h" -#include "RAS_IRasterizer.h" - -struct MTFace; -extern "C" int set_tpage(MTFace* tface); /* Worst hack ever */ - -#if 0 -class KX_BlenderPolyMaterial : public RAS_IPolyMaterial -{ - /** Blender texture face structure. */ - MTFace* m_tface; - -public: - - KX_BlenderPolyMaterial(const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - struct MTFace* tface); - - /** - * Returns the caching information for this material, - * This can be used to speed up the rasterizing process. - * @return The caching information. - */ - virtual TCachingInfo GetCachingInfo(void) const; - - /** - * Activates the material in the (OpenGL) rasterizer. - * On entry, the cachingInfo contains info about the last activated material. - * On exit, the cachingInfo should contain updated info about this material. - * @param rasty The rasterizer in which the material should be active. - * @param cachingInfo The information about the material used to speed up rasterizing. - */ - virtual void Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const; - - /** - * Returns the Blender texture face structure that is used for this material. - * @return The material's texture face. - */ - MTFace* GetMTFace(void) const; -protected: -private: -}; - - -inline MTFace* KX_BlenderPolyMaterial::GetMTFace(void) const -{ - return m_tface; -} - -inline RAS_IPolyMaterial::TCachingInfo KX_BlenderPolyMaterial::GetCachingInfo(void) const -{ - return GetMTFace(); -} - -#endif - -#endif // __KX_BLENDERPOLYMATERIAL - diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 220d174d464..e4eff163d5b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -40,7 +40,6 @@ // it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" -#include "KX_BlenderPolyMaterial.h" #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 320921722e1..2cc5cfda84c 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -136,8 +136,12 @@ #include "BKE_mesh.h" #include "MT_Point3.h" +#include "BLI_arithb.h" + extern "C" { - #include "BKE_customdata.h" +#include "BKE_customdata.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_DerivedMesh.h" } #include "BKE_material.h" /* give_current_material */ @@ -309,7 +313,6 @@ typedef struct MTF_localLayer // ------------------------------------ BL_Material* ConvertMaterial( - Mesh* mesh, Material *mat, MTFace* tface, const char *tfaceName, @@ -323,15 +326,16 @@ BL_Material* ConvertMaterial( //this needs some type of manager BL_Material *material = new BL_Material(); - int numchan = -1; + int numchan = -1, texalpha = 0; bool validmat = (mat!=0); - bool validface = (mesh->mtface && tface); + bool validface = (tface!=0); short type = 0; if( validmat ) type = 1; // material color material->IdMode = DEFAULT_BLENDER; + material->glslmat = (validmat)? glslmat: false; // -------------------------------- if(validmat) { @@ -367,12 +371,13 @@ BL_Material* ConvertMaterial( if(i==0 && facetex ) { Image*tmp = (Image*)(tface->tpage); + if(tmp) { material->img[i] = tmp; material->texname[i] = material->img[i]->id.name; material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0; - material->ras_mode|= ( tface->transp &(TF_ADD | TF_ALPHA))?TRANSP:0; + if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; else @@ -430,6 +435,8 @@ BL_Material* ConvertMaterial( material->flag[i] |= ( mttmp->mapto & MAP_ALPHA )?TEXALPHA:0; material->flag[i] |= ( mttmp->texflag& MTEX_NEGATIVE )?TEXNEG:0; + if(!glslmat && (material->flag[i] & TEXALPHA)) + texalpha = 1; } } else if(mttmp->tex->type == TEX_ENVMAP) { @@ -546,17 +553,7 @@ BL_Material* ConvertMaterial( material->ref = mat->ref; material->amb = mat->amb; - // set alpha testing without z-sorting - if( ( validface && (!(tface->transp &~ TF_CLIP))) && mat->mode & MA_ZTRA) { - // sets the RAS_IPolyMaterial::m_flag |RAS_FORCEALPHA - // this is so we don't have the overhead of the z-sorting code - material->ras_mode|=ALPHA_TEST; - } - else{ - // use regular z-sorting - material->ras_mode |= ((mat->mode & MA_ZTRA) != 0)?ZSORT:0; - } - material->ras_mode |= ((mat->mode & MA_WIRE) != 0)?WIRE:0; + material->ras_mode |= (mat->mode & MA_WIRE)? WIRE: 0; } else { int valid = 0; @@ -574,7 +571,6 @@ BL_Material* ConvertMaterial( material->mapping[0].mapping |= ( (material->img[0]->flag & IMA_REFLECT)!=0 )?USEREFL:0; material->flag[0] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[0] |= ( tface->transp &TF_ADD )?CALCALPHA:0; - material->ras_mode|= ( tface->transp & (TF_ADD|TF_ALPHA))?TRANSP:0; valid++; } } @@ -607,10 +603,6 @@ BL_Material* ConvertMaterial( material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0; material->transp = tface->transp; - - if(tface->transp&~TF_CLIP) - material->ras_mode |= TRANSP; - material->tile = tface->tile; material->mode = tface->mode; @@ -631,7 +623,15 @@ BL_Material* ConvertMaterial( material->tile = 0; } + // with ztransp enabled, enforce alpha blending mode + if(validmat && (mat->mode & MA_ZTRA) && (material->transp == TF_SOLID)) + material->transp = TF_ALPHA; + // always zsort alpha + add + if(material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) { + material->ras_mode |= ALPHA; + material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; + } // get uv sets if(validmat) @@ -711,132 +711,54 @@ BL_Material* ConvertMaterial( } -static void BL_ComputeTriTangentSpace(const MT_Vector3 &v1, const MT_Vector3 &v2, const MT_Vector3 &v3, - const MT_Vector2 &uv1, const MT_Vector2 &uv2, const MT_Vector2 &uv3, - MFace* mface, MT_Vector3 *tan1, MT_Vector3 *tan2) -{ - MT_Vector3 dx1(v2 - v1), dx2(v3 - v1); - MT_Vector2 duv1(uv2 - uv1), duv2(uv3 - uv1); - - MT_Scalar r = 1.0 / (duv1.x() * duv2.y() - duv2.x() * duv1.y()); - duv1 *= r; - duv2 *= r; - MT_Vector3 sdir(duv2.y() * dx1 - duv1.y() * dx2); - MT_Vector3 tdir(duv1.x() * dx2 - duv2.x() * dx1); - - tan1[mface->v1] += sdir; - tan1[mface->v2] += sdir; - tan1[mface->v3] += sdir; - - tan2[mface->v1] += tdir; - tan2[mface->v2] += tdir; - tan2[mface->v3] += tdir; -} - -static MT_Vector4* BL_ComputeMeshTangentSpace(Mesh* mesh) -{ - MFace* mface = static_cast(mesh->mface); - MTFace* tface = static_cast(mesh->mtface); - - MT_Vector3 *tan1 = new MT_Vector3[mesh->totvert]; - MT_Vector3 *tan2 = new MT_Vector3[mesh->totvert]; - - int v; - for (v = 0; v < mesh->totvert; v++) - { - tan1[v] = MT_Vector3(0.0, 0.0, 0.0); - tan2[v] = MT_Vector3(0.0, 0.0, 0.0); - } - - for (int p = 0; p < mesh->totface; p++, mface++, tface++) - { - MT_Vector3 v1(mesh->mvert[mface->v1].co), - v2(mesh->mvert[mface->v2].co), - v3(mesh->mvert[mface->v3].co); - - MT_Vector2 uv1(tface->uv[0]), - uv2(tface->uv[1]), - uv3(tface->uv[2]); - - BL_ComputeTriTangentSpace(v1, v2, v3, uv1, uv2, uv3, mface, tan1, tan2); - if (mface->v4) - { - MT_Vector3 v4(mesh->mvert[mface->v4].co); - MT_Vector2 uv4(tface->uv[3]); - - BL_ComputeTriTangentSpace(v1, v3, v4, uv1, uv3, uv4, mface, tan1, tan2); - } - } - - MT_Vector4 *tangent = new MT_Vector4[mesh->totvert]; - for (v = 0; v < mesh->totvert; v++) - { - const MT_Vector3 no(mesh->mvert[v].no[0]/32767.0, - mesh->mvert[v].no[1]/32767.0, - mesh->mvert[v].no[2]/32767.0); - // Gram-Schmidt orthogonalize - MT_Vector3 t(tan1[v] - no.cross(no.cross(tan1[v]))); - if (!MT_fuzzyZero(t)) - t /= t.length(); - - tangent[v].x() = t.x(); - tangent[v].y() = t.y(); - tangent[v].z() = t.z(); - // Calculate handedness - tangent[v].w() = no.dot(tan1[v].cross(tan2[v])) < 0.0 ? -1.0 : 1.0; - } - - delete [] tan1; - delete [] tan2; - - return tangent; -} - RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rendertools, KX_Scene* scene, KX_BlenderSceneConverter *converter) { RAS_MeshObject *meshobj; - bool skinMesh = false; - + bool skinMesh = false; int lightlayer = blenderobj->lay; - - MFace* mface = static_cast(mesh->mface); - MTFace* tface = static_cast(mesh->mtface); - const char *tfaceName = ""; - MCol* mmcol = mesh->mcol; - MT_assert(mface || mesh->totface == 0); + // Get DerivedMesh data + DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj); + + MVert *mvert = dm->getVertArray(dm); + int totvert = dm->getNumVerts(dm); + + MFace *mface = dm->getFaceArray(dm); + MTFace *tface = static_cast(dm->getFaceDataArray(dm, CD_MTFACE)); + MCol *mcol = static_cast(dm->getFaceDataArray(dm, CD_MCOL)); + float (*tangent)[3] = NULL; + int totface = dm->getNumFaces(dm); + const char *tfaceName = ""; + + if(tface) { + DM_add_tangent_layer(dm); + tangent = (float(*)[3])dm->getFaceDataArray(dm, CD_TANGENT); + } // Determine if we need to make a skinned mesh - if (mesh->dvert || mesh->key){ + if (mesh->dvert || mesh->key) { meshobj = new BL_SkinMeshObject(mesh, lightlayer); skinMesh = true; } - else { + else meshobj = new RAS_MeshObject(mesh, lightlayer); - } - MT_Vector4 *tangent = 0; - if (tface) - tangent = BL_ComputeMeshTangentSpace(mesh); - // Extract avaiable layers MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; - for (int lay=0; layfdata.totlayer; i++) + for (int i=0; ifaceData.totlayer; i++) { - if (mesh->fdata.layers[i].type == CD_MTFACE) + if (dm->faceData.layers[i].type == CD_MTFACE) { assert(validLayers <= 8); - layers[validLayers].face = (MTFace*)mesh->fdata.layers[i].data;; - layers[validLayers].name = mesh->fdata.layers[i].name; + layers[validLayers].face = (MTFace*)(dm->faceData.layers[i].data); + layers[validLayers].name = dm->faceData.layers[i].name; if(tface == layers[validLayers].face) tfaceName = layers[validLayers].name; validLayers++; @@ -844,271 +766,269 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } meshobj->SetName(mesh->id.name); - meshobj->m_xyz_index_to_vertex_index_mapping.resize(mesh->totvert); - for (int f=0;ftotface;f++,mface++) + meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert); + + for (int f=0;fv3) - { - MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0); - MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); - // rgb3 is set from the adjoint face in a square - unsigned int rgb0,rgb1,rgb2,rgb3 = 0; - MT_Vector3 no0(mesh->mvert[mface->v1].no[0], mesh->mvert[mface->v1].no[1], mesh->mvert[mface->v1].no[2]), - no1(mesh->mvert[mface->v2].no[0], mesh->mvert[mface->v2].no[1], mesh->mvert[mface->v2].no[2]), - no2(mesh->mvert[mface->v3].no[0], mesh->mvert[mface->v3].no[1], mesh->mvert[mface->v3].no[2]), - no3(0.0, 0.0, 0.0); - MT_Point3 pt0(mesh->mvert[mface->v1].co), - pt1(mesh->mvert[mface->v2].co), - pt2(mesh->mvert[mface->v3].co), - pt3(0.0, 0.0, 0.0); - MT_Vector4 tan0(0.0, 0.0, 0.0, 0.0), - tan1(0.0, 0.0, 0.0, 0.0), - tan2(0.0, 0.0, 0.0, 0.0), - tan3(0.0, 0.0, 0.0, 0.0); + MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0); + MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); + unsigned int rgb0,rgb1,rgb2,rgb3 = 0; + + MT_Vector3 no0, no1, no2, no3; + MT_Point3 pt0, pt1, pt2, pt3; + MT_Vector4 tan0, tan1, tan2, tan3; + + /* get coordinates, normals and tangents */ + pt0 = MT_Point3(mvert[mface->v1].co); + pt1 = MT_Point3(mvert[mface->v2].co); + pt2 = MT_Point3(mvert[mface->v3].co); + pt3 = (mface->v4)? MT_Point3(mvert[mface->v4].co): MT_Point3(0.0, 0.0, 0.0); + + if(mface->flag & ME_SMOOTH) { + float n0[3], n1[3], n2[3], n3[3]; + + NormalShortToFloat(n0, mvert[mface->v1].no); + NormalShortToFloat(n1, mvert[mface->v2].no); + NormalShortToFloat(n2, mvert[mface->v3].no); + no0 = n0; + no1 = n1; + no2 = n2; + + if(mface->v4) { + NormalShortToFloat(n3, mvert[mface->v4].no); + no3 = n3; + } + else + no3 = MT_Vector3(0.0, 0.0, 0.0); + } + else { + float fno[3]; + + if(mface->v4) + CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, mvert[mface->v4].co, fno); + else + CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, fno); + + no0 = no1 = no2 = no3 = MT_Vector3(fno); + } + + if(tangent) { + tan0 = tangent[f*4 + 0]; + tan1 = tangent[f*4 + 1]; + tan2 = tangent[f*4 + 2]; - no0 /= 32767.0; - no1 /= 32767.0; - no2 /= 32767.0; if (mface->v4) - { - pt3 = MT_Point3(mesh->mvert[mface->v4].co); - no3 = MT_Vector3(mesh->mvert[mface->v4].no[0], mesh->mvert[mface->v4].no[1], mesh->mvert[mface->v4].no[2]); - no3 /= 32767.0; - } + tan3 = tangent[f*4 + 3]; + } + + /* get material */ + ma = give_current_material(blenderobj, mface->mat_nr+1); - if(!(mface->flag & ME_SMOOTH)) - { - MT_Vector3 norm = ((pt1-pt0).cross(pt2-pt0)).safe_normalized(); - norm[0] = ((int) (10*norm[0]))/10.0; - norm[1] = ((int) (10*norm[1]))/10.0; - norm[2] = ((int) (10*norm[2]))/10.0; - no0=no1=no2=no3= norm; - - } - - { - Material* ma = 0; - bool polyvisible = true; - RAS_IPolyMaterial* polymat = NULL; - BL_Material *bl_mat = NULL; + { + bool polyvisible = true; + RAS_IPolyMaterial* polymat = NULL; + BL_Material *bl_mat = NULL; - if(converter->GetMaterials()) - { - if(mesh->totcol > 1) - ma = mesh->mat[mface->mat_nr]; - else - ma = give_current_material(blenderobj, 1); + if(converter->GetMaterials()) { + /* do Blender Multitexture and Blender GLSL materials */ + unsigned int rgb[4]; + MT_Point2 uv[4]; - bl_mat = ConvertMaterial(mesh, ma, tface, tfaceName, mface, mmcol, lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); - // set the index were dealing with - bl_mat->material_index = (int)mface->mat_nr; + /* first is the BL_Material */ + bl_mat = ConvertMaterial(ma, tface, tfaceName, mface, mcol, + lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); - polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); - collider = ((bl_mat->ras_mode & COLLIDER)!=0); - - polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); - - unsigned int rgb[4]; - bl_mat->GetConversionRGB(rgb); - rgb0 = rgb[0]; rgb1 = rgb[1]; - rgb2 = rgb[2]; rgb3 = rgb[3]; - MT_Point2 uv[4]; - bl_mat->GetConversionUV(uv); - uv0 = uv[0]; uv1 = uv[1]; - uv2 = uv[2]; uv3 = uv[3]; + bl_mat->material_index = (int)mface->mat_nr; - bl_mat->GetConversionUV2(uv); - uv20 = uv[0]; uv21 = uv[1]; - uv22 = uv[2]; uv23 = uv[3]; + polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); + collider = ((bl_mat->ras_mode & COLLIDER)!=0); - if(tangent){ - tan0 = tangent[mface->v1]; - tan1 = tangent[mface->v2]; - tan2 = tangent[mface->v3]; - if (mface->v4) - tan3 = tangent[mface->v4]; - } - } - else - { - ma = give_current_material(blenderobj, 1); + /* vertex colors and uv's were stored in bl_mat temporarily */ + bl_mat->GetConversionRGB(rgb); + rgb0 = rgb[0]; rgb1 = rgb[1]; + rgb2 = rgb[2]; rgb3 = rgb[3]; - Image* bima = ((mesh->mtface && tface) ? (Image*) tface->tpage : NULL); - - STR_String imastr = - ((mesh->mtface && tface) ? - (bima? (bima)->id.name : "" ) : "" ); - - char transp=0; - short mode=0, tile=0; - int tilexrep=4,tileyrep = 4; - - if (bima) - { - tilexrep = bima->xrep; - tileyrep = bima->yrep; + bl_mat->GetConversionUV(uv); + uv0 = uv[0]; uv1 = uv[1]; + uv2 = uv[2]; uv3 = uv[3]; + + bl_mat->GetConversionUV2(uv); + uv20 = uv[0]; uv21 = uv[1]; + uv22 = uv[2]; uv23 = uv[3]; - } - - if (mesh->mtface && tface) - { - // Use texface colors if available - //TF_DYNAMIC means the polygon is a collision face - collider = ((tface->mode & TF_DYNAMIC) != 0); - transp = tface->transp &~ TF_CLIP; - tile = tface->tile; - mode = tface->mode; - - polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); - - uv0 = MT_Point2(tface->uv[0]); - uv1 = MT_Point2(tface->uv[1]); - uv2 = MT_Point2(tface->uv[2]); + /* then the KX_BlenderMaterial */ + polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); + } + else { + /* do Texture Face materials */ + Image* bima = (tface)? (Image*)tface->tpage: NULL; + STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; - if (mface->v4) - uv3 = MT_Point2(tface->uv[3]); - } - else - { - // no texfaces, set COLLSION true and everything else FALSE - - mode = default_face_mode; - transp = TF_SOLID; - tile = 0; - } + char transp=0; + short mode=0, tile=0; + int tilexrep=4,tileyrep = 4; + + if (bima) { + tilexrep = bima->xrep; + tileyrep = bima->yrep; + } - if (mmcol) - { - // Use vertex colors - rgb0 = KX_Mcol2uint_new(mmcol[0]); - rgb1 = KX_Mcol2uint_new(mmcol[1]); - rgb2 = KX_Mcol2uint_new(mmcol[2]); - - if (mface->v4) - rgb3 = KX_Mcol2uint_new(mmcol[3]); - } - else { - // no vertex colors: take from material if we have one, - // otherwise set to white - unsigned int color = 0xFFFFFFFFL; - - if (ma) - { - union - { - unsigned char cp[4]; - unsigned int integer; - } col_converter; - - col_converter.cp[3] = (unsigned char) (ma->r*255.0); - col_converter.cp[2] = (unsigned char) (ma->g*255.0); - col_converter.cp[1] = (unsigned char) (ma->b*255.0); - col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); - - color = col_converter.integer; - } + /* get tface properties if available */ + if(tface) { + /* TF_DYNAMIC means the polygon is a collision face */ + collider = ((tface->mode & TF_DYNAMIC) != 0); + transp = tface->transp; + tile = tface->tile; + mode = tface->mode; + + polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); + + uv0 = MT_Point2(tface->uv[0]); + uv1 = MT_Point2(tface->uv[1]); + uv2 = MT_Point2(tface->uv[2]); - rgb0 = KX_rgbaint2uint_new(color); - rgb1 = KX_rgbaint2uint_new(color); - rgb2 = KX_rgbaint2uint_new(color); - - if (mface->v4) - rgb3 = KX_rgbaint2uint_new(color); - } + if (mface->v4) + uv3 = MT_Point2(tface->uv[3]); + } + else { + /* no texfaces, set COLLSION true and everything else FALSE */ + mode = default_face_mode; + transp = TF_SOLID; + tile = 0; + } + + /* get vertex colors */ + if (mcol) { + /* we have vertex colors */ + rgb0 = KX_Mcol2uint_new(mcol[0]); + rgb1 = KX_Mcol2uint_new(mcol[1]); + rgb2 = KX_Mcol2uint_new(mcol[2]); - bool istriangle = (mface->v4==0); - bool zsort = ma?(ma->mode & MA_ZTRA) != 0:false; - - polymat = new KX_PolygonMaterial(imastr, ma, - tile, tilexrep, tileyrep, - mode, transp, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mmcol); - + if (mface->v4) + rgb3 = KX_Mcol2uint_new(mcol[3]); + } + else { + /* no vertex colors, take from material, otherwise white */ + unsigned int color = 0xFFFFFFFFL; + if (ma) { - polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; - polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512 - polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); - - } else - { - polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); - polymat->m_shininess = 35.0; + union + { + unsigned char cp[4]; + unsigned int integer; + } col_converter; + + col_converter.cp[3] = (unsigned char) (ma->r*255.0); + col_converter.cp[2] = (unsigned char) (ma->g*255.0); + col_converter.cp[1] = (unsigned char) (ma->b*255.0); + col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); + + color = col_converter.integer; } - } - - // see if a bucket was reused or a new one was created - // this way only one KX_BlenderMaterial object has to exist per bucket - bool bucketCreated; - RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated); - if (bucketCreated) { - // this is needed to free up memory afterwards - converter->RegisterPolyMaterial(polymat); - if(converter->GetMaterials()) { - converter->RegisterBlenderMaterial(bl_mat); - } - } else { - // delete the material objects since they are no longer needed - // from now on, use the polygon material from the material bucket - delete polymat; - if(converter->GetMaterials()) { - delete bl_mat; - } - polymat = bucket->GetPolyMaterial(); - } - - int nverts = mface->v4?4:3; - int vtxarray = meshobj->FindVertexArray(nverts,polymat); - RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); - bool flat; - - if (skinMesh) { - /* If the face is set to solid, all fnors are the same */ - if (mface->flag & ME_SMOOTH) - flat = false; - else - flat = true; - } - else - flat = false; - - poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); - poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); - poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); - if (nverts==4) - poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); - - meshobj->AddPolygon(poly); - if (poly->IsCollider()) - { - RAS_TriangleIndex idx; - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v2; - idx.m_index[2] = mface->v3; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - if (nverts==4) - { - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v3; - idx.m_index[2] = mface->v4; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - } + rgb0 = KX_rgbaint2uint_new(color); + rgb1 = KX_rgbaint2uint_new(color); + rgb2 = KX_rgbaint2uint_new(color); + + if (mface->v4) + rgb3 = KX_rgbaint2uint_new(color); } -// poly->SetVisibleWireframeEdges(mface->edcode); - poly->SetCollider(collider); + bool istriangle = (mface->v4==0); + + // only zsort alpha + add + bool alpha = (transp == TF_ALPHA || transp == TF_ADD); + bool zsort = (mode & TF_ALPHASORT)? alpha: 0; + + polymat = new KX_PolygonMaterial(imastr, ma, + tile, tilexrep, tileyrep, + mode, transp, alpha, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mcol); + + if (ma) { + polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; + polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512 + polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); + } + else { + polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); + polymat->m_shininess = 35.0; + } } + + // see if a bucket was reused or a new one was created + // this way only one KX_BlenderMaterial object has to exist per bucket + bool bucketCreated; + RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated); + if (bucketCreated) { + // this is needed to free up memory afterwards + converter->RegisterPolyMaterial(polymat); + if(converter->GetMaterials()) { + converter->RegisterBlenderMaterial(bl_mat); + } + } else { + // delete the material objects since they are no longer needed + // from now on, use the polygon material from the material bucket + delete polymat; + if(converter->GetMaterials()) { + delete bl_mat; + } + polymat = bucket->GetPolyMaterial(); + } + + int nverts = mface->v4?4:3; + int vtxarray = meshobj->FindVertexArray(nverts,polymat); + RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); + + bool flat; + + if (skinMesh) { + /* If the face is set to solid, all fnors are the same */ + if (mface->flag & ME_SMOOTH) + flat = false; + else + flat = true; + } + else + flat = false; + + poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); + poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); + poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); + if (nverts==4) + poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); + + meshobj->AddPolygon(poly); + if (poly->IsCollider()) + { + RAS_TriangleIndex idx; + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v2; + idx.m_index[2] = mface->v3; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); + if (nverts==4) + { + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v3; + idx.m_index[2] = mface->v4; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); + } + } + +// poly->SetVisibleWireframeEdges(mface->edcode); + poly->SetCollider(collider); } + if (tface) tface++; - if (mmcol) - mmcol+=4; + if (mcol) + mcol+=4; for (int lay=0; layGetPolyMaterial()->OnConstruction(); } - if(tangent) - delete [] tangent; - if (layers) delete []layers; + + dm->release(dm); return meshobj; } @@ -1819,7 +1738,7 @@ KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist){ return 0; } -#include "BLI_arithb.h" + // convert blender objects into ketsji gameobjects void BL_ConvertBlenderObjects(struct Main* maggie, const STR_String& scenename, diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index dd45d522b9f..a9a0771936c 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -1,6 +1,10 @@ #include "DNA_customdata_types.h" #include "DNA_material_types.h" +#include "DNA_scene_types.h" + +#include "BKE_global.h" +#include "BKE_main.h" #include "BL_BlenderShader.h" #include "BL_Material.h" @@ -10,30 +14,51 @@ #include "GPU_material.h" #endif +#include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" + + /* this is evil, but we need the scene to create materials with + * lights from the correct scene .. */ +static struct Scene *GetSceneForName(const STR_String& scenename) +{ + Scene *sce; -const bool BL_BlenderShader::Ok()const + for (sce= (Scene*)G.main->scene.first; sce; sce= (Scene*)sce->id.next) + if (scenename == (sce->id.name+2)) + return sce; + + return (Scene*)G.main->scene.first; +} + +bool BL_BlenderShader::Ok() { #ifdef BLENDER_GLSL - return (mGPUMat != 0); + VerifyShader(); + + return (mMat && mMat->gpumaterial); #else return 0; #endif } -BL_BlenderShader::BL_BlenderShader(struct Material *ma, int lightlayer) +BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer) : #ifdef BLENDER_GLSL - mGPUMat(0), + mScene(scene), + mMat(ma), + mGPUMat(NULL), #endif mBound(false), mLightLayer(lightlayer) { #ifdef BLENDER_GLSL - if(ma) { - GPU_material_from_blender(ma); - mGPUMat = ma->gpumaterial; + mBlenderScene = GetSceneForName(scene->GetName()); + mBlendMode = GPU_BLEND_SOLID; + + if(mMat) { + GPU_material_from_blender(mBlenderScene, mMat); + mGPUMat = mMat->gpumaterial; } #endif } @@ -41,17 +66,29 @@ BL_BlenderShader::BL_BlenderShader(struct Material *ma, int lightlayer) BL_BlenderShader::~BL_BlenderShader() { #ifdef BLENDER_GLSL - if(mGPUMat) { - GPU_material_unbind(mGPUMat); - mGPUMat = 0; - } + if(mMat && mMat->gpumaterial) + GPU_material_unbind(mMat->gpumaterial); +#endif +} + +bool BL_BlenderShader::VerifyShader() +{ +#ifdef BLENDER_GLSL + if(mMat && !mMat->gpumaterial) + GPU_material_from_blender(mBlenderScene, mMat); + + mGPUMat = mMat->gpumaterial; + + return (mMat && mGPUMat); +#else + return false; #endif } void BL_BlenderShader::SetProg(bool enable) { #ifdef BLENDER_GLSL - if(mGPUMat) { + if(VerifyShader()) { if(enable) { GPU_material_bind(mGPUMat, mLightLayer); mBound = true; @@ -70,7 +107,7 @@ int BL_BlenderShader::GetAttribNum() GPUVertexAttribs attribs; int i, enabled = 0; - if(!mGPUMat) + if(!VerifyShader()) return enabled; GPU_material_vertex_attributes(mGPUMat, &attribs); @@ -96,7 +133,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) ras->SetAttribNum(0); - if(!mGPUMat) + if(!VerifyShader()) return; if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { @@ -142,9 +179,11 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) { #ifdef BLENDER_GLSL - float obmat[4][4], viewmat[4][4], viewinvmat[4][4]; + float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; - if(!mGPUMat || !mBound) + VerifyShader(); + + if(!mGPUMat) // || !mBound) return; MT_Matrix4x4 model; @@ -158,10 +197,22 @@ void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) view.invert(); view.getValue((float*)viewinvmat); - GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat); + if(ms.m_bObjectColor) + ms.m_RGBAcolor.getValue((float*)obcol); + else + obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f; + + GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat, obcol); + + mBlendMode = GPU_material_blend_mode(mGPUMat, obcol); #endif } +int BL_BlenderShader::GetBlendMode() +{ + return mBlendMode; +} + bool BL_BlenderShader::Equals(BL_BlenderShader *blshader) { #ifdef BLENDER_GLSL diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index b758d1a9cba..da9765dafa4 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -14,7 +14,10 @@ #include "RAS_IPolygonMaterial.h" +#include "KX_Scene.h" + struct Material; +struct Scene; class BL_Material; #define BL_MAX_ATTRIB 16 @@ -27,21 +30,28 @@ class BL_BlenderShader { private: #ifdef BLENDER_GLSL + KX_Scene *mScene; + struct Scene *mBlenderScene; + struct Material *mMat; GPUMaterial *mGPUMat; #endif bool mBound; int mLightLayer; + int mBlendMode; + + bool VerifyShader(); public: - BL_BlenderShader(struct Material *ma, int lightlayer); + BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer); virtual ~BL_BlenderShader(); - const bool Ok()const; + bool Ok(); void SetProg(bool enable); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); + int GetBlendMode(); bool Equals(BL_BlenderShader *blshader); }; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index 568f7e171de..dcb66ea2579 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -129,8 +129,7 @@ enum BL_flag TEXALPHA=8, // use alpha combiner functions TEXNEG=16, // negate blending HASIPO=32, - USENEGALPHA=64, - ALPHA_TEST=128 + USENEGALPHA=64 }; // BL_Material::ras_mode @@ -139,7 +138,7 @@ enum BL_ras_mode POLY_VIS=1, COLLIDER=2, ZSORT=4, - TRANSP=8, + ALPHA=8, TRIANGLE=16, USE_LIGHT=32, WIRE=64 diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index f24ef4322f0..f0ef84032f7 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -384,8 +384,6 @@ void BL_Texture::DisableUnit() void BL_Texture::DisableAllTextures() { - glDisable(GL_BLEND); - for(int i=0; itilexrep[0], data->tileyrep[0], data->mode, - ((data->ras_mode &TRANSP)!=0), + data->transp, + ((data->ras_mode &ALPHA)!=0), ((data->ras_mode &ZSORT)!=0), lightlayer, ((data->ras_mode &TRIANGLE)!=0), @@ -79,7 +81,6 @@ KX_BlenderMaterial::KX_BlenderMaterial( m_flag |=RAS_BLENDERMAT; m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0; m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0; - m_flag |=(mMaterial->ras_mode &ALPHA_TEST)!=0?RAS_FORCEALPHA:0; // figure max int enabled = mMaterial->num_enabled; @@ -158,12 +159,29 @@ void KX_BlenderMaterial::OnConstruction() mConstructed = true; } +void KX_BlenderMaterial::EndFrame() +{ + if(mLastBlenderShader) { + mLastBlenderShader->SetProg(false); + mLastBlenderShader = NULL; + } + + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader = NULL; + } +} + void KX_BlenderMaterial::OnExit() { if( mShader ) { - //note, the shader here is allocated, per unique material - //and this function is called per face - mShader->SetProg(false); + //note, the shader here is allocated, per unique material + //and this function is called per face + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } + delete mShader; mShader = 0; } @@ -197,13 +215,19 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) int i; if( !enable || !mShader->Ok() ) { // frame cleanup. - mShader->SetProg(false); + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } + + ras->SetBlendingMode(TF_SOLID); BL_Texture::DisableAllTextures(); return; } BL_Texture::DisableAllTextures(); mShader->SetProg(true); + mLastShader = mShader; BL_Texture::ActivateFirst(); @@ -217,9 +241,12 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) } if(!mUserDefBlend) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } else { + ras->SetBlendingMode(TF_SOLID); + ras->SetBlendingMode(-1); // indicates custom mode + // tested to be valid enums glEnable(GL_BLEND); glBlendFunc(mBlendFunc[0], mBlendFunc[1]); @@ -234,11 +261,14 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; } + + ras->SetBlendingMode(TF_SOLID); BL_Texture::DisableAllTextures(); return; } if(!mBlenderShader->Equals(mLastBlenderShader)) { + ras->SetBlendingMode(mMaterial->transp); BL_Texture::DisableAllTextures(); if(mLastBlenderShader) @@ -251,17 +281,17 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) { - if(GLEW_ARB_shader_objects && mShader) - mShader->SetProg(false); - BL_Texture::DisableAllTextures(); - if( !enable ) + + if( !enable ) { + ras->SetBlendingMode(TF_SOLID); return; + } BL_Texture::ActivateFirst(); if( mMaterial->IdMode == DEFAULT_BLENDER ) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); return; } @@ -271,7 +301,7 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) mTextures[0].ActivateTexture(); mTextures[0].setTexEnv(0, true); mTextures[0].SetMapping(mMaterial->mapping[0].mapping); - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } return; } @@ -294,9 +324,12 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) } if(!mUserDefBlend) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } else { + ras->SetBlendingMode(TF_SOLID); + ras->SetBlendingMode(-1); // indicates custom mode + glEnable(GL_BLEND); glBlendFunc(mBlendFunc[0], mBlendFunc[1]); } @@ -356,6 +389,11 @@ KX_BlenderMaterial::ActivateBlenderShaders( { KX_BlenderMaterial *tmp = const_cast(this); + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader= NULL; + } + // reset... if(tmp->mMaterial->IsShared()) cachingInfo =0; @@ -402,6 +440,11 @@ KX_BlenderMaterial::ActivateMat( { KX_BlenderMaterial *tmp = const_cast(this); + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader= NULL; + } + if(mLastBlenderShader) { mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; @@ -451,7 +494,10 @@ KX_BlenderMaterial::Activate( return dopass; } else { - mShader->SetProg(false); + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } mPass = 0; dopass = false; return dopass; @@ -499,10 +545,22 @@ bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const { - if(mShader && GLEW_ARB_shader_objects) + if(mShader && GLEW_ARB_shader_objects) { mShader->Update(ms, rasty); - else if(mBlenderShader && GLEW_ARB_shader_objects) + } + else if(mBlenderShader && GLEW_ARB_shader_objects) { + int blendmode; + mBlenderShader->Update(ms, rasty); + + /* we do blend modes here, because they can change per object + * with the same material due to obcolor */ + blendmode = mBlenderShader->GetBlendMode(); + if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID) + blendmode = mMaterial->transp; + + rasty->SetBlendingMode(blendmode); + } } void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const @@ -582,31 +640,6 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const ras->EnableTextures(false); } -bool KX_BlenderMaterial::setDefaultBlending() -{ - if( mMaterial->transp &TF_ADD) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - glDisable ( GL_ALPHA_TEST ); - return true; - } - - if( mMaterial->transp & TF_ALPHA ) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable ( GL_ALPHA_TEST ); - return true; - } - - if( mMaterial->transp & TF_CLIP ) { - glDisable(GL_BLEND); - glEnable ( GL_ALPHA_TEST ); - glAlphaFunc(GL_GREATER, 0.5f); - return false; - } - return false; -} - void KX_BlenderMaterial::setTexMatrixData(int i) { glMatrixMode(GL_TEXTURE); @@ -831,12 +864,14 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") void KX_BlenderMaterial::SetBlenderGLSLShader(void) { if(!mBlenderShader) - mBlenderShader = new BL_BlenderShader(mMaterial->material, m_lightlayer); + mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, m_lightlayer); if(!mBlenderShader->Ok()) { delete mBlenderShader; mBlenderShader = 0; } + else + m_flag |= RAS_BLENDERGLSL; } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index bf6d2095e7c..0d7657b8cdb 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -90,11 +90,13 @@ public: // -------------------------------- // pre calculate to avoid pops/lag at startup virtual void OnConstruction( ); + + static void EndFrame(); + private: BL_Material* mMaterial; BL_Shader* mShader; BL_BlenderShader* mBlenderShader; - static BL_BlenderShader *mLastBlenderShader; KX_Scene* mScene; BL_Texture mTextures[MAXTEX]; // texture array bool mUserDefBlend; @@ -114,7 +116,6 @@ private: void setBlenderShaderData( bool enable, RAS_IRasterizer *ras); void setShaderData( bool enable, RAS_IRasterizer *ras); - bool setDefaultBlending(); void setObjectMatrixData(int i, RAS_IRasterizer *ras); void setTexMatrixData(int i); @@ -123,6 +124,10 @@ private: // cleanup stuff void OnExit(); + // shader chacing + static BL_BlenderShader *mLastBlenderShader; + static BL_Shader *mLastShader; + mutable int mPass; }; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 3d9c7aafd70..df478be5ca2 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -77,10 +77,10 @@ KX_GameObject::KX_GameObject( SCA_IObject(T), m_bDyna(false), m_layer(0), + m_pBlenderObject(NULL), m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), - m_pBlenderObject(NULL), m_bVisible(true), m_pPhysicsController1(NULL), m_pPhysicsEnvironment(NULL), @@ -96,12 +96,9 @@ KX_GameObject::KX_GameObject( KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New(); m_pSGNode->SetParentRelation(parent_relation); - - }; - KX_GameObject::~KX_GameObject() { // is this delete somewhere ? @@ -165,6 +162,7 @@ STR_String KX_GameObject::GetName() void KX_GameObject::SetName(STR_String name) { m_name = name; + }; // Set the name of the value @@ -454,12 +452,13 @@ KX_GameObject::UpdateMaterialData( ) { int mesh = 0; + if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial(); for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit) { RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial(); - if(poly->GetFlag() & RAS_BLENDERMAT ) + if(poly->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *m = static_cast(poly); @@ -467,7 +466,8 @@ KX_GameObject::UpdateMaterialData( { m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) - SetObjectColor(rgba); + if(!(poly->GetFlag() & RAS_BLENDERGLSL)) + SetObjectColor(rgba); } else { diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index db099d56b55..1d6cc975ab5 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -118,7 +118,6 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_bInitialized(false), m_activecam(0), m_bFixedTime(false), - m_game2ipo(false), m_firstframe(true), @@ -148,6 +147,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_showBackground(false), m_show_debug_properties(false), + m_game2ipo(false), + // Default behavior is to hide the cursor every frame. m_hideCursor(false), diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 93d6d5bb70d..144f74a1a4c 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -59,7 +59,8 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -74,7 +75,8 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, tilexrep, tileyrep, mode, - transparant, + transp, + alpha, zsort, lightlayer, bIsTriangle, @@ -245,7 +247,7 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) if (attr == "drawingmode") return PyInt_FromLong(m_drawingmode); if (attr == "transparent") - return PyInt_FromLong(m_transparant); + return PyInt_FromLong(m_alpha); if (attr == "zsort") return PyInt_FromLong(m_zsort); if (attr == "lightlayer") @@ -312,7 +314,7 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) if (attr == "transparent") { - m_transparant = value; + m_alpha = value; return 0; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 19015494e06..11c8baa8b1f 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -64,7 +64,8 @@ public: int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 648a6ca31d5..ad476e492d0 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -37,6 +37,7 @@ #include "MT_assert.h" #include "KX_KetsjiEngine.h" +#include "KX_BlenderMaterial.h" #include "RAS_IPolygonMaterial.h" #include "ListValue.h" #include "SCA_LogicManager.h" @@ -116,13 +117,13 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, PyObjectPlus(&KX_Scene::Type), m_keyboardmgr(NULL), m_mousemgr(NULL), + m_sceneConverter(NULL), m_physicsEnvironment(0), m_sceneName(sceneName), m_adi(adi), m_networkDeviceInterface(ndi), m_active_camera(NULL), - m_ueberExecutionPriority(0), - m_sceneConverter(NULL) + m_ueberExecutionPriority(0) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -984,6 +985,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) //m_active_camera->Release(); m_active_camera = NULL; } + // in case this is a camera m_cameras.remove((KX_Camera*)newobj); @@ -1240,14 +1242,10 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi if (visible) { int nummeshes = gameobj->GetMeshCount(); - MT_Transform t( cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); - + // this adds the vertices to the display list for (int m=0;mGetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode()); - } + (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } gameobj->MarkVisible(visible); } @@ -1304,12 +1302,11 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam if (vis) { int nummeshes = gameobj->GetMeshCount(); - MT_Transform t(cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); for (int m=0;mGetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode()); + (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } // Visibility/ non-visibility are marked // elsewhere now. @@ -1422,7 +1419,7 @@ void KX_Scene::UpdateParents(double curtime) RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool &bucketCreated) { - return m_bucketmanager->RAS_BucketManagerFindBucket(polymat, bucketCreated); + return m_bucketmanager->FindBucket(polymat, bucketCreated); } @@ -1432,10 +1429,9 @@ void KX_Scene::RenderBuckets(const MT_Transform & cameratransform, class RAS_IRenderTools* rendertools) { m_bucketmanager->Renderbuckets(cameratransform,rasty,rendertools); + KX_BlenderMaterial::EndFrame(); } - - void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index b4492ca03a9..82bdce44519 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -94,7 +94,6 @@ void RAS_BucketManager::RenderAlphaBuckets( const MT_Scalar cam_origin = cameratrans.getOrigin()[2]; for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { - (*bit)->ClearScheduledPolygons(); for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { if ((*mit).m_bVisible) @@ -133,28 +132,15 @@ void RAS_BucketManager::Renderbuckets( rasty->ClearCachingInfo(); RAS_MaterialBucket::StartFrame(); - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - { - (*bucket)->ClearScheduledPolygons(); - } for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - { - RAS_IPolyMaterial *tmp = (*bucket)->GetPolyMaterial(); - if(tmp->IsZSort() || tmp->GetFlag() &RAS_FORCEALPHA ) - rasty->SetAlphaTest(true); - else - rasty->SetAlphaTest(false); - (*bucket)->Render(cameratrans,rasty,rendertools); - } - rasty->SetAlphaTest(false); RenderAlphaBuckets(cameratrans, rasty, rendertools); RAS_MaterialBucket::EndFrame(); } -RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) +RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) { bucketCreated = false; BucketList::iterator it; @@ -172,7 +158,7 @@ RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMate RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); bucketCreated = true; - if (bucket->IsTransparant()) + if (bucket->IsAlpha()) m_AlphaBuckets.push_back(bucket); else m_MaterialBuckets.push_back(bucket); @@ -195,3 +181,28 @@ void RAS_BucketManager::RAS_BucketManagerClearAll() m_MaterialBuckets.clear(); m_AlphaBuckets.clear(); } + +void RAS_BucketManager::ReleaseDisplayLists() +{ + BucketList::iterator bit; + RAS_MaterialBucket::T_MeshSlotList::iterator mit; + + for (bit = m_MaterialBuckets.begin(); bit != m_MaterialBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } + } + } + + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } + } + } +} + diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 010478b1d5b..08b67ed022f 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -58,8 +58,9 @@ public: RAS_IRasterizer* rasty, class RAS_IRenderTools* rendertools); - RAS_MaterialBucket* RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + void ReleaseDisplayLists(); private: void RAS_BucketManagerClearAll(); diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 31bdd8638c2..4ee06d96603 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -39,7 +39,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -51,7 +52,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_tilexrep(tilexrep), m_tileyrep(tileyrep), m_drawingmode (mode), - m_transparant(transparant), + m_transp(transp), + m_alpha(alpha), m_zsort(zsort), m_lightlayer(lightlayer), m_bIsTriangle(bIsTriangle), @@ -74,6 +76,7 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_multimode == lhs.m_multimode && this->m_flag == lhs.m_flag && this->m_drawingmode == lhs.m_drawingmode && + this->m_transp == lhs.m_transp && this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() @@ -85,7 +88,8 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_tile == lhs.m_tile && this->m_tilexrep == lhs.m_tilexrep && this->m_tileyrep == lhs.m_tileyrep && - this->m_transparant == lhs.m_transparant && + this->m_transp == lhs.m_transp && + this->m_alpha == lhs.m_alpha && this->m_zsort == lhs.m_zsort && this->m_drawingmode == lhs.m_drawingmode && this->m_bIsTriangle == lhs.m_bIsTriangle && @@ -109,9 +113,9 @@ int RAS_IPolyMaterial::GetLightLayer() const return m_lightlayer; } -bool RAS_IPolyMaterial::IsTransparant() const +bool RAS_IPolyMaterial::IsAlpha() const { - return m_transparant; + return m_alpha || m_zsort; } bool RAS_IPolyMaterial::IsZSort() const diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 6d90d260a23..8fc53e6b038 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -52,7 +52,7 @@ enum MaterialProps RAS_AUTOGEN =128, RAS_NORMAL =256, RAS_DEFMULTI =512, - RAS_FORCEALPHA =1024 + RAS_BLENDERGLSL =1024 }; /** @@ -67,7 +67,8 @@ protected: int m_tile; int m_tilexrep,m_tileyrep; int m_drawingmode; // tface->mode - bool m_transparant; + int m_transp; + bool m_alpha; bool m_zsort; int m_lightlayer; bool m_bIsTriangle; @@ -102,7 +103,8 @@ public: int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -132,7 +134,7 @@ public: virtual bool Equals(const RAS_IPolyMaterial& lhs) const; bool Less(const RAS_IPolyMaterial& rhs) const; int GetLightLayer() const; - bool IsTransparant() const; + bool IsAlpha() const; bool IsZSort() const; bool UsesTriangles() const; unsigned int hash() const; diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index d4a9177a85d..9e03212283e 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -372,10 +372,6 @@ public: virtual void SetAmbientColor(float red, float green, float blue)=0; virtual void SetAmbient(float factor)=0; - /** - * Sets alpha testing - */ - virtual void SetAlphaTest(bool enable)=0; /** * Sets a polygon offset. z depth will be: z1 = mult*z0 + add @@ -398,8 +394,10 @@ public: virtual void DisableMotionBlur()=0; virtual float GetMotionBlurValue()=0; - virtual int GetMotionBlurState()=0; - virtual void SetMotionBlurState(int newstate)=0; + virtual int GetMotionBlurState()=0; + virtual void SetMotionBlurState(int newstate)=0; + + virtual void SetBlendingMode(int blendmode)=0; }; #endif //__RAS_IRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index e295d69e48e..0015b6a251f 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -76,26 +76,11 @@ KX_MeshSlot::~KX_MeshSlot() RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat) :m_bModified(true) { - m_bScheduled=true; m_material = mat; } -void RAS_MaterialBucket::SchedulePolygons(int drawingmode) -{ - m_bScheduled = true; -} - - - -void RAS_MaterialBucket::ClearScheduledPolygons() -{ - m_bScheduled = false; -} - - - RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const { return m_material; @@ -134,9 +119,14 @@ void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms, (*it).m_RGBAcolor= rgbavec; } -bool RAS_MaterialBucket::IsTransparant() const +bool RAS_MaterialBucket::IsAlpha() const { - return (m_material->IsTransparant()); + return (m_material->IsAlpha()); +} + +bool RAS_MaterialBucket::IsZSort() const +{ + return (m_material->IsZSort()); } diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 13d8a53714a..4eef889c533 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -125,11 +125,9 @@ public: class RAS_IRasterizer* rasty, class RAS_IRenderTools* rendertools); - void SchedulePolygons(int drawingmode); - void ClearScheduledPolygons(); - RAS_IPolyMaterial* GetPolyMaterial() const; - bool IsTransparant() const; + bool IsAlpha() const; + bool IsZSort() const; static void StartFrame(); static void EndFrame(); @@ -162,7 +160,6 @@ public: private: T_MeshSlotList m_meshSlots; - bool m_bScheduled; bool m_bModified; RAS_IPolyMaterial* m_material; double* m_pOGLMatrix; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 5087f62500e..9c0460aad2d 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -203,7 +203,6 @@ void RAS_MeshObject::DebugColor(unsigned int abgr) void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) { - RAS_TexVert* vertex = NULL; const vecVertexArray & vertexvec = GetVertexCache(mat); for (vector::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it) @@ -220,20 +219,15 @@ void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, int numverts, RAS_IPolyMaterial* mat) { - //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; - //m_IndexArrayCount[idx.m_vtxarray] = indexpos + 3; - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]); ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]); ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]); - if (!mat->UsesTriangles()) //if (!m_bUseTriangles) - { - //m_IndexArrayCount[idx.m_vtxarray] = indexpos+4; - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]); - } -} + if (!mat->UsesTriangles()) + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]); +} void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx, @@ -422,7 +416,6 @@ void RAS_MeshObject::Bucketize(double* oglmatrix, for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { RAS_MaterialBucket* bucket = *it; - bucket->SchedulePolygons(0); // KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); bucket->SetMeshSlot(ms); } @@ -447,7 +440,6 @@ void RAS_MeshObject::MarkVisible(double* oglmatrix, for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { RAS_MaterialBucket* bucket = *it; - bucket->SchedulePolygons(0); // KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec); } @@ -466,7 +458,6 @@ void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix, { RAS_MaterialBucket* bucket = *it; // RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial(); - bucket->SchedulePolygons(0); //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat); bucket->RemoveMeshSlot(ms); } @@ -585,31 +576,36 @@ void RAS_MeshObject::UpdateMaterialList() struct RAS_MeshObject::polygonSlot { - float m_z; - RAS_Polygon *m_poly; - - polygonSlot(float z, RAS_Polygon* poly) : - m_z(z), - m_poly(poly) - {} - /** - * pnorm and pval form the plane equation that the distance from is used to - * sort against. - */ - polygonSlot(const MT_Vector3 &pnorm, const MT_Scalar &pval, RAS_MeshObject *mesh, RAS_Polygon* poly) : - m_poly(poly) + float m_z; + int m_index[4]; + + polygonSlot() {} + + /* pnorm is the normal from the plane equation that the distance from is + * used to sort again. */ + void get(const KX_VertexArray& vertexarray, const KX_IndexArray& indexarray, + int offset, int nvert, const MT_Vector3& pnorm) { - const KX_VertexIndex &base = m_poly->GetIndexBase(); - RAS_TexVert *vert = mesh->GetVertex(base.m_vtxarray, base.m_indexarray[0], poly->GetMaterial()->GetPolyMaterial()); - m_z = MT_dot(pnorm, vert->getLocalXYZ()) + pval; - - for(int i = 1; i < m_poly->VertexCount(); i++) - { - vert = mesh->GetVertex(base.m_vtxarray, base.m_indexarray[i], poly->GetMaterial()->GetPolyMaterial()); - float z = MT_dot(pnorm, vert->getLocalXYZ()) + pval; - m_z += z; + MT_Vector3 center(0, 0, 0); + int i; + + for(i=0; iVertexCount(); + + /* note we don't divide center by the number of vertices, since all + * polygons have the same number of vertices, and that we leave out + * the 4-th component of the plane equation since it is constant. */ + m_z = MT_dot(pnorm, center); + } + + void set(KX_IndexArray& indexarray, int offset, int nvert) + { + int i; + + for(i=0; i alphapolyset; - std::multiset solidpolyset; - - for (unsigned int p = 0; p < numpolys; p++) - { - RAS_Polygon* poly = m_Polygons[p]; - if (poly->IsVisible()) - { - if (poly->GetMaterial()->GetPolyMaterial()->IsTransparant()) - { - alphapolyset.insert(polygonSlot(pnorm, pval, this, poly)); - } else { - solidpolyset.insert(polygonSlot(pnorm, pval, this, poly)); - } - } - } - - // Clear current array data. + // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { - vector *indexcache = &GetArrayOptimizer((*it)->GetPolyMaterial())->m_IndexArrayCache1; - for (vector::iterator iit = indexcache->begin(); iit != indexcache->end(); ++iit) - (*iit)->clear(); - } + if(!(*it)->IsZSort()) + continue; - std::multiset::iterator sit = solidpolyset.begin(); - for (; sit != solidpolyset.end(); ++sit) - SchedulePoly((*sit).m_poly->GetVertexIndexBase(), (*sit).m_poly->VertexCount(), (*sit).m_poly->GetMaterial()->GetPolyMaterial()); - - std::multiset::iterator ait = alphapolyset.begin(); - for (; ait != alphapolyset.end(); ++ait) - SchedulePoly((*ait).m_poly->GetVertexIndexBase(), (*ait).m_poly->VertexCount(), (*ait).m_poly->GetMaterial()->GetPolyMaterial()); + RAS_IPolyMaterial *mat = (*it)->GetPolyMaterial(); + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + vecIndexArrays& indexarrays = ao->m_IndexArrayCache1; + vecVertexArray& vertexarrays = ao->m_VertexArrayCache1; + unsigned int i, j, nvert = (mat->UsesTriangles())? 3: 4; + + for(i=0; i slots(totpoly); + + /* get indices and z into temporary array */ + for(j=0; jSchedulePolygons(drawingmode); - if (bucket->GetPolyMaterial()->IsZSort()) + if ((*it)->IsZSort()) m_zsort = true; - } - - int numpolys = m_Polygons.size(); - if ((drawingmode > RAS_IRasterizer::KX_BOUNDINGBOX) && - (drawingmode < RAS_IRasterizer::KX_SOLID)) + if (drawingmode == RAS_IRasterizer::KX_WIREFRAME) { for (i=0;iIsVisible()) - ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode() - ,poly->GetMaterial()->GetPolyMaterial()); + ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode(), + poly->GetMaterial()->GetPolyMaterial()); } m_zsort = false; } else { - if (!m_zsort) + for (i=0;iIsVisible()) - { - SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetMaterial()->GetPolyMaterial()); - } - } + RAS_Polygon* poly = m_Polygons[i]; + if (poly->IsVisible()) + SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(), + poly->GetMaterial()->GetPolyMaterial()); } } m_bModified = false; - m_MeshMod = true; } } + diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 44ad508d1e8..99806666fa6 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -137,6 +137,18 @@ class RAS_MeshObject struct backtofront; struct fronttoback; + void SchedulePoly( + const KX_VertexIndex& idx, + int numverts, + RAS_IPolyMaterial* mat + ); + + void ScheduleWireframePoly( + const KX_VertexIndex& idx, + int numverts, + int edgecode, + RAS_IPolyMaterial* mat + ); protected: enum { BUCKET_MAX_INDICES = 65535 };//2048};//8192}; @@ -196,10 +208,7 @@ public: */ void SortPolygons(const MT_Transform &transform); - void SchedulePolygons( - const MT_Transform &transform, - int drawingmode - ); + void SchedulePolygons(int drawingmode); void ClearArrayData(); @@ -216,19 +225,7 @@ public: int numverts, RAS_IPolyMaterial* polymat ); - - void SchedulePoly( - const KX_VertexIndex& idx, - int numverts, - RAS_IPolyMaterial* mat - ); - void ScheduleWireframePoly( - const KX_VertexIndex& idx, - int numverts, - int edgecode, - RAS_IPolyMaterial* mat - ); // find (and share) or add vertices // for some speedup, only the last 20 added vertices are searched for equality diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index dcc36bf5a39..1dcc6e70934 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -67,6 +67,7 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_motionblurvalue(-1.0), m_texco_num(0), m_attrib_num(0), + m_last_blendmode(0), m_materialCachingInfo(0) { m_viewmatrix.Identity(); @@ -171,6 +172,8 @@ bool RAS_OpenGLRasterizer::Init() m_ambg = 0.0f; m_ambb = 0.0f; + SetBlendingMode(0); + glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -189,18 +192,6 @@ void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) } -void RAS_OpenGLRasterizer::SetAlphaTest(bool enable) -{ - if (enable) - { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.6f); - } - else glDisable(GL_ALPHA_TEST); -} - - - void RAS_OpenGLRasterizer::SetAmbient(float factor) { float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; @@ -353,6 +344,8 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glEnable (GL_CULL_FACE); } + SetBlendingMode(0); + glShadeModel(GL_SMOOTH); m_2DCanvas->BeginFrame(); @@ -1389,3 +1382,34 @@ void RAS_OpenGLRasterizer::DisableMotionBlur() m_motionblur = 0; m_motionblurvalue = -1.0; } + +void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) +{ + if(blendmode == m_last_blendmode) + return; + + if(blendmode == 0) { + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else if(blendmode == 1) { + glBlendFunc(GL_ONE, GL_ONE); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + } + else if(blendmode == 2) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.0f); + } + else if(blendmode == 4) { + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.5f); + } + + m_last_blendmode = blendmode; +} + diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 0d54552db05..02056cce446 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -99,6 +99,7 @@ protected: TexCoGen m_attrib[RAS_MAX_ATTRIB]; int m_texco_num; int m_attrib_num; + int m_last_blendmode; /** Stores the caching information for the last material activated. */ RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo; @@ -142,8 +143,6 @@ public: virtual void SetFocalLength(const float focallength); virtual float GetFocalLength(); - virtual void SetAlphaTest(bool enable); - virtual void SwapBuffers(); virtual void IndexPrimitives( const vecVertexArray& vertexarrays, @@ -282,8 +281,8 @@ public: virtual void EnableMotionBlur(float motionblurvalue); virtual void DisableMotionBlur(); virtual float GetMotionBlurValue(){return m_motionblurvalue;}; - virtual int GetMotionBlurState(){return m_motionblur;}; - virtual void SetMotionBlurState(int newstate) + virtual int GetMotionBlurState(){return m_motionblur;}; + virtual void SetMotionBlurState(int newstate) { if(newstate<0) m_motionblur = 0; @@ -292,6 +291,8 @@ public: else m_motionblur = newstate; }; + + virtual void SetBlendingMode(int blendmode); }; #endif //__RAS_OPENGLRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp index 852c94def3f..b74cb9cfcac 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.cpp +++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp @@ -37,24 +37,6 @@ #include "RAS_Polygon.h" -/* -RAS_TexVert* RAS_Polygon::GetVertex(int index) -{ - if (m_bucket) - return m_bucket->GetVertex(m_vertexindexbase.m_vtxarray, m_vertexindexbase.m_indexarray[index]); - else - return NULL; -} -*/ - -/*void RAS_Polygon::Bucketize(double* oglmatrix) -{ - //Transform(trans); - if (m_bucket) - m_bucket->AddPolygon(this,oglmatrix); -} -*/ - RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, bool visible, int numverts, From 039814f7d22b05225b66da7135639712e865ef9a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 29 Jul 2008 18:07:06 +0000 Subject: [PATCH 10/58] No long needed here (win64 cleanup) --- source/blender/blenkernel/intern/collision.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 6dfb77504fb..5b3cec25772 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1547,7 +1547,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f { Cloth *cloth=NULL; BVHTree *cloth_bvh=NULL; - long i=0, numfaces = 0, numverts = 0; + int i=0, numfaces = 0, numverts = 0; int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; From ca951b3627b48beab9ddf14ac18040e2f24d959b Mon Sep 17 00:00:00 2001 From: Mal Duffin Date: Tue, 29 Jul 2008 20:28:11 +0000 Subject: [PATCH 11/58] Am teaching a GE course this week, and am finding some small issues that I'm hoping to patch. This one deals with the very small default clipend value ( 100.0 ) when pressing P to run the GE from a non-camera view. ( ie if the user zooms out a bit from the default box area, the box will get clipped out of view, so it's a WFT from the user ) To see what this fixes, load up Blender default scene, go into perspective, and press P. Everything looks grand. Now, zoom out until the box is about 10 pixels high, and press P again. The box will disappear / be clipped out. I've set the clip end to the maximum ( 5000 ) as defined in Camera.h. This should be suitable for inclusion in 2.47 branch also. --- source/gameengine/Rasterizer/RAS_CameraData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h index 0327a3f4763..e3af43fb839 100644 --- a/source/gameengine/Rasterizer/RAS_CameraData.h +++ b/source/gameengine/Rasterizer/RAS_CameraData.h @@ -42,7 +42,7 @@ struct RAS_CameraData int m_viewporttop; float m_focallength; - RAS_CameraData(float lens = 35., float clipstart = 0.1, float clipend = 100., bool perspective = true, + RAS_CameraData(float lens = 35.0, float clipstart = 0.1, float clipend = 5000.0, bool perspective = true, float focallength = 0.0f, bool viewport = false, int viewportleft = 0, int viewportbottom = 0, int viewportright = 0, int viewporttop = 0) : m_lens(lens), From 7f3c27995ed9a3adf04974f26b7b1a33f58adc5d Mon Sep 17 00:00:00 2001 From: Mal Duffin Date: Tue, 29 Jul 2008 21:49:59 +0000 Subject: [PATCH 12/58] Copy Attributes now has option to copy all physical attributes. There existed two options to copy only the mass, and only the damping, but no option to copy all of the physical attributes. This patch adds in this option, right under the Mass and Damping listings. --- source/blender/src/editobject.c | 13 ++++++++++++- source/blender/src/header_view3d.c | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 2f9addb106e..cbf7691754d 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3506,6 +3506,17 @@ void copy_attr(short event) base->object->damping= ob->damping; base->object->rdamping= ob->rdamping; } + else if(event==11) { /* all physical attributes */ + base->object->gameflag = ob->gameflag; + base->object->inertia = ob->inertia; + base->object->formfactor = ob->formfactor; + base->object->damping= ob->damping; + base->object->rdamping= ob->rdamping; + base->object->mass= ob->mass; + if (ob->gameflag & OB_BOUNDS) { + base->object->boundtype = ob->boundtype; + } + } else if(event==17) { /* tex space */ copy_texture_space(base->object, ob); } @@ -3692,7 +3703,7 @@ void copy_attr_menu() * view3d_edit_object_copyattrmenu() and in toolbox.c */ - strcpy(str, "Copy Attributes %t|Location%x1|Rotation%x2|Size%x3|Draw Options%x4|Time Offset%x5|Dupli%x6|%l|Mass%x7|Damping%x8|Properties%x9|Logic Bricks%x10|Protected Transform%x29|%l"); + strcpy(str, "Copy Attributes %t|Location%x1|Rotation%x2|Size%x3|Draw Options%x4|Time Offset%x5|Dupli%x6|%l|Mass%x7|Damping%x8|All Physical Attributes%x11|Properties%x9|Logic Bricks%x10|Protected Transform%x29|%l"); strcat (str, "|Object Constraints%x22"); strcat (str, "|NLA Strips%x26"); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 71bf0cd9bd4..0b48db461e6 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -2196,6 +2196,7 @@ static uiBlock *view3d_edit_object_copyattrmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mass|Ctrl C, 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Damping|Ctrl C, 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "All Physical Attributes|Ctrl C, 11", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Properties|Ctrl C, 9", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Logic Bricks|Ctrl C, 10", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Protected Transform |Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 29, ""); From e04c48df86babc18ed49ef8d33a3cfefcb28ed32 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 29 Jul 2008 21:56:50 +0000 Subject: [PATCH 13/58] * making sure BGE compiles after brecht's big commit (r15867). Needed to compile with msvc. --- source/gameengine/Rasterizer/RAS_MeshObject.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 9c0460aad2d..adef998acc2 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -35,6 +35,8 @@ #include "MT_MinMax.h" #include "MT_Point3.h" +#include + STR_String RAS_MeshObject::s_emptyname = ""; From 34bb44673469dc50e980dec86b5892789449b378 Mon Sep 17 00:00:00 2001 From: Mal Duffin Date: Tue, 29 Jul 2008 22:44:43 +0000 Subject: [PATCH 14/58] Simple changes to Motion Actuator UI. This includes... - Renaming dLoc and dRot as Loc and Rot ( as well as changing the tooltip to location and rotation ). dLoc and dRot are programming terms, not user terms. - Placing Loc and Rot as the two initial shown values, so that the physical ones are all shown together. I also changed it so that only Loc and Rot are shown in the UI, unless the object is Dynamic ( as the other values only make sense if it is dynamic ). These are just a few simple changes, that should make a lot of difference to users when learning how to use the GE. -------------------------------------- Things I'd *really* like to do to this, when I get a chance to code Blender again ( hopefully in a few days time, after I have finished teaching on the GE course )... Color / Colour tint the X,Y and Z entry boxes as slightly red, green and blue, to reflect the colour of the axis / transform gizmo ...or... Just show X,Y and Z labels above all of the values. Getting to grips with the whole XYZ thing is very confusing for users, esp when they are presented with 6 x 3 entry boxes. --- source/blender/src/buttons_logic.c | 93 +++++++++++++++++------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 498edc0dfed..5cf1958678e 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1654,53 +1654,66 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh wval = (width-100)/3; if (oa->type == ACT_OBJECT_NORMAL) { - ysize= 175; - + if ( ob->gameflag & OB_DYNAMIC ) + { + ysize= 175; + } + else + { + ysize= 72; + } + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefBut(block, LABEL, 0, "Force", xco, yco-45, 55, 19, NULL, 0, 0, 0, 0, "Sets the force"); - uiDefButF(block, NUM, 0, "", xco+45, yco-45, wval, 19, oa->forceloc, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-45, wval, 19, oa->forceloc+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-45, wval, 19, oa->forceloc+2, -10000.0, 10000.0, 10, 0, ""); + uiDefBut(block, LABEL, 0, "Loc", xco, yco-45, 45, 19, NULL, 0, 0, 0, 0, "Sets the location"); + uiDefButF(block, NUM, 0, "", xco+45, yco-45, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-45, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-45, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, ""); - uiDefBut(block, LABEL, 0, "Torque", xco, yco-64, 55, 19, NULL, 0, 0, 0, 0, "Sets the torque"); - uiDefButF(block, NUM, 0, "", xco+45, yco-64, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-64, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-64, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, ""); - - uiDefBut(block, LABEL, 0, "dLoc", xco, yco-87, 45, 19, NULL, 0, 0, 0, 0, "Sets the dLoc"); - uiDefButF(block, NUM, 0, "", xco+45, yco-87, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-87, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-87, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, ""); - - uiDefBut(block, LABEL, 0, "dRot", xco, yco-106, 45, 19, NULL, 0, 0, 0, 0, "Sets the dRot"); - uiDefButF(block, NUM, 0, "", xco+45, yco-106, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-106, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-106, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, ""); - - uiDefBut(block, LABEL, 0, "linV", xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Sets the linear velocity"); - uiDefButF(block, NUM, 0, "", xco+45, yco-129, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-129, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-129, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, ""); - - uiDefBut(block, LABEL, 0, "angV", xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity"); - uiDefButF(block, NUM, 0, "", xco+45, yco-148, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-148, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-148, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, ""); - - uiDefBut(block, LABEL, 0, "damp", xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity"); - uiDefButS(block, NUM, 0, "", xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, ""); + uiDefBut(block, LABEL, 0, "Rot", xco, yco-64, 45, 19, NULL, 0, 0, 0, 0, "Sets the rotation"); + uiDefButF(block, NUM, 0, "", xco+45, yco-64, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-64, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-64, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, ""); - uiDefButBitS(block, TOG, ACT_FORCE_LOCAL, 0, "L", xco+45+3*wval, yco-45, 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-64, 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-87, 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-106, 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-129, 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-148, 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-45, 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-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); + + if ( ob->gameflag & OB_DYNAMIC ) + { + uiDefBut(block, LABEL, 0, "Force", xco, yco-87, 55, 19, NULL, 0, 0, 0, 0, "Sets the force"); + uiDefButF(block, NUM, 0, "", xco+45, yco-87, wval, 19, oa->forceloc, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-87, wval, 19, oa->forceloc+1, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-87, wval, 19, oa->forceloc+2, -10000.0, 10000.0, 10, 0, ""); - uiDefButBitS(block, TOG, ACT_ADD_LIN_VEL, 0, "add",xco+45+3*wval+15, yco-129, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV"); + uiDefBut(block, LABEL, 0, "Torque", xco, yco-106, 55, 19, NULL, 0, 0, 0, 0, "Sets the torque"); + uiDefButF(block, NUM, 0, "", xco+45, yco-106, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-106, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-6106, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, ""); + } + if ( ob->gameflag & OB_DYNAMIC ) + { + uiDefBut(block, LABEL, 0, "LinV", xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Sets the linear velocity"); + uiDefButF(block, NUM, 0, "", xco+45, yco-129, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-129, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-129, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, ""); + + uiDefBut(block, LABEL, 0, "AngV", xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity"); + uiDefButF(block, NUM, 0, "", xco+45, yco-148, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-148, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-148, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, ""); + + uiDefBut(block, LABEL, 0, "Damp", xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity"); + uiDefButS(block, NUM, 0, "", xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, ""); + + uiDefButBitS(block, TOG, ACT_FORCE_LOCAL, 0, "L", xco+45+3*wval, yco-87, 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-106, 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-129, 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-148, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); + + uiDefButBitS(block, TOG, ACT_ADD_LIN_VEL, 0, "add",xco+45+3*wval+15, yco-129, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV"); + } } else if (oa->type == ACT_OBJECT_SERVO) { ysize= 172; From 7b819bc6316ac32c60dd6a0e404bc9e2a781feba Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 30 Jul 2008 09:07:56 +0000 Subject: [PATCH 15/58] == Grease Pencil - Eraser (First Draft) == This commit introduces the ability to erase strokes. Admittedly, the code for this is not totally stable yet, and doesn't always produce optimum results. I'm committing now for backup purposes. It currently uses the lasso code to check whether segments of the strokes (a segment occurs between two recorded points) occur inside a region defined by the 'eraser' stroke, or any intersections it makes with the 'eraser' stroke. There are multiple ways to erase strokes: * With 'Draw Mode' on, use RMB-drag to erase * With a tablet, use the 'eraser' end of the stylus * Hold the Alt Key, and use the 'selection' mouse-button (i.e. LMB if mouse-button swapping is on, RMB otherwise) to erase. For this one, this is necessary to avoid overriding the view-rotation hotkey combo for 2-button mice! Todo: * 3d-strokes are not correctly mapped back to screen-space for sampling yet * Drawing of eraser strokes is still not distinctive enough * After running a few times, may cause stack corruption/segfaults, so be careful! == Bugfixes == * Grease-Pencil Onion-Skinning works again. Onionskining was being supplied the wrong frames, and the alpha factor was still the old one used for 0-255 ranged colour values --- source/blender/include/BDR_gpencil.h | 9 + source/blender/include/BIF_editview.h | 1 + source/blender/makesdna/DNA_gpencil_types.h | 2 +- source/blender/src/drawgpencil.c | 92 ++++- source/blender/src/editview.c | 2 +- source/blender/src/gpencil.c | 358 +++++++++++++++----- 6 files changed, 369 insertions(+), 95 deletions(-) diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h index d2fc7be29ea..eb749cf28ec 100644 --- a/source/blender/include/BDR_gpencil.h +++ b/source/blender/include/BDR_gpencil.h @@ -38,6 +38,15 @@ struct bGPdata; struct bGPDlayer; struct bGPDframe; +/* ------------- Grease-Pencil Helpers -------------- */ + +/* Temporary 'Stroke Point' data */ +typedef struct tGPspoint { + short x, y; /* x and y coordinates of cursor (in relative to area) */ + float xf, yf; /* same as x and y, but as floats */ + float pressure; /* pressure of tablet at this point */ +} tGPspoint; + /* ------------ Grease-Pencil API ------------------ */ void free_gpencil_strokes(struct bGPDframe *gpf); diff --git a/source/blender/include/BIF_editview.h b/source/blender/include/BIF_editview.h index 4ed3d0df367..4c407d43672 100644 --- a/source/blender/include/BIF_editview.h +++ b/source/blender/include/BIF_editview.h @@ -37,6 +37,7 @@ struct View3D; void arrows_move_cursor(unsigned short event); int lasso_inside(short mcords[][2], short moves, short sx, short sy); +int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1); void borderselect(void); void circle_select(void); void deselectall(void); diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index b88dd698c3f..dca4e28688d 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -125,7 +125,7 @@ typedef struct bGPdata { */ short sbuffer_size; /* number of elements currently in cache */ short sbuffer_sflag; /* flags for stroke that cache represents */ - bGPDspoint *sbuffer; /* stroke buffer (can hold GP_STROKE_BUFFER_MAX) */ + void *sbuffer; /* stroke buffer (can hold GP_STROKE_BUFFER_MAX) */ } bGPdata; /* bGPdata->flag */ diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index e07dec90629..733310bfda7 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -280,11 +280,15 @@ short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa) /* show override lmb-clicks button + painting lock */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret LMB-click as new strokes (same as holding Shift-Key per stroke)"); - - uiBlockSetCol(block, TH_BUT_SETTING); - uiDefIconButBitI(block, ICONTOG, GP_DATA_LMBPLOCK, B_REDR, ICON_UNLOCKED, 300, 225, 20, 20, &gpd->flag, 0.0, 0.0, 0, 0, "Painting cannot occur with Shift-LMB (when making selections)"); - uiBlockSetCol(block, TH_AUTO); + if ((gpd->flag & GP_DATA_EDITPAINT)==0) { + uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes"); + + uiBlockSetCol(block, TH_BUT_SETTING); + uiDefIconButBitI(block, ICONTOG, GP_DATA_LMBPLOCK, B_REDR, ICON_UNLOCKED, 300, 225, 20, 20, &gpd->flag, 0.0, 0.0, 0, 0, "Painting cannot occur with Shift-LMB (when making selections)"); + uiBlockSetCol(block, TH_AUTO); + } + else + uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes"); uiBlockEndAlign(block); /* 'view align' button (naming depends on context) */ @@ -313,6 +317,66 @@ enum { GP_DRAWDATA_ONLYV2D = (1<<2), /* only draw 'canvas' strokes */ }; +/* draw stroke in buffer */ +static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thickness, short dflag, short sflag) +{ + tGPspoint *pt; + int i; + + /* error checking */ + if ((points == NULL) || (totpoints <= 0)) + return; + + /* check if buffer can be drawn */ + if (dflag & (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_ONLYV2D)) + return; + + /* if drawing a single point, draw it larger */ + if (totpoints == 1) { + /* draw point */ + glBegin(GL_POINTS); + glVertex2f(points->x, points->y); + glEnd(); + } + else if (sflag & GP_STROKE_ERASER) { + /* draw stroke curve - just standard thickness */ + setlinestyle(4); + glLineWidth(1.0f); + + glBegin(GL_LINE_STRIP); + for (i=0, pt=points; i < totpoints && pt; i++, pt++) { + glVertex2f(pt->x, pt->y); + } + glEnd(); + + setlinestyle(0); + } + else { + float oldpressure = 0.0f; + + /* draw stroke curve */ + setlinestyle(2); + + glBegin(GL_LINE_STRIP); + for (i=0, pt=points; i < totpoints && pt; i++, pt++) { + if (fabs(pt->pressure - oldpressure) > 0.2f) { + glEnd(); + glLineWidth(pt->pressure * thickness); + glBegin(GL_LINE_STRIP); + + glVertex2f(pt->x, pt->y); + + oldpressure = pt->pressure; + } + else + glVertex2f(pt->x, pt->y); + } + glEnd(); + + setlinestyle(0); + } +} + /* draw a given stroke */ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy) { @@ -489,8 +553,8 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* check if frame is drawable */ if ((gpf->framenum - gf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ - tcolor[3] = color[3] - (i * 0.7); - gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); + tcolor[3] = color[3] - (i/gpl->gstep); + gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -501,8 +565,8 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* check if frame is drawable */ if ((gf->framenum - gpf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ - tcolor[3] = color[3] - (i * 0.7); - gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); + tcolor[3] = color[3] - (i/gpl->gstep); + gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -515,12 +579,12 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* draw the strokes for the ghost frames (at half of the alpha set by user) */ if (gpf->prev) { tcolor[3] = (color[3] / 7); - gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf->prev, winx, winy, dflag, debug, lthick, tcolor); } if (gpf->next) { tcolor[3] = (color[3] / 4); - gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf->next, winx, winy, dflag, debug, lthick, tcolor); } /* restore alpha */ @@ -533,15 +597,13 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); /* Check if may need to draw the active stroke cache, only if this layer is the active layer - * that is being edited. (Stroke cache is currently stored in gp-data) + * that is being edited. (Stroke buffer is currently stored in gp-data) */ if ((G.f & G_GREASEPENCIL) && (gpl->flag & GP_LAYER_ACTIVE) && (gpf->flag & GP_FRAME_PAINT)) { /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */ - setlinestyle(2); - gp_draw_stroke(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, debug, winx, winy); - setlinestyle(0); + gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag); } } diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index e3ec69975de..f58248be161 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -298,7 +298,7 @@ int lasso_inside(short mcords[][2], short moves, short sx, short sy) } /* edge version for lasso select. we assume boundbox check was done */ -static int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1) +int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1) { short v1[2], v2[2]; int a; diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index 24ed6a7b0ba..fe01106919f 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -57,6 +57,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_butspace.h" +#include "BIF_editview.h" #include "BIF_graphics.h" #include "BIF_interface.h" #include "BIF_mywindow.h" @@ -683,7 +684,7 @@ typedef struct tGPsdata { bGPDframe *gpf; /* frame we're working on */ short status; /* current status of painting */ - short paintmode; /* mode for painting (L_MOUSE or R_MOUSE for now) */ + short paintmode; /* mode for painting */ } tGPsdata; /* values for tGPsdata->status */ @@ -693,6 +694,12 @@ enum { GP_STATUS_DONE /* painting done */ }; +/* values for tGPsdata->paintmode */ +enum { + GP_PAINTMODE_DRAW = 0, + GP_PAINTMODE_ERASER +}; + /* Return flags for adding points to stroke buffer */ enum { GP_STROKEADD_INVALID = -2, /* error occurred - insufficient info to do so */ @@ -710,9 +717,9 @@ static void gp_session_validatebuffer (tGPsdata *p) /* clear memory of buffer (or allocate it if starting a new session) */ if (gpd->sbuffer) - memset(gpd->sbuffer, 0, sizeof(bGPDspoint)*GP_STROKE_BUFFER_MAX); + memset(gpd->sbuffer, 0, sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX); else - gpd->sbuffer= MEM_callocN(sizeof(bGPDspoint)*GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer"); + gpd->sbuffer= MEM_callocN(sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer"); /* reset indices */ gpd->sbuffer_size = 0; @@ -850,6 +857,25 @@ static void gp_session_cleanup (tGPsdata *p) gpd->sbuffer_sflag= 0; } +/* check if the current mouse position is suitable for adding a new point */ +static short gp_stroke_filtermval (tGPsdata *p, short mval[2], short pmval[2]) +{ + short dx= abs(mval[0] - pmval[0]); + short dy= abs(mval[1] - pmval[1]); + + /* check if mouse moved at least certain distance on both axes (best case) */ + if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) + return 1; + + /* check if the distance since the last point is significant enough */ + else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX) + return 1; + + /* mouse 'didn't move' */ + else + return 0; +} + /* convert screen-coordinates to buffer-coordinates */ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) { @@ -884,30 +910,11 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) } } -/* check if the current mouse position is suitable for adding a new point */ -static short gp_stroke_filtermval (tGPsdata *p, short mval[2], short pmval[2]) -{ - short dx= abs(mval[0] - pmval[0]); - short dy= abs(mval[1] - pmval[1]); - - /* check if mouse moved at least certain distance on both axes (best case) */ - if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) - return 1; - - /* check if the distance since the last point is significant enough */ - else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX) - return 1; - - /* mouse 'didn't move' */ - else - return 0; -} - /* add current stroke-point to buffer (returns whether point was successfully added) */ static short gp_stroke_addpoint (tGPsdata *p, short mval[2], float pressure) { bGPdata *gpd= p->gpd; - bGPDspoint *pt; + tGPspoint *pt; /* check if still room in buffer */ if (gpd->sbuffer_size >= GP_STROKE_BUFFER_MAX) @@ -915,12 +922,13 @@ static short gp_stroke_addpoint (tGPsdata *p, short mval[2], float pressure) /* get pointer to destination point */ - pt= gpd->sbuffer + gpd->sbuffer_size; + pt= ((tGPspoint *)(gpd->sbuffer) + gpd->sbuffer_size); - /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, mval, &pt->x); - - /* store other settings */ + /* store settings */ + pt->x= mval[0]; + pt->y= mval[1]; + pt->xf= (float)mval[0]; + pt->yf= (float)mval[0]; pt->pressure= pressure; /* increment counters */ @@ -933,38 +941,13 @@ static short gp_stroke_addpoint (tGPsdata *p, short mval[2], float pressure) return GP_STROKEADD_NORMAL; } -/* smooth a stroke (in buffer) before storing it */ -static void gp_stroke_smooth (tGPsdata *p) -{ - bGPdata *gpd= p->gpd; - int i=0, cmx=gpd->sbuffer_size; - - // fixme: currently disabled as it damages too much sometimes - return; - - /* don't try if less than 2 points in buffer */ - if ((cmx <= 2) || (gpd->sbuffer == NULL)) - return; - - /* apply weighting-average (note doing this along path sequentially does introduce slight error) */ - for (i=0; i < gpd->sbuffer_size; i++) { - bGPDspoint *pc= (gpd->sbuffer + i); - bGPDspoint *pb= (i-1 > 0)?(pc-1):(pc); - bGPDspoint *pa= (i-2 > 0)?(pc-2):(pb); - bGPDspoint *pd= (i+1 < cmx)?(pc+1):(pc); - bGPDspoint *pe= (i+2 < cmx)?(pc+2):(pd); - - pc->x= (0.1*pa->x + 0.2*pb->x + 0.4*pc->x + 0.2*pd->x + 0.1*pe->x); - pc->y= (0.1*pa->y + 0.2*pb->y + 0.4*pc->y + 0.2*pd->y + 0.1*pe->y); - } -} - /* make a new stroke from the buffer data */ static void gp_stroke_newfrombuffer (tGPsdata *p) { bGPdata *gpd= p->gpd; bGPDstroke *gps; - bGPDspoint *pt, *ptc; + bGPDspoint *pt; + tGPspoint *ptc; int i, totelem; /* get total number of points to allocate space for */ @@ -990,7 +973,12 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) /* copy points from the buffer to the stroke */ for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { - memcpy(pt, ptc, sizeof(bGPDspoint)); + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x); + + /* copy pressure */ + pt->pressure= ptc->pressure; + pt++; } @@ -998,10 +986,202 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) BLI_addtail(&p->gpf->strokes, gps); } +/* --- 'Eraser' for 'Paint' Tool ------ */ +/* User should draw 'circles' around the parts of the sketches they wish to + * delete instead of drawing squiggles over existing lines. This should be + * easier to manage than if it was done otherwise. + */ + +/* convert gp-buffer stroke into mouse-coordinates array */ +static short (*gp_stroke_eraser_2mco (bGPdata *gpd))[2] +{ + tGPspoint *pt; + short (*mcoords)[2]; + int i; + + /* allocate memory for coordinates array */ + mcoords= MEM_mallocN(sizeof(*mcoords)*gpd->sbuffer_size,"gp_buf_mcords"); + + /* copy coordinates */ + for (pt=gpd->sbuffer, i=0; i < gpd->sbuffer_size; i++, pt++) { + mcoords[i][0]= pt->x; + mcoords[i][1]= pt->y; + } + + /* return */ + return mcoords; +} + +/* eraser tool evaluation per curve */ +static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short moves, bGPDframe *gpf, bGPDstroke *gps) +{ + bGPDspoint *pt1, *pt2; + short x0=0, y0=0, x1=0, y1=0; + short xyval[2]; + int i; + + if (gps->totpoints == 0) { + /* just free stroke */ + if (gps->points) + MEM_freeN(gps->points); + BLI_freelinkN(&gpf->strokes, gps); + } + else if (gps->totpoints == 1) { + /* get coordinates */ + if (gps->flag & GP_STROKE_3DSPACE) { + // FIXME: this may not be the correct correction + project_short(&gps->points->x, xyval); + x0= xyval[0]; + x1= xyval[1]; + } + else if (gps->flag & GP_STROKE_2DSPACE) { + ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval); + x0= xyval[0]; + y0= xyval[1]; + } + else { + x0= (gps->points->x / 1000 * p->sa->winx); + y0= (gps->points->y / 1000 * p->sa->winy); + } + + /* only check if point is inside */ + if (lasso_inside(mcoords, moves, x0, y0)) { + /* free stroke */ + MEM_freeN(gps->points); + BLI_freelinkN(&gpf->strokes, gps); + } + } + else { + /* loop over the points in the stroke, checking for intersections + * - an intersection will require the stroke to be split + */ + for (i=0; (i+1) < gps->totpoints; i++) { + /* get points to work with */ + pt1= gps->points + i; + pt2= gps->points + i + 1; + + /* get coordinates */ + if (gps->flag & GP_STROKE_3DSPACE) { + // FIXME: may not be correct correction + project_short(&gps->points->x, xyval); + x0= xyval[0]; + x1= xyval[1]; + } + else if (gps->flag & GP_STROKE_2DSPACE) { + ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval); + x0= xyval[0]; + y0= xyval[1]; + + ipoco_to_areaco_noclip(p->v2d, &pt2->x, xyval); + x1= xyval[0]; + y1= xyval[1]; + } + else { + x0= (pt1->x / 1000 * p->sa->winx); + y0= (pt1->y / 1000 * p->sa->winy); + x1= (pt2->x / 1000 * p->sa->winx); + y1= (pt2->y / 1000 * p->sa->winy); + } + + /* check if point segment of stroke had anything to do with + * eraser region (either within stroke painted, or on its lines) + * - this assumes that linewidth is irrelevant + * - handled using the lasso-select checking code + */ + if (lasso_inside_edge(mcoords, moves, x0, y0, x1, x1)) { + bGPDspoint *pt_tmp= gps->points; + bGPDstroke *gsn = NULL; + + /* if stroke only had two points, get rid of stroke */ + if (gps->totpoints == 2) { + /* free stroke points, then stroke */ + MEM_freeN(pt_tmp); + BLI_freelinkN(&gpf->strokes, gps); + + /* nothing left in stroke, so stop */ + break; + } + + /* if last segment, just remove segment from the stroke */ + else if (i == gps->totpoints - 2) { + /* allocate new points array, and assign most of the old stroke there */ + gps->totpoints--; + gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); + memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*gps->totpoints); + + /* free temp buffer */ + MEM_freeN(pt_tmp); + + /* nothing left in stroke, so stop */ + break; + } + + /* if first segment, just remove segment from the stroke */ + else if (i == 0) { + /* allocate new points array, and assign most of the old stroke there */ + gps->totpoints--; + gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); + memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint)*gps->totpoints); + + /* free temp buffer */ + MEM_freeN(pt_tmp); + + /* no break here, as there might still be stuff to remove in this stroke */ + } + + /* segment occurs in 'middle' of stroke, so split */ + else { + /* duplicate stroke, and assign 'later' data to that stroke */ + gsn= MEM_dupallocN(gps); + gsn->prev= gsn->next= NULL; + BLI_insertlinkafter(&gpf->strokes, gps, gsn); + + gsn->totpoints= gps->totpoints - i; + gsn->points= MEM_callocN(sizeof(bGPDspoint)*gsn->totpoints, "gp_stroke_points"); + memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint)*gsn->totpoints); + + /* adjust existing stroke */ + gps->totpoints= i; + gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); + memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*i); + + /* free temp buffer */ + MEM_freeN(pt_tmp); + + /* nothing left in stroke, so stop */ + break; + } + } + } + } +} + +/* -------- */ + +/* erase strokes which fall under the eraser strokes */ +static void gp_stroke_doeraser (tGPsdata *p) +{ + bGPdata *gpd= p->gpd; + bGPDframe *gpf= p->gpf; + bGPDstroke *gps; + short (*mcoords)[2]; + + /* get buffer-stroke coordinates as shorts array */ + mcoords= gp_stroke_eraser_2mco(gpd); + + /* loop over strokes, checking segments for intersections */ + for (gps= gpf->strokes.first; gps; gps= gps->next) { + gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, gpf, gps); + } + + /* free mcoords array */ + MEM_freeN(mcoords); +} + /* ---------- 'Paint' Tool ------------ */ /* init new stroke */ -static void gp_paint_initstroke (tGPsdata *p, short mousebutton) +static void gp_paint_initstroke (tGPsdata *p, short paintmode) { /* get active layer (or add a new one if non-existent) */ p->gpl= gpencil_layer_getactive(p->gpd); @@ -1025,14 +1205,10 @@ static void gp_paint_initstroke (tGPsdata *p, short mousebutton) else p->gpf->flag |= GP_FRAME_PAINT; - /* set 'eraser' for this stroke if using eraser or right-mouse in action */ - if ( get_activedevice() == 2 || (mousebutton & R_MOUSE) ) { + /* set 'eraser' for this stroke if using eraser */ + p->paintmode= paintmode; + if (p->paintmode == GP_PAINTMODE_ERASER) p->gpd->sbuffer_sflag |= GP_STROKE_ERASER; - - // for now: eraser isn't ready for prime-time yet, so no painting available here yet - p->status= GP_STATUS_ERROR; - return; - } /* check if points will need to be made in view-aligned space */ if (p->gpd->flag & GP_DATA_VIEWALIGN) { @@ -1062,12 +1238,10 @@ static void gp_paint_initstroke (tGPsdata *p, short mousebutton) /* finish off a stroke (clears buffer, but doesn't finish the paint operation) */ static void gp_paint_strokeend (tGPsdata *p) { - /* sanitize stroke-points in buffer (remove jitter) */ - gp_stroke_smooth(p); - /* check if doing eraser or not */ if (p->gpd->sbuffer_sflag & GP_STROKE_ERASER) { /* get rid of relevant sections of strokes */ + gp_stroke_doeraser(p); } else { /* transfer stroke to frame */ @@ -1100,7 +1274,7 @@ static void gp_paint_cleanup (tGPsdata *p) /* -------- */ /* main call to paint a new stroke */ -short gpencil_paint (short mousebutton) +short gpencil_paint (short mousebutton, short paintmode) { tGPsdata p; short prevmval[2], mval[2]; @@ -1113,7 +1287,7 @@ short gpencil_paint (short mousebutton) gp_session_cleanup(&p); return 0; } - gp_paint_initstroke(&p, mousebutton); + gp_paint_initstroke(&p, paintmode); if (p.status == GP_STATUS_ERROR) { gp_session_cleanup(&p); return 0; @@ -1188,7 +1362,10 @@ short gpencil_paint (short mousebutton) setcursor_space(p.sa->spacetype, CURSOR_STD); /* check size of buffer before cleanup, to determine if anything happened here */ - ok= p.gpd->sbuffer_size; + if (paintmode == GP_PAINTMODE_ERASER) + ok= (p.gpd->sbuffer_size > 1); + else + ok= p.gpd->sbuffer_size; /* cleanup */ gp_paint_cleanup(&p); @@ -1202,7 +1379,7 @@ short gpencil_paint (short mousebutton) /* All event (loops) handling checking if stroke drawing should be initiated * should call this function. */ -short gpencil_do_paint (ScrArea *sa, short mousebutton) +short gpencil_do_paint (ScrArea *sa, short mbut) { bGPdata *gpd = gpencil_data_getactive(sa); short retval= 0; @@ -1211,18 +1388,43 @@ short gpencil_do_paint (ScrArea *sa, short mousebutton) if (gpd == NULL) return 0; - /* currently, we will only paint if: + /* currently, we will only 'paint' if: * 1. draw-mode on gpd is set (for accessibility reasons) * (single 'dots' are only available via this method) * 2. if shift-modifier is held + lmb -> 'quick paint' + * + * OR + * + * draw eraser stroke if: + * 1. using the eraser on a tablet + * 2. draw-mode on gpd is set (for accessiblity reasons) + * (eraser is mapped to right-mouse) + * 3. Alt + 'select' mouse-button + * i.e. if LMB = select: Alt-LMB + * if RMB = select: Alt-RMB */ - if (gpd->flag & GP_DATA_EDITPAINT) { - /* try to paint */ - retval = gpencil_paint(mousebutton); + if (get_activedevice() == 2) { + /* eraser on a tablet - always try to erase strokes */ + retval = gpencil_paint(mbut, GP_PAINTMODE_ERASER); } - else if (!(gpd->flag & GP_DATA_LMBPLOCK) && (G.qual == LR_SHIFTKEY)) { - /* try to paint */ - retval = gpencil_paint(mousebutton); + else if (gpd->flag & GP_DATA_EDITPAINT) { + /* try to paint/erase */ + if (mbut == L_MOUSE) + retval = gpencil_paint(mbut, GP_PAINTMODE_DRAW); + else if (mbut == R_MOUSE) + retval = gpencil_paint(mbut, GP_PAINTMODE_ERASER); + } + else if (!(gpd->flag & GP_DATA_LMBPLOCK)) { + /* try to paint/erase as not locked */ + if ((G.qual == LR_SHIFTKEY) && (mbut == L_MOUSE)) { + retval = gpencil_paint(mbut, GP_PAINTMODE_DRAW); + } + else if (G.qual == LR_ALTKEY) { + if ((U.flag & USER_LMOUSESELECT) && (mbut == L_MOUSE)) + retval = gpencil_paint(mbut, GP_PAINTMODE_ERASER); + else if (!(U.flag & USER_LMOUSESELECT) && (mbut == R_MOUSE)) + retval = gpencil_paint(mbut, GP_PAINTMODE_ERASER); + } } /* return result of trying to paint */ From f3a4f3adaf4de26c45e0b5264e2e52b089ce7891 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 30 Jul 2008 09:20:05 +0000 Subject: [PATCH 16/58] Grease Pencil Bugfixes: * Segfaults with eraser should now be fixed * Attempted fixed for sequencer redraw problems with buttons --- source/blender/src/gpencil.c | 5 +++-- source/blender/src/space.c | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index fe01106919f..f4274b853cc 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -1163,14 +1163,15 @@ static void gp_stroke_doeraser (tGPsdata *p) { bGPdata *gpd= p->gpd; bGPDframe *gpf= p->gpf; - bGPDstroke *gps; + bGPDstroke *gps, *gpn; short (*mcoords)[2]; /* get buffer-stroke coordinates as shorts array */ mcoords= gp_stroke_eraser_2mco(gpd); /* loop over strokes, checking segments for intersections */ - for (gps= gpf->strokes.first; gps; gps= gps->next) { + for (gps= gpf->strokes.first; gps; gps= gpn) { + gpn= gps->next; gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, gpf, gps); } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index c30f6ca9f54..b4702788e0c 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -5119,7 +5119,10 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } - if(doredraw) scrarea_queue_winredraw(curarea); + if(doredraw) { + scrarea_queue_winredraw(curarea); + scrarea_queue_headredraw(curarea); + } } From 2d3a57eaa3ce9237ca5334a8fbcd23b1b060739e Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 30 Jul 2008 11:21:10 +0000 Subject: [PATCH 17/58] Bugfix for mesh deformer under windows --> uninitialized variable was used in meshdeform_inside_cage() --- source/blender/src/meshlaplacian.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c index 4d84672185a..60f569ecf0e 100644 --- a/source/blender/src/meshlaplacian.c +++ b/source/blender/src/meshlaplacian.c @@ -1281,9 +1281,9 @@ static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co) outside[1] = co[1] + (mdb->max[1] - mdb->min[1] + 1.0f)*MESHDEFORM_OFFSET[i][1]; outside[2] = co[2] + (mdb->max[2] - mdb->min[2] + 1.0f)*MESHDEFORM_OFFSET[i][2]; + VECCOPY(start, co); VECSUB(dir, outside, start); Normalize(dir); - VECCOPY(start, co); isect = meshdeform_ray_tree_intersect(mdb, start, outside); if(isect && !isect->facing) From 7f170c18bbc3ef3cc8e3b459b8bcc8a789ba0438 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 30 Jul 2008 16:15:15 +0000 Subject: [PATCH 18/58] Bugfixes: fix for two memory leaks related to dupligroups, and a missing reference count in the trackto actuator. This showed up as leaked pose data, but actually the whole object was not being freed. --- .../Converter/BL_ActionActuator.cpp | 24 +++++-------------- .../Converter/BL_ArmatureObject.cpp | 9 ++++--- .../Converter/BL_BlenderDataConversion.cpp | 5 ++-- source/gameengine/Ketsji/KX_Scene.cpp | 9 ++++++- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 10 ++++++++ 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 5d6dd694765..2ee8b54a014 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -57,24 +57,12 @@ BL_ActionActuator::~BL_ActionActuator() { - - if (m_pose) { - free_pose_channels(m_pose); - MEM_freeN(m_pose); - m_pose = NULL; - }; - - if (m_userpose){ - free_pose_channels(m_userpose); - MEM_freeN(m_userpose); - m_userpose=NULL; - } - if (m_blendpose) { - free_pose_channels(m_blendpose); - MEM_freeN(m_blendpose); - m_blendpose = NULL; - }; - + if (m_pose) + free_pose(m_pose); + if (m_userpose) + free_pose(m_userpose); + if (m_blendpose) + free_pose(m_blendpose); } void BL_ActionActuator::ProcessReplica(){ diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index f73d5b42a01..09f1d9d4d87 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -82,10 +82,8 @@ void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica) BL_ArmatureObject::~BL_ArmatureObject() { - if (m_mrdPose){ - free_pose_channels(m_mrdPose); - MEM_freeN(m_mrdPose); - } + if (m_mrdPose) + free_pose(m_mrdPose); } /* note, you can only call this for exisiting Armature objects, and not mix it with other Armatures */ @@ -172,12 +170,13 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose) // copy_pose (&m_mrdPose, m_pose, 0); //} - if (!*pose) + if (!*pose) { // must duplicate the constraints too otherwise we have corruption in free_pose_channels() // because it will free the blender constraints. // Ideally, blender should rememeber that the constraints were not copied so that // free_pose_channels() would not free them. copy_pose(pose, m_objArma->pose, 1); + } else extract_pose_from_pose(*pose, m_objArma->pose); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 2cc5cfda84c..da1767793bb 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -628,7 +628,8 @@ BL_Material* ConvertMaterial( material->transp = TF_ALPHA; // always zsort alpha + add - if(material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) { + if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) + && (material->transp != TF_CLIP)) { material->ras_mode |= ALPHA; material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; } @@ -1856,7 +1857,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, if (converter->addInitFromFrame) if (!isInActiveLayer) addobj=false; - + if (gameobj&&addobj) { MT_Point3 posPrev; diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index ad476e492d0..2828663c63d 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -93,6 +93,9 @@ void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene) { KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj); + if(replica) + replica->Release(); + return (void*)replica; } @@ -670,8 +673,12 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) for (oit=m_groupGameObjects.begin(); oit != m_groupGameObjects.end(); oit++) { gameobj = (KX_GameObject*)(*oit); - if (gameobj->GetParent() != NULL) + + KX_GameObject *parent = gameobj->GetParent(); + if (parent != NULL) { + parent->Release(); // GetParent() increased the refcount + // this object is not a top parent. Either it is the child of another // object in the group and it will be added automatically when the parent // is added. Or it is the child of an object outside the group and the group diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index d4bd109de1a..f5b463abf02 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -195,6 +195,8 @@ void KX_TrackToActuator::ProcessReplica() // the replica is tracking the same object => register it if (m_object) m_object->RegisterActuator(this); + if (m_parentobj) + m_parentobj->AddRef(); SCA_IActuator::ProcessReplica(); } @@ -219,6 +221,14 @@ void KX_TrackToActuator::Relink(GEN_Map *obj_map) m_object = (SCA_IObject*)(*h_obj); m_object->RegisterActuator(this); } + + void **h_parobj = (*obj_map)[m_parentobj]; + if (h_parobj) { + if (m_parentobj) + m_parentobj->Release(); + m_parentobj= (KX_GameObject*)(*h_parobj); + m_parentobj->AddRef(); + } } From d05363627bee12bd9e5af8b1114b68f73eeb3e5f Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 30 Jul 2008 17:22:57 +0000 Subject: [PATCH 19/58] Update MSVC project since recent commit --- .../gameengine/blenderhook/KX_blenderhook.vcproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj b/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj index b020d88b2b3..edf0faf4ab7 100644 --- a/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj +++ b/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj @@ -142,9 +142,6 @@ - - @@ -170,9 +167,6 @@ - - From 8a8a12ed846dc86b2f9b21582fd34d941beed7ed Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 30 Jul 2008 17:41:47 +0000 Subject: [PATCH 20/58] BGE patch: logic optimization part 2: remove inactive sensors from logic manager. With this patch, only sensors that are connected to active states are actually registered in the logic manager. Inactive sensors won't take any CPU, especially the Radar and Near sensors that use a physical object for the detection: these objects are removed from the physics engine. To take advantage of this optimization patch, you need to define very light idle state when the objects are inactive: make them transparent, suspend the physics, keep few sensors active (e,g a message sensor to wake up), etc. --- .../Converter/BL_BlenderDataConversion.cpp | 12 +-- .../Converter/KX_ConvertSensors.cpp | 6 +- .../GameLogic/SCA_ActuatorEventManager.cpp | 13 +-- .../GameLogic/SCA_ActuatorEventManager.h | 1 - .../GameLogic/SCA_AlwaysEventManager.cpp | 11 +-- .../GameLogic/SCA_AlwaysEventManager.h | 1 - .../gameengine/GameLogic/SCA_EventManager.cpp | 13 +-- .../gameengine/GameLogic/SCA_EventManager.h | 6 +- source/gameengine/GameLogic/SCA_IObject.cpp | 27 +++++- source/gameengine/GameLogic/SCA_ISensor.cpp | 9 +- source/gameengine/GameLogic/SCA_ISensor.h | 4 +- .../GameLogic/SCA_JoystickManager.cpp | 11 +-- .../GameLogic/SCA_JoystickManager.h | 1 - .../GameLogic/SCA_KeyboardManager.cpp | 15 +-- .../GameLogic/SCA_KeyboardManager.h | 1 - .../gameengine/GameLogic/SCA_LogicManager.cpp | 7 +- .../gameengine/GameLogic/SCA_MouseManager.cpp | 14 +-- .../gameengine/GameLogic/SCA_MouseManager.h | 1 - .../GameLogic/SCA_PropertyEventManager.cpp | 11 +-- .../GameLogic/SCA_PropertyEventManager.h | 1 - .../GameLogic/SCA_RandomEventManager.cpp | 11 +-- .../GameLogic/SCA_RandomEventManager.h | 1 - .../GameLogic/SCA_TimeEventManager.cpp | 5 + .../GameLogic/SCA_TimeEventManager.h | 1 + .../KXNetwork/KX_NetworkEventManager.cpp | 17 +--- .../Ketsji/KXNetwork/KX_NetworkEventManager.h | 3 - source/gameengine/Ketsji/KX_GameObject.cpp | 1 + source/gameengine/Ketsji/KX_NearSensor.cpp | 8 ++ source/gameengine/Ketsji/KX_NearSensor.h | 1 + .../gameengine/Ketsji/KX_RayEventManager.cpp | 9 +- source/gameengine/Ketsji/KX_RayEventManager.h | 1 - .../Ketsji/KX_TouchEventManager.cpp | 31 +++--- .../gameengine/Ketsji/KX_TouchEventManager.h | 2 +- source/gameengine/Ketsji/KX_TouchSensor.cpp | 8 ++ source/gameengine/Ketsji/KX_TouchSensor.h | 1 + .../Physics/BlOde/OdePhysicsEnvironment.h | 1 + .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 97 +++++-------------- .../Physics/Bullet/CcdPhysicsEnvironment.h | 11 +-- .../Physics/Dummy/DummyPhysicsEnvironment.h | 1 + .../Physics/Sumo/Fuzzics/src/SM_Scene.cpp | 17 ++-- .../Physics/Sumo/SumoPhysicsEnvironment.cpp | 6 ++ .../Physics/Sumo/SumoPhysicsEnvironment.h | 1 + .../Physics/common/PHY_IPhysicsEnvironment.h | 1 + 43 files changed, 158 insertions(+), 242 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index da1767793bb..f44318120e8 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2441,13 +2441,13 @@ void BL_ConvertBlenderObjects(struct Main* maggie, int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,layerMask,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); + // set the init state to all objects gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); + } + // apply the initial state to controllers, only on the active objects as this registers the sensors + for ( i=0;iGetCount();i++) + { + KX_GameObject* gameobj = static_cast(objectlist->GetValue(i)); gameobj->ResetState(); } diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 7c9df688d45..5e433bb821b 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -733,9 +733,9 @@ void BL_ConvertSensors(struct Object* blenderobject, gameobj->AddSensor(gamesensor); // only register to manager if it's in an active layer - - if (isInActiveLayer) - gamesensor->RegisterToManager(); + // Make registration dynamic: only when sensor is activated + //if (isInActiveLayer) + // gamesensor->RegisterToManager(); for (int i=0;itotlinks;i++) diff --git a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp index 28ca1fd673f..768a3a45937 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp @@ -48,19 +48,10 @@ SCA_ActuatorEventManager::~SCA_ActuatorEventManager() } - - -void SCA_ActuatorEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -} - - - void SCA_ActuatorEventManager::NextFrame() { // check for changed actuator - for (vector::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + for (set::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) { (*it)->Activate(m_logicmgr,NULL); } @@ -69,7 +60,7 @@ void SCA_ActuatorEventManager::NextFrame() void SCA_ActuatorEventManager::UpdateFrame() { // update the state of actuator before executing them - for (vector::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + for (set::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) { ((SCA_ActuatorSensor*)(*it))->Update(); } diff --git a/source/gameengine/GameLogic/SCA_ActuatorEventManager.h b/source/gameengine/GameLogic/SCA_ActuatorEventManager.h index b5108764197..a7d61627c23 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorEventManager.h +++ b/source/gameengine/GameLogic/SCA_ActuatorEventManager.h @@ -44,7 +44,6 @@ public: virtual ~SCA_ActuatorEventManager(); virtual void NextFrame(); virtual void UpdateFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); //SCA_LogicManager* GetLogicManager() { return m_logicmgr;} }; diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp index ab3bc2cc4ee..4cd2dfba994 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp @@ -51,16 +51,9 @@ SCA_AlwaysEventManager::SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr) void SCA_AlwaysEventManager::NextFrame() { - for (vector::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + for (set::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) { - SCA_ISensor* sensor = *i; - sensor->Activate(m_logicmgr, NULL); + (*i)->Activate(m_logicmgr, NULL); } } - - -void SCA_AlwaysEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -} diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.h b/source/gameengine/GameLogic/SCA_AlwaysEventManager.h index 28c71512875..a619eecddd4 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysEventManager.h +++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.h @@ -39,7 +39,6 @@ class SCA_AlwaysEventManager : public SCA_EventManager public: SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr); virtual void NextFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); }; diff --git a/source/gameengine/GameLogic/SCA_EventManager.cpp b/source/gameengine/GameLogic/SCA_EventManager.cpp index 0169864a133..e4fd0379597 100644 --- a/source/gameengine/GameLogic/SCA_EventManager.cpp +++ b/source/gameengine/GameLogic/SCA_EventManager.cpp @@ -45,17 +45,14 @@ SCA_EventManager::~SCA_EventManager() { } - +void SCA_EventManager::RegisterSensor(class SCA_ISensor* sensor) +{ + m_sensors.insert(sensor); +} void SCA_EventManager::RemoveSensor(class SCA_ISensor* sensor) { - std::vector::iterator i = - std::find(m_sensors.begin(), m_sensors.end(), sensor); - if (!(i == m_sensors.end())) - { - std::swap(*i, m_sensors.back()); - m_sensors.pop_back(); - } + m_sensors.erase(sensor); } void SCA_EventManager::NextFrame(double curtime, double fixedtime) diff --git a/source/gameengine/GameLogic/SCA_EventManager.h b/source/gameengine/GameLogic/SCA_EventManager.h index 9cc1718cd1e..9dbb5a6d24f 100644 --- a/source/gameengine/GameLogic/SCA_EventManager.h +++ b/source/gameengine/GameLogic/SCA_EventManager.h @@ -30,12 +30,14 @@ #define __KX_EVENTMANAGER #include +#include #include class SCA_EventManager { protected: - std::vector m_sensors; + // use a set to speed-up insertion/removal + std::set m_sensors; public: enum EVENT_MANAGER_TYPE { @@ -61,7 +63,7 @@ public: virtual void NextFrame(); virtual void UpdateFrame(); virtual void EndFrame(); - virtual void RegisterSensor(class SCA_ISensor* sensor)=0; + virtual void RegisterSensor(class SCA_ISensor* sensor); int GetType(); protected: diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 25b4af696ea..b0f8decee26 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -337,12 +337,31 @@ void SCA_IObject::Resume(void) void SCA_IObject::SetState(unsigned int state) { - m_state = state; - // update the status of the controllers + unsigned int tmpstate; SCA_ControllerList::iterator contit; - for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + + // we will update the state in two steps: + // 1) set the new state bits that are 1 + // 2) clr the new state bits that are 0 + // This to ensure continuity if a sensor is attached to two states + // that are switching state: no need to deactive and reactive the sensor + + tmpstate = m_state | state; + if (tmpstate != m_state) { - (*contit)->ApplyState(m_state); + // update the status of the controllers + for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + { + (*contit)->ApplyState(tmpstate); + } + } + m_state = state; + if (m_state != tmpstate) + { + for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + { + (*contit)->ApplyState(m_state); + } } } diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index f11c8047fac..2dc49924062 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -41,7 +41,8 @@ void SCA_ISensor::ReParent(SCA_IObject* parent) { SCA_ILogicBrick::ReParent(parent); - m_eventmgr->RegisterSensor(this); + // will be done when the sensor is activated + //m_eventmgr->RegisterSensor(this); this->SetActive(false); } @@ -133,6 +134,7 @@ void SCA_ISensor::DecLink() { { // sensor is detached from all controllers, initialize it so that it // is fresh as at startup when it is reattached again. + UnregisterToManager(); Init(); } } @@ -203,6 +205,11 @@ void SCA_ISensor::RegisterToManager() m_eventmgr->RegisterSensor(this); } +void SCA_ISensor::UnregisterToManager() +{ + m_eventmgr->RemoveSensor(this); +} + void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) { diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 51837755ba4..d5dabbce3ee 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -115,6 +115,8 @@ public: void SetLevel(bool lvl); void RegisterToManager(); + void UnregisterToManager(); + virtual float GetNumber(); /** Stop sensing for a while. */ @@ -129,7 +131,7 @@ public: void ClrLink() { m_links = 0; } void IncLink() - { m_links++; } + { if (!m_links++) RegisterToManager(); } void DecLink(); bool IsNoLink() const { return !m_links; } diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp index 7bf2049e56e..8ff28ba0b51 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp @@ -52,9 +52,10 @@ SCA_JoystickManager::~SCA_JoystickManager() void SCA_JoystickManager::NextFrame(double curtime,double deltatime) { - for (unsigned int i = 0; i < m_sensors.size(); i++) + set::iterator it; + for (it = m_sensors.begin(); it != m_sensors.end(); it++) { - SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*) m_sensors[i]; + SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); if(!joysensor->IsSuspended()) { m_joystick->HandleEvents(); @@ -64,12 +65,6 @@ void SCA_JoystickManager::NextFrame(double curtime,double deltatime) } -void SCA_JoystickManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -} - - SCA_Joystick *SCA_JoystickManager::GetJoystickDevice() { /* diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.h b/source/gameengine/GameLogic/SCA_JoystickManager.h index 3c4df64677e..f2bb27965fa 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.h +++ b/source/gameengine/GameLogic/SCA_JoystickManager.h @@ -45,7 +45,6 @@ public: SCA_JoystickManager(class SCA_LogicManager* logicmgr); virtual ~SCA_JoystickManager(); virtual void NextFrame(double curtime,double deltatime); - virtual void RegisterSensor(SCA_ISensor* sensor); SCA_Joystick* GetJoystickDevice(void); }; diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp index 259b06134d7..6a96442b124 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp @@ -62,23 +62,14 @@ void SCA_KeyboardManager::NextFrame() { //const SCA_InputEvent& event = GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)=0; // cerr << "SCA_KeyboardManager::NextFrame"<< endl; - for (unsigned int i=0;i::iterator it; + for (it=m_sensors.begin(); it != m_sensors.end(); it++) { - SCA_KeyboardSensor* keysensor = (SCA_KeyboardSensor*)m_sensors[i]; - keysensor->Activate(m_logicmanager,NULL); + (*it)->Activate(m_logicmanager,NULL); } } - - -void SCA_KeyboardManager::RegisterSensor(SCA_ISensor* keysensor) -{ - m_sensors.push_back(keysensor); -} - - - bool SCA_KeyboardManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode) { return false; diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.h b/source/gameengine/GameLogic/SCA_KeyboardManager.h index b4a50f56025..8f3cc0ab715 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardManager.h +++ b/source/gameengine/GameLogic/SCA_KeyboardManager.h @@ -55,7 +55,6 @@ public: bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode); virtual void NextFrame(); - virtual void RegisterSensor(class SCA_ISensor* sensor); SCA_IInputDevice* GetInputDevice(); }; diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index d1c5917f0ce..91e66aea359 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -176,12 +176,7 @@ void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor) (*c)->UnlinkSensor(sensor); } m_sensorcontrollermapje.erase(sensor); - - for (vector::const_iterator ie=m_eventmanagers.begin(); - !(ie==m_eventmanagers.end());ie++) - { - (*ie)->RemoveSensor(sensor); - } + sensor->UnregisterToManager(); } void SCA_LogicManager::RemoveController(SCA_IController* controller) diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp index b4251d8ab53..ca875dad07c 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.cpp +++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp @@ -75,9 +75,10 @@ void SCA_MouseManager::NextFrame() { if (m_mousedevice) { - for (unsigned int i = 0; i < m_sensors.size(); i++) + set::iterator it; + for (it=m_sensors.begin(); it!=m_sensors.end(); it++) { - SCA_MouseSensor* mousesensor = (SCA_MouseSensor*) m_sensors[i]; + SCA_MouseSensor* mousesensor = (SCA_MouseSensor*)(*it); // (0,0) is the Upper Left corner in our local window // coordinates if (!mousesensor->IsSuspended()) @@ -98,15 +99,6 @@ void SCA_MouseManager::NextFrame() } } - - -void SCA_MouseManager::RegisterSensor(SCA_ISensor* keysensor) -{ - m_sensors.push_back(keysensor); -} - - - bool SCA_MouseManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode) { /* We should guard for non-mouse events maybe? A rather silly side */ diff --git a/source/gameengine/GameLogic/SCA_MouseManager.h b/source/gameengine/GameLogic/SCA_MouseManager.h index bc8254486ad..efa4c639ce7 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.h +++ b/source/gameengine/GameLogic/SCA_MouseManager.h @@ -62,7 +62,6 @@ public: */ bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode); virtual void NextFrame(); - virtual void RegisterSensor(class SCA_ISensor* sensor); SCA_IInputDevice* GetInputDevice(); }; diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp index fc56d101728..e5e3f9cced5 100644 --- a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp @@ -47,19 +47,10 @@ SCA_PropertyEventManager::~SCA_PropertyEventManager() } - - -void SCA_PropertyEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -} - - - void SCA_PropertyEventManager::NextFrame() { // check for changed properties - for (vector::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + for (set::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) { (*it)->Activate(m_logicmgr,NULL); } diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.h b/source/gameengine/GameLogic/SCA_PropertyEventManager.h index aaa303a52c8..f166065b198 100644 --- a/source/gameengine/GameLogic/SCA_PropertyEventManager.h +++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.h @@ -43,7 +43,6 @@ public: SCA_PropertyEventManager(class SCA_LogicManager* logicmgr); virtual ~SCA_PropertyEventManager(); virtual void NextFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); //SCA_LogicManager* GetLogicManager() { return m_logicmgr;} }; diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp index 02020a52a17..156478d866d 100644 --- a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp @@ -50,16 +50,9 @@ SCA_RandomEventManager::SCA_RandomEventManager(class SCA_LogicManager* logicmgr) void SCA_RandomEventManager::NextFrame() { - for (vector::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + for (set::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) { - SCA_ISensor *sensor = *i; - sensor->Activate(m_logicmgr, NULL); + (*i)->Activate(m_logicmgr, NULL); } } - - -void SCA_RandomEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -}; diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.h b/source/gameengine/GameLogic/SCA_RandomEventManager.h index 8c75ef665fa..79138c23c62 100644 --- a/source/gameengine/GameLogic/SCA_RandomEventManager.h +++ b/source/gameengine/GameLogic/SCA_RandomEventManager.h @@ -45,7 +45,6 @@ public: SCA_RandomEventManager(class SCA_LogicManager* logicmgr); virtual void NextFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); }; #endif //__KX_RANDOMEVENTMGR diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp index 643f1247a52..b7fadd3d62c 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp @@ -65,6 +65,11 @@ void SCA_TimeEventManager::RegisterSensor(SCA_ISensor* sensor) // not yet } +void SCA_TimeEventManager::RemoveSensor(SCA_ISensor* sensor) +{ + // empty +} + void SCA_TimeEventManager::NextFrame(double curtime, double fixedtime) diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.h b/source/gameengine/GameLogic/SCA_TimeEventManager.h index 2fd39661a2d..bd57e12eb44 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.h +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.h @@ -45,6 +45,7 @@ public: virtual void NextFrame(double curtime, double fixedtime); virtual void RegisterSensor(class SCA_ISensor* sensor); + virtual void RemoveSensor(class SCA_ISensor* sensor); void AddTimeProperty(CValue* timeval); void RemoveTimeProperty(CValue* timeval); }; diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp index 7b5b7fdf78c..eee8e9f6827 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp @@ -55,28 +55,13 @@ KX_NetworkEventManager::~KX_NetworkEventManager() //printf("KX_NetworkEventManager destructor\n"); } -void KX_NetworkEventManager::RegisterSensor(class SCA_ISensor* sensor) -{ - //printf("KX_NetworkEventManager RegisterSensor\n"); - m_sensors.push_back(sensor); -} - -void KX_NetworkEventManager::RemoveSensor(class SCA_ISensor* sensor) -{ - //printf("KX_NetworkEventManager RemoveSensor\n"); - // Network specific RemoveSensor stuff goes here - - // parent - SCA_EventManager::RemoveSensor(sensor); -} - void KX_NetworkEventManager::NextFrame() { // printf("KX_NetworkEventManager::proceed %.2f - %.2f\n", curtime, deltatime); // each frame, the logicmanager will call the network // eventmanager to look for network events, and process it's // 'network' sensors - vector::iterator it; + set::iterator it; for (it = m_sensors.begin(); !(it==m_sensors.end()); it++) { // printf("KX_NetworkEventManager::proceed sensor %.2f\n", curtime); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h index 0b097ba2ef6..ae88f1d4987 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h @@ -42,9 +42,6 @@ public: class NG_NetworkDeviceInterface *ndi); virtual ~KX_NetworkEventManager (); - virtual void RegisterSensor(class SCA_ISensor* sensor); - virtual void RemoveSensor(class SCA_ISensor* sensor); - virtual void NextFrame(); virtual void EndFrame(); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index df478be5ca2..02d1ad1b12b 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -275,6 +275,7 @@ void KX_GameObject::ProcessReplica(KX_GameObject* replica) replica->m_pSGNode = NULL; replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info); replica->m_pClient_info->m_gameobject = replica; + replica->m_state = 0; } diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 89699d80031..140dd37f5c6 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -98,6 +98,14 @@ void KX_NearSensor::RegisterSumo(KX_TouchEventManager *touchman) } } +void KX_NearSensor::UnregisterSumo(KX_TouchEventManager* touchman) +{ + if (m_physCtrl) + { + touchman->GetPhysicsEnvironment()->removeSensor(m_physCtrl); + } +} + CValue* KX_NearSensor::GetReplica() { KX_NearSensor* replica = new KX_NearSensor(*this); diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index c6724caccc3..3f7078ef9fd 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -77,6 +77,7 @@ public: const PHY_CollData * coll_data); virtual bool BroadPhaseFilterCollision(void*obj1,void*obj2); virtual void RegisterSumo(KX_TouchEventManager *touchman); + virtual void UnregisterSumo(KX_TouchEventManager* touchman); virtual PyObject* _getattr(const STR_String& attr); diff --git a/source/gameengine/Ketsji/KX_RayEventManager.cpp b/source/gameengine/Ketsji/KX_RayEventManager.cpp index 4101c6b547e..1af29151adf 100644 --- a/source/gameengine/Ketsji/KX_RayEventManager.cpp +++ b/source/gameengine/Ketsji/KX_RayEventManager.cpp @@ -44,14 +44,9 @@ using namespace std; void KX_RayEventManager::NextFrame() { - for (vector::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + for (set::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) { - SCA_ISensor *sensor = *i; - sensor->Activate(m_logicmgr, NULL); + (*i)->Activate(m_logicmgr, NULL); } } -void KX_RayEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -}; diff --git a/source/gameengine/Ketsji/KX_RayEventManager.h b/source/gameengine/Ketsji/KX_RayEventManager.h index 3630f9682b9..b816d4d5250 100644 --- a/source/gameengine/Ketsji/KX_RayEventManager.h +++ b/source/gameengine/Ketsji/KX_RayEventManager.h @@ -45,7 +45,6 @@ public: m_logicmgr(logicmgr) {} virtual void NextFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); }; #endif //__KX_RAYEVENTMGR diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp index 423543eef5c..7528fdbbc34 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp +++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp @@ -100,16 +100,24 @@ bool KX_TouchEventManager::newBroadphaseResponse(void *client_data, void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor) { KX_TouchSensor* touchsensor = static_cast(sensor); - m_sensors.push_back(touchsensor); + m_sensors.insert(touchsensor); touchsensor->RegisterSumo(this); } +void KX_TouchEventManager::RemoveSensor(SCA_ISensor* sensor) +{ + KX_TouchSensor* touchsensor = static_cast(sensor); + m_sensors.erase(touchsensor); + + touchsensor->UnregisterSumo(this); +} + void KX_TouchEventManager::EndFrame() { - vector::iterator it; + set::iterator it; for ( it = m_sensors.begin(); !(it==m_sensors.end());it++) { @@ -124,7 +132,7 @@ void KX_TouchEventManager::NextFrame() { if (m_sensors.size() > 0) { - vector::iterator it; + set::iterator it; for (it = m_sensors.begin();!(it==m_sensors.end());++it) static_cast(*it)->SynchronizeTransform(); @@ -157,20 +165,3 @@ void KX_TouchEventManager::NextFrame() (*it)->Activate(m_logicmgr,NULL); } } - - - -void KX_TouchEventManager::RemoveSensor(class SCA_ISensor* sensor) -{ - std::vector::iterator i = - std::find(m_sensors.begin(), m_sensors.end(), sensor); - if (!(i == m_sensors.end())) - { - std::swap(*i, m_sensors.back()); - m_sensors.pop_back(); - } - - // remove the sensor forever :) - SCA_EventManager::RemoveSensor(sensor); -} - diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.h b/source/gameengine/Ketsji/KX_TouchEventManager.h index 20ed6126bd0..cc77bccfc31 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.h +++ b/source/gameengine/Ketsji/KX_TouchEventManager.h @@ -71,8 +71,8 @@ public: PHY_IPhysicsEnvironment* physEnv); virtual void NextFrame(); virtual void EndFrame(); - virtual void RemoveSensor(class SCA_ISensor* sensor); virtual void RegisterSensor(SCA_ISensor* sensor); + virtual void RemoveSensor(SCA_ISensor* sensor); SCA_LogicManager* GetLogicManager() { return m_logicmgr;} PHY_IPhysicsEnvironment *GetPhysicsEnvironment() { return m_physEnv; } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index ce3aa1de2ef..60e1d87d318 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -153,6 +153,14 @@ void KX_TouchSensor::RegisterSumo(KX_TouchEventManager *touchman) } } +void KX_TouchSensor::UnregisterSumo(KX_TouchEventManager* touchman) +{ + if (m_physCtrl) + { + touchman->GetPhysicsEnvironment()->removeCollisionCallback(m_physCtrl); + } +} + bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_CollData* colldata) { // KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr; diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 056440ccd6c..b611d296939 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -76,6 +76,7 @@ public: virtual void ReParent(SCA_IObject* parent); virtual void RegisterSumo(KX_TouchEventManager* touchman); + virtual void UnregisterSumo(KX_TouchEventManager* touchman); // virtual DT_Bool HandleCollision(void* obj1,void* obj2, // const DT_CollData * coll_data); diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h index ec1b7702ffd..7c61902f8e2 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h @@ -65,6 +65,7 @@ public: { } virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl) {} + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl) {} virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;} virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight) { return 0;} diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index b773f40650b..ea14c5430e2 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -368,7 +368,7 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) body->setUserPointer(ctrl); body->setGravity( m_gravity ); - m_controllers.push_back(ctrl); + m_controllers.insert(ctrl); //use explicit group/filter for finer control over collision in bullet => near/radar sensor m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); @@ -434,36 +434,13 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl) { - //also remove constraint - - m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); - - - { - std::vector::iterator i = - std::find(m_controllers.begin(), m_controllers.end(), ctrl); - if (!(i == m_controllers.end())) - { - std::swap(*i, m_controllers.back()); - m_controllers.pop_back(); - } - } + m_controllers.erase(ctrl); //remove it from the triggers - { - std::vector::iterator i = - std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl); - if (!(i == m_triggerControllers.end())) - { - std::swap(*i, m_triggerControllers.back()); - m_triggerControllers.pop_back(); - } - } - - + m_triggerControllers.erase(ctrl); } void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask) @@ -487,11 +464,10 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctrl) { - std::vector::iterator i = - std::find(m_controllers.begin(), m_controllers.end(), ctrl); - if (i == m_controllers.end()) + if (m_controllers.insert(ctrl).second) { btRigidBody* body = ctrl->GetRigidBody(); + body->setUserPointer(ctrl); m_dynamicsWorld->addCollisionObject(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); } @@ -507,12 +483,12 @@ void CcdPhysicsEnvironment::beginFrame() bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) { + std::set::iterator it; + int i; - int i,numCtrl = GetNumControllers(); - for (i=0;iSynchronizeMotionStates(timeStep); + (*it)->SynchronizeMotionStates(timeStep); } float subStep = timeStep / float(m_numTimeSubSteps); @@ -521,11 +497,9 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step } - numCtrl = GetNumControllers(); - for (i=0;iSynchronizeMotionStates(timeStep); + (*it)->SynchronizeMotionStates(timeStep); } for (i=0;i::iterator i = - std::find(m_controllers.begin(), m_controllers.end(), ctrl); - if ((i == m_controllers.end())) - { - addCcdPhysicsController(ctrl1); - } + // addSensor() is a "light" function for bullet because it is used + // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead + //if (m_controllers.insert(ctrl1).second) + //{ + // addCcdPhysicsController(ctrl1); + //} + enableCcdPhysicsController(ctrl1); + //Collision filter/mask is now set at the time of the creation of the controller //force collision detection with everything, including static objects (might hurt performance!) //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::SensorTrigger; @@ -923,21 +885,15 @@ void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) { - std::vector::iterator i = - std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl); - if (!(i == m_triggerControllers.end())) - { - std::swap(*i, m_triggerControllers.back()); - m_triggerControllers.pop_back(); - } + m_triggerControllers.erase((CcdPhysicsController*)ctrl); } void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl) { - removeCollisionCallback(ctrl); - //printf("removeSensor\n"); + removeCcdPhysicsController((CcdPhysicsController*)ctrl); } + void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) { /* printf("addTouchCallback\n(response class = %i)\n",response_class); @@ -975,10 +931,9 @@ void CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctr CcdPhysicsController* ccdCtrl = static_cast(ctrl); //printf("requestCollisionCallback\n"); - m_triggerControllers.push_back(ccdCtrl); + m_triggerControllers.insert(ccdCtrl); } - void CcdPhysicsEnvironment::CallbackTriggers() { @@ -1011,11 +966,10 @@ void CcdPhysicsEnvironment::CallbackTriggers() CcdPhysicsController* ctrl0 = static_cast(obj0->getUserPointer()); CcdPhysicsController* ctrl1 = static_cast(obj1->getUserPointer()); - std::vector::iterator i = - std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl0); + std::set::const_iterator i = m_triggerControllers.find(ctrl0); if (i == m_triggerControllers.end()) { - i = std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl1); + i = m_triggerControllers.find(ctrl1); } if (!(i == m_triggerControllers.end())) @@ -1125,7 +1079,6 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radi CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo); - return sphereController; } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 453749b27b3..fd96522037e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -18,6 +18,7 @@ subject to the following restrictions: #include "PHY_IPhysicsEnvironment.h" #include +#include class CcdPhysicsController; #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" @@ -209,12 +210,6 @@ protected: } - int GetNumControllers(); - - CcdPhysicsController* GetPhysicsController( int index); - - - const btPersistentManifold* GetManifold(int index) const; @@ -229,9 +224,9 @@ protected: - std::vector m_controllers; + std::set m_controllers; - std::vector m_triggerControllers; + std::set m_triggerControllers; PHY_ResponseCallback m_triggerCallbacks[PHY_NUM_RESPONSE]; void* m_triggerCallbacksUserPtrs[PHY_NUM_RESPONSE]; diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index f0761618e4e..b5a61f72e4a 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -80,6 +80,7 @@ public: { } virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl) {} + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl) {} virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;} virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight) { return 0;} diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp index b5bf67b14ea..f0791bbf89f 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp @@ -98,12 +98,17 @@ void SM_Scene::addTouchCallback(int response_class, DT_ResponseCallback callback void SM_Scene::addSensor(SM_Object& object) { - object.calcXform(); - m_objectList.push_back(&object); - DT_AddObject(m_scene, object.getObjectHandle()); - DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[SENSOR_RESPONSE]); - DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass[SENSOR_RESPONSE]); - DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[SENSOR_RESPONSE]); + T_ObjectList::iterator i = + std::find(m_objectList.begin(), m_objectList.end(), &object); + if (i == m_objectList.end()) + { + object.calcXform(); + m_objectList.push_back(&object); + DT_AddObject(m_scene, object.getObjectHandle()); + DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[SENSOR_RESPONSE]); + DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass [SENSOR_RESPONSE]); + DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[SENSOR_RESPONSE]); + } } void SM_Scene::add(SM_Object& object) { diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp index 16ba45a0be5..65018d2523e 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp @@ -228,6 +228,12 @@ void SumoPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ct m_sumoScene->requestCollisionCallback(*smObject); } } + +void SumoPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) +{ + // intentionally empty +} + PHY_IPhysicsController* SumoPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position) { DT_ShapeHandle shape = DT_NewSphere(0.0); diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h index ce5cd70e8cc..8b9fb463034 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h @@ -84,6 +84,7 @@ public: virtual void removeSensor(PHY_IPhysicsController* ctrl); virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user); virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl); + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl); virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position); virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight); diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index c148210903f..5b275066665 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -104,6 +104,7 @@ class PHY_IPhysicsEnvironment virtual void removeSensor(PHY_IPhysicsController* ctrl)=0; virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)=0; virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl)=0; + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl)=0; //These two methods are *solely* used to create controllers for sensor! Don't use for anything else virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) =0; virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight)=0; From 01b1bd49015ee0f0389a28b62669aa2414d2d46d Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 30 Jul 2008 20:45:04 +0000 Subject: [PATCH 21/58] * another commit adding std:: to the sort call (older msvc [<9] choked?) --- source/gameengine/Rasterizer/RAS_MeshObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index adef998acc2..af5228e4c35 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -676,7 +676,7 @@ void RAS_MeshObject::SortPolygons(const MT_Transform &transform) slots[j].get(vertexarray, indexarray, j*nvert, nvert, pnorm); /* sort (stable_sort might be better, if flickering happens?) */ - sort(slots.begin(), slots.end(), backtofront()); + std::sort(slots.begin(), slots.end(), backtofront()); /* get indices from temporary array again */ for(j=0; j Date: Wed, 30 Jul 2008 21:52:02 +0000 Subject: [PATCH 22/58] Tools ----- Minor changes to boolean code; add an new include file to gather various #defines global to the boolean system. Currently, this just allows control of whether some debugging code is compiled or not. This is a precursor commit for some other boolean optimizations/cleanups. But in case that commit is later reverted, this code should still remain. --- intern/boolop/intern/BOP_Edge.cpp | 15 ++++++++++ intern/boolop/intern/BOP_Edge.h | 5 ++++ intern/boolop/intern/BOP_Face.cpp | 2 ++ intern/boolop/intern/BOP_Face.h | 3 ++ intern/boolop/intern/BOP_Mesh.cpp | 4 ++- intern/boolop/intern/BOP_Mesh.h | 7 ----- intern/boolop/intern/BOP_Misc.h | 43 +++++++++++++++++++++++++++++ intern/boolop/intern/BOP_Vertex.cpp | 19 +++++++++++++ intern/boolop/intern/BOP_Vertex.h | 5 ++++ 9 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 intern/boolop/intern/BOP_Misc.h diff --git a/intern/boolop/intern/BOP_Edge.cpp b/intern/boolop/intern/BOP_Edge.cpp index ac302b530df..dc6222fcd4e 100644 --- a/intern/boolop/intern/BOP_Edge.cpp +++ b/intern/boolop/intern/BOP_Edge.cpp @@ -75,4 +75,19 @@ void BOP_Edge::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex) else if (m_vertexs[1] == oldIndex) m_vertexs[1] = newIndex; } +#ifdef BOP_DEBUG + +#include +using namespace std; + +/** + * Implements operator <<. + */ +ostream &operator<<(ostream &stream, BOP_Edge *e) +{ + stream << "Edge[" << e->getVertex1() << "," << e->getVertex2(); + return stream; +} +#endif + diff --git a/intern/boolop/intern/BOP_Edge.h b/intern/boolop/intern/BOP_Edge.h index 13426f6e63c..fb352620c17 100644 --- a/intern/boolop/intern/BOP_Edge.h +++ b/intern/boolop/intern/BOP_Edge.h @@ -29,6 +29,7 @@ #define BOP_EDGE_H #include "BOP_Indexs.h" +#include "BOP_Misc.h" class BOP_Edge { @@ -47,6 +48,10 @@ public: inline unsigned int getNumFaces(){return m_faces.size();}; inline BOP_Indexs &getFaces(){return m_faces;}; void addFace(BOP_Index face); +#ifdef BOP_DEBUG + friend ostream &operator<<(ostream &stream, BOP_Edge *e); +#endif + }; #endif diff --git a/intern/boolop/intern/BOP_Face.cpp b/intern/boolop/intern/BOP_Face.cpp index 12c94624517..01308de3e5d 100644 --- a/intern/boolop/intern/BOP_Face.cpp +++ b/intern/boolop/intern/BOP_Face.cpp @@ -402,6 +402,7 @@ bool BOP_Face4::getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e) return true; } +#ifdef BOP_DEBUG /** * Implements operator <<. */ @@ -421,3 +422,4 @@ ostream &operator<<(ostream &stream, BOP_Face *f) return stream; } +#endif diff --git a/intern/boolop/intern/BOP_Face.h b/intern/boolop/intern/BOP_Face.h index e16425f78b3..965882db732 100644 --- a/intern/boolop/intern/BOP_Face.h +++ b/intern/boolop/intern/BOP_Face.h @@ -32,6 +32,7 @@ #include "MT_Plane3.h" #include "BOP_Indexs.h" #include "BOP_BBox.h" +#include "BOP_Misc.h" #include #include using namespace std; @@ -80,7 +81,9 @@ public: virtual void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex) = 0; virtual bool containsVertex(BOP_Index v) = 0; +#ifdef BOP_DEBUG friend ostream &operator<<(ostream &stream, BOP_Face *f); +#endif }; class BOP_Face3: public BOP_Face diff --git a/intern/boolop/intern/BOP_Mesh.cpp b/intern/boolop/intern/BOP_Mesh.cpp index 5659cd62a3f..685478fae39 100644 --- a/intern/boolop/intern/BOP_Mesh.cpp +++ b/intern/boolop/intern/BOP_Mesh.cpp @@ -794,7 +794,8 @@ bool BOP_Mesh::isClosedMesh() } -/** *************************************************************************** +#ifdef BOP_DEBUG +/****************************************************************************** * DEBUG METHODS * * This functions are used to test the mesh state and debug program errors. * ******************************************************************************/ @@ -1075,3 +1076,4 @@ void BOP_Mesh::updatePlanes() } } +#endif diff --git a/intern/boolop/intern/BOP_Mesh.h b/intern/boolop/intern/BOP_Mesh.h index 9abff52545f..46c8fa53d20 100644 --- a/intern/boolop/intern/BOP_Mesh.h +++ b/intern/boolop/intern/BOP_Mesh.h @@ -1,10 +1,3 @@ -/* - * TEMPORARY defines to enable hashing support - */ - -#define HASH(x) ((x) >> 5) /* each "hash" covers 32 indices */ -// #define HASH_PRINTF_DEBUG /* uncomment to enable debug output */ - /** * * $Id$ diff --git a/intern/boolop/intern/BOP_Misc.h b/intern/boolop/intern/BOP_Misc.h new file mode 100644 index 00000000000..0e009d8ee8d --- /dev/null +++ b/intern/boolop/intern/BOP_Misc.h @@ -0,0 +1,43 @@ +/** + * + * $Id: BOP_Misc.h 14444 2008-04-16 22:40:48Z khughes $ + * + * ***** 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): Ken Hughes + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* + * This file contains various definitions used across the modules + */ + +/* + * define operator>> for faces, edges and vertices, and also add some + * debugging functions for displaying various internal data structures + */ + +// #define BOP_DEBUG + +#define HASH(x) ((x) >> 5) /* each "hash" covers 32 indices */ +// #define HASH_PRINTF_DEBUG /* uncomment to enable debug output */ diff --git a/intern/boolop/intern/BOP_Vertex.cpp b/intern/boolop/intern/BOP_Vertex.cpp index a429c26d204..edb53ea6a59 100644 --- a/intern/boolop/intern/BOP_Vertex.cpp +++ b/intern/boolop/intern/BOP_Vertex.cpp @@ -89,3 +89,22 @@ bool BOP_Vertex::containsEdge(BOP_Index i) return false; } + +#ifdef BOP_DEBUG +/** + * Implements operator <<. + */ +#include + +ostream &operator<<(ostream &stream, BOP_Vertex *v) +{ + char aux[20]; + BOP_stringTAG(v->m_tag,aux); + MT_Point3 point = v->getPoint(); + stream << setprecision(6) << showpoint << fixed; + stream << "Vertex[" << point[0] << "," << point[1] << ","; + stream << point[2] << "] (" << aux << ")"; + return stream; +} +#endif + diff --git a/intern/boolop/intern/BOP_Vertex.h b/intern/boolop/intern/BOP_Vertex.h index 3a9895df6d3..18b2f168f8c 100644 --- a/intern/boolop/intern/BOP_Vertex.h +++ b/intern/boolop/intern/BOP_Vertex.h @@ -31,6 +31,7 @@ #include "BOP_Tag.h" #include "BOP_Indexs.h" #include "MT_Point3.h" +#include "BOP_Misc.h" class BOP_Vertex { @@ -52,6 +53,10 @@ public: inline MT_Point3 getPoint() const { return m_point;}; inline BOP_TAG getTAG() { return m_tag;}; inline void setTAG(BOP_TAG t) { m_tag = t;}; +#ifdef BOP_DEBUG + friend ostream &operator<<(ostream &stream, BOP_Vertex *v); +#endif + }; #endif From db82e15e6fd9c87e0a443aef09c775faa9b1aa50 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 31 Jul 2008 12:23:09 +0000 Subject: [PATCH 23/58] Korean translation, provided by J.H. Jeong (yongdori) (Bugreport 17415) --- bin/.blender/.Blanguages | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/.blender/.Blanguages b/bin/.blender/.Blanguages index 0f98ce02247..de8d8c44550 100644 --- a/bin/.blender/.Blanguages +++ b/bin/.blender/.Blanguages @@ -20,3 +20,4 @@ Romanian:ro Arabic:ar Bulgarian:bg Greek:el +Korean:kr From d66449996cb719138d1fe3e6838fd403cf64a512 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 31 Jul 2008 12:23:29 +0000 Subject: [PATCH 24/58] == Grease Pencil Eraser - Tweaks == Improved accuracy of the eraser a bit. Now it does a boundbox test first before trying to erase strokes, which means that other (rather unrelated) strokes are less likely to be affected as well. --- source/blender/include/BIF_editview.h | 2 + source/blender/src/editview.c | 2 +- source/blender/src/gpencil.c | 171 ++++++++++++++------------ 3 files changed, 97 insertions(+), 78 deletions(-) diff --git a/source/blender/include/BIF_editview.h b/source/blender/include/BIF_editview.h index 4c407d43672..d2c6c56d01a 100644 --- a/source/blender/include/BIF_editview.h +++ b/source/blender/include/BIF_editview.h @@ -34,8 +34,10 @@ struct Base; struct Object; struct Camera; struct View3D; +struct rcti; void arrows_move_cursor(unsigned short event); +void lasso_select_boundbox(struct rcti *rect, short mcords[][2], short moves); int lasso_inside(short mcords[][2], short moves, short sx, short sy); int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1); void borderselect(void); diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index f58248be161..a3fcad7885c 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -371,7 +371,7 @@ static void do_lasso_select_objects(short mcords[][2], short moves, short select } } -static void lasso_select_boundbox(rcti *rect, short mcords[][2], short moves) +void lasso_select_boundbox(rcti *rect, short mcords[][2], short moves) { short a; diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index f4274b853cc..eef21323a44 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -48,6 +48,7 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_userdef_types.h" +#include "DNA_vec_types.h" #include "DNA_view3d_types.h" #include "BKE_global.h" @@ -920,7 +921,6 @@ static short gp_stroke_addpoint (tGPsdata *p, short mval[2], float pressure) if (gpd->sbuffer_size >= GP_STROKE_BUFFER_MAX) return GP_STROKEADD_OVERFLOW; - /* get pointer to destination point */ pt= ((tGPspoint *)(gpd->sbuffer) + gpd->sbuffer_size); @@ -1012,8 +1012,76 @@ static short (*gp_stroke_eraser_2mco (bGPdata *gpd))[2] return mcoords; } -/* eraser tool evaluation per curve */ -static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short moves, bGPDframe *gpf, bGPDstroke *gps) +/* eraser tool - remove segment from stroke/split stroke (after lasso inside) */ +static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i) +{ + bGPDspoint *pt_tmp= gps->points; + bGPDstroke *gsn = NULL; + + /* if stroke only had two points, get rid of stroke */ + if (gps->totpoints == 2) { + /* free stroke points, then stroke */ + MEM_freeN(pt_tmp); + BLI_freelinkN(&gpf->strokes, gps); + + /* nothing left in stroke, so stop */ + return 1; + } + + /* if last segment, just remove segment from the stroke */ + else if (i == gps->totpoints - 2) { + /* allocate new points array, and assign most of the old stroke there */ + gps->totpoints--; + gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); + memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*gps->totpoints); + + /* free temp buffer */ + MEM_freeN(pt_tmp); + + /* nothing left in stroke, so stop */ + return 1; + } + + /* if first segment, just remove segment from the stroke */ + else if (i == 0) { + /* allocate new points array, and assign most of the old stroke there */ + gps->totpoints--; + gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); + memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint)*gps->totpoints); + + /* free temp buffer */ + MEM_freeN(pt_tmp); + + /* no break here, as there might still be stuff to remove in this stroke */ + return 0; + } + + /* segment occurs in 'middle' of stroke, so split */ + else { + /* duplicate stroke, and assign 'later' data to that stroke */ + gsn= MEM_dupallocN(gps); + gsn->prev= gsn->next= NULL; + BLI_insertlinkafter(&gpf->strokes, gps, gsn); + + gsn->totpoints= gps->totpoints - i; + gsn->points= MEM_callocN(sizeof(bGPDspoint)*gsn->totpoints, "gp_stroke_points"); + memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint)*gsn->totpoints); + + /* adjust existing stroke */ + gps->totpoints= i; + gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); + memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*i); + + /* free temp buffer */ + MEM_freeN(pt_tmp); + + /* nothing left in stroke, so stop */ + return 1; + } +} + +/* eraser tool - evaluation per stroke */ +static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short moves, rcti *rect, bGPDframe *gpf, bGPDstroke *gps) { bGPDspoint *pt1, *pt2; short x0=0, y0=0, x1=0, y1=0; @@ -1044,11 +1112,14 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo y0= (gps->points->y / 1000 * p->sa->winy); } - /* only check if point is inside */ - if (lasso_inside(mcoords, moves, x0, y0)) { - /* free stroke */ - MEM_freeN(gps->points); - BLI_freelinkN(&gpf->strokes, gps); + /* do boundbox check first */ + if (BLI_in_rcti(rect, x0, y0)) { + /* only check if point is inside */ + if (lasso_inside(mcoords, moves, x0, y0)) { + /* free stroke */ + MEM_freeN(gps->points); + BLI_freelinkN(&gpf->strokes, gps); + } } } else { @@ -1083,73 +1154,17 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo y1= (pt2->y / 1000 * p->sa->winy); } - /* check if point segment of stroke had anything to do with - * eraser region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant - * - handled using the lasso-select checking code - */ - if (lasso_inside_edge(mcoords, moves, x0, y0, x1, x1)) { - bGPDspoint *pt_tmp= gps->points; - bGPDstroke *gsn = NULL; - - /* if stroke only had two points, get rid of stroke */ - if (gps->totpoints == 2) { - /* free stroke points, then stroke */ - MEM_freeN(pt_tmp); - BLI_freelinkN(&gpf->strokes, gps); - - /* nothing left in stroke, so stop */ - break; - } - - /* if last segment, just remove segment from the stroke */ - else if (i == gps->totpoints - 2) { - /* allocate new points array, and assign most of the old stroke there */ - gps->totpoints--; - gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); - memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*gps->totpoints); - - /* free temp buffer */ - MEM_freeN(pt_tmp); - - /* nothing left in stroke, so stop */ - break; - } - - /* if first segment, just remove segment from the stroke */ - else if (i == 0) { - /* allocate new points array, and assign most of the old stroke there */ - gps->totpoints--; - gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); - memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint)*gps->totpoints); - - /* free temp buffer */ - MEM_freeN(pt_tmp); - - /* no break here, as there might still be stuff to remove in this stroke */ - } - - /* segment occurs in 'middle' of stroke, so split */ - else { - /* duplicate stroke, and assign 'later' data to that stroke */ - gsn= MEM_dupallocN(gps); - gsn->prev= gsn->next= NULL; - BLI_insertlinkafter(&gpf->strokes, gps, gsn); - - gsn->totpoints= gps->totpoints - i; - gsn->points= MEM_callocN(sizeof(bGPDspoint)*gsn->totpoints, "gp_stroke_points"); - memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint)*gsn->totpoints); - - /* adjust existing stroke */ - gps->totpoints= i; - gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); - memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*i); - - /* free temp buffer */ - MEM_freeN(pt_tmp); - - /* nothing left in stroke, so stop */ - break; + /* check that point segment of the boundbox of the eraser stroke */ + if (BLI_in_rcti(rect, x0, y0) || BLI_in_rcti(rect, x1, y1)) { + /* check if point segment of stroke had anything to do with + * eraser region (either within stroke painted, or on its lines) + * - this assumes that linewidth is irrelevant + * - handled using the lasso-select checking code + */ + if (lasso_inside_edge(mcoords, moves, x0, y0, x1, x1)) { + /* if function returns true, break this loop (as no more point to check) */ + if (gp_stroke_eraser_splitdel(gpf, gps, i)) + break; } } } @@ -1165,14 +1180,16 @@ static void gp_stroke_doeraser (tGPsdata *p) bGPDframe *gpf= p->gpf; bGPDstroke *gps, *gpn; short (*mcoords)[2]; + rcti rect; - /* get buffer-stroke coordinates as shorts array */ + /* get buffer-stroke coordinates as shorts array, and then get bounding box */ mcoords= gp_stroke_eraser_2mco(gpd); + lasso_select_boundbox(&rect, mcoords, gpd->sbuffer_size); /* loop over strokes, checking segments for intersections */ for (gps= gpf->strokes.first; gps; gps= gpn) { gpn= gps->next; - gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, gpf, gps); + gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, &rect, gpf, gps); } /* free mcoords array */ From cb0aa467cd7acb1392897bf436d808de5b40e552 Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Thu, 31 Jul 2008 18:37:03 +0000 Subject: [PATCH 25/58] Tools ----- New boolean merge algorithm. The current code often does a poor job of merging tris and quads after the operation, resulting in many unnecessary faces. This commit add a new algorithm which takes advantage of topology information saved in the interal BOP structures. The file intern/boolop/intern/BOP_Misc.h has two #defines which control which algorithm(s) are compiled. They are set now to compile both, with the new algorithm as the default. The original algorithm can be enabled by setting the "rt" debugging button on the Scene panel (F10) to 100. One note: the current boolean code still occasionally creates a non-manifold mesh from an operation on two manifold meshes. The original merge algorithm would sometimes "close" these meshes and sometimes not. The new algorithms behaves the same way, but sometimes closes a mesh the original would not and sometimes leaves open a mesh the original would close. My fairly extensive tests did not indicate any significant difference in the percentage of final non-manifold meshes. --- intern/boolop/intern/BOP_Edge.cpp | 28 + intern/boolop/intern/BOP_Edge.h | 8 + intern/boolop/intern/BOP_Interface.cpp | 30 +- intern/boolop/intern/BOP_Merge.cpp | 3 + intern/boolop/intern/BOP_Merge.h | 5 + intern/boolop/intern/BOP_Merge2.cpp | 944 +++++++++++++++++++++++++ intern/boolop/intern/BOP_Merge2.h | 99 +++ intern/boolop/intern/BOP_Mesh.cpp | 7 + intern/boolop/intern/BOP_Misc.h | 11 + intern/boolop/intern/BOP_Tag.h | 2 +- 10 files changed, 1135 insertions(+), 2 deletions(-) create mode 100644 intern/boolop/intern/BOP_Merge2.cpp create mode 100644 intern/boolop/intern/BOP_Merge2.h diff --git a/intern/boolop/intern/BOP_Edge.cpp b/intern/boolop/intern/BOP_Edge.cpp index dc6222fcd4e..44e7d5cb567 100644 --- a/intern/boolop/intern/BOP_Edge.cpp +++ b/intern/boolop/intern/BOP_Edge.cpp @@ -75,6 +75,28 @@ void BOP_Edge::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex) else if (m_vertexs[1] == oldIndex) m_vertexs[1] = newIndex; } +#ifdef BOP_NEW_MERGE + +/** + * Returns if this edge contains the specified face index. + * @param i face index + * @return true if this edge contains the specified face index, false otherwise + */ +bool BOP_Edge::removeFace(BOP_Index i) +{ + int pos=0; + for(BOP_IT_Indexs it = m_faces.begin();it!=m_faces.end();pos++,it++) { + if ((*it) == i) { + m_faces.erase(it); + return true; + } + } + + return false; +} + +#endif + #ifdef BOP_DEBUG #include @@ -86,6 +108,12 @@ using namespace std; ostream &operator<<(ostream &stream, BOP_Edge *e) { stream << "Edge[" << e->getVertex1() << "," << e->getVertex2(); +#ifdef BOP_NEW_MERGE + if(e->m_used) + stream << "] (used)"; + else + stream << "] (unused)"; +#endif return stream; } #endif diff --git a/intern/boolop/intern/BOP_Edge.h b/intern/boolop/intern/BOP_Edge.h index fb352620c17..a817b3d624f 100644 --- a/intern/boolop/intern/BOP_Edge.h +++ b/intern/boolop/intern/BOP_Edge.h @@ -36,6 +36,9 @@ class BOP_Edge private: BOP_Index m_vertexs[2]; BOP_Indexs m_faces; +#ifdef BOP_NEW_MERGE + bool m_used; +#endif bool containsFace(BOP_Index i); @@ -48,6 +51,11 @@ public: inline unsigned int getNumFaces(){return m_faces.size();}; inline BOP_Indexs &getFaces(){return m_faces;}; void addFace(BOP_Index face); +#ifdef BOP_NEW_MERGE + bool removeFace(BOP_Index i); + bool getUsed() { return m_used;}; + void setUsed(bool setting) { m_used=setting;}; +#endif #ifdef BOP_DEBUG friend ostream &operator<<(ostream &stream, BOP_Edge *e); #endif diff --git a/intern/boolop/intern/BOP_Interface.cpp b/intern/boolop/intern/BOP_Interface.cpp index 2a198103931..898ca708204 100644 --- a/intern/boolop/intern/BOP_Interface.cpp +++ b/intern/boolop/intern/BOP_Interface.cpp @@ -33,9 +33,12 @@ #include "BOP_Mesh.h" #include "BOP_Face2Face.h" #include "BOP_Merge.h" +#include "BOP_Merge2.h" #include "BOP_Chrono.h" -//#define DEBUG +#if defined(BOP_ORIG_MERGE) && defined(BOP_NEW_MERGE) +#include "../../source/blender/blenkernel/BKE_global.h" +#endif BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC, BOP_Faces* facesA, @@ -208,7 +211,32 @@ BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC, #endif // Merge faces +#ifdef BOP_ORIG_MERGE +#ifndef BOP_NEW_MERGE BOP_Merge::getInstance().mergeFaces(meshC,numVertices); +#endif +#endif + +#ifdef BOP_NEW_MERGE +#ifndef BOP_ORIG_MERGE + BOP_Merge2::getInstance().mergeFaces(meshC,numVertices); +#else + static int state = -1; + if (G.rt == 100) { + if( state != 1 ) { + cout << "Boolean code using old merge technique." << endl; + state = 1; + } + BOP_Merge::getInstance().mergeFaces(meshC,numVertices); + } else { + if( state != 0 ) { + cout << "Boolean code using new merge technique." << endl; + state = 0; + } + BOP_Merge2::getInstance().mergeFaces(meshC,numVertices); + } +#endif +#endif #ifdef DEBUG c = chrono.stamp(); t += c; diff --git a/intern/boolop/intern/BOP_Merge.cpp b/intern/boolop/intern/BOP_Merge.cpp index 1e4139ab971..012d3409187 100644 --- a/intern/boolop/intern/BOP_Merge.cpp +++ b/intern/boolop/intern/BOP_Merge.cpp @@ -30,6 +30,7 @@ #include "BOP_Merge.h" +#ifdef BOP_ORIG_MERGE #ifdef _MSC_VER #if _MSC_VER < 1300 @@ -802,3 +803,5 @@ void BOP_Merge::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, B } } } + +#endif /* BOP_ORIG_MERGE */ diff --git a/intern/boolop/intern/BOP_Merge.h b/intern/boolop/intern/BOP_Merge.h index 88999b2e734..ceb8ec10690 100644 --- a/intern/boolop/intern/BOP_Merge.h +++ b/intern/boolop/intern/BOP_Merge.h @@ -28,6 +28,9 @@ #ifndef BOP_MERGE_H #define BOP_MERGE_H +#include "BOP_Misc.h" + +#ifdef BOP_ORIG_MERGE #include "BOP_Mesh.h" #include "BOP_Tag.h" #include "BOP_MathUtils.h" @@ -68,4 +71,6 @@ class BOP_Merge { void mergeFaces(BOP_Mesh *m, BOP_Index v); }; +#endif /* BOP_ORIG_MERGE */ + #endif diff --git a/intern/boolop/intern/BOP_Merge2.cpp b/intern/boolop/intern/BOP_Merge2.cpp new file mode 100644 index 00000000000..bbf3f8ba702 --- /dev/null +++ b/intern/boolop/intern/BOP_Merge2.cpp @@ -0,0 +1,944 @@ +/** + * + * $Id: BOP_Merge22.cpp 14444 2008-04-16 22:40:48Z hos $ + * + * ***** 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): Marc Freixas, Ken Hughes + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "BOP_Merge2.h" + +#ifdef BOP_NEW_MERGE + +static void deleteFace(BOP_Mesh *m, BOP_Face *face); + +/** + * SINGLETON (use method BOP_Merge2.getInstance). + */ +BOP_Merge2 BOP_Merge2::SINGLETON; + +#ifdef BOP_DEBUG +void dumpmesh ( BOP_Mesh *m, bool force ) +{ + unsigned int nonmanifold = 0; + { + BOP_Edges edges = m->getEdges(); + int count = 0; + for (BOP_IT_Edges edge = edges.begin(); edge != edges.end(); + ++count, ++edge) { + if (!(*edge)->getUsed() && (*edge)->getFaces().size() == 0 ) continue; + BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1()); + BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2()); + + if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) { + int fcount = 0; + BOP_Indexs faces = (*edge)->getFaces(); + for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) { + BOP_Face *f = m->getFace(*face); + if(f->getTAG()== UNCLASSIFIED) ++fcount; + } + + + if(fcount !=0 && fcount !=2 ) { + ++nonmanifold; + } + } + } + if (!force && nonmanifold == 0) return; + } + if( nonmanifold ) + cout << nonmanifold << " edges detected" << endl; +#ifdef DEBUG + cout << "---------------------------" << endl; + + BOP_Edges edges = m->getEdges(); + int count = 0; + for (BOP_IT_Edges edge = edges.begin(); edge != edges.end(); + ++count, ++edge) { + BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1()); + BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2()); + + if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) { + int fcount = 0; + BOP_Indexs faces = (*edge)->getFaces(); + cout << count << ", " << (*edge) << ", " << faces.size() << endl; + for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) { + BOP_Face *f = m->getFace(*face); + if(f->getTAG()== UNCLASSIFIED) ++fcount; + cout << " face " << f << endl; + } + + + if(fcount !=0 && fcount !=2 ) + cout << " NON-MANIFOLD" << endl; + } + } + + BOP_Faces faces = m->getFaces(); + count = 0; + for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) { + if( count < 12*2 || (*face)->getTAG() != BROKEN ) { + cout << count << ", " << *face << endl; + } + ++count; + } + + BOP_Vertexs verts = m->getVertexs(); + count = 0; + for (BOP_IT_Vertexs vert = verts.begin(); vert != verts.end(); vert++) { + cout << count++ << ", " << *vert << " " << (*vert)->getNumEdges() << endl; + BOP_Indexs edges = (*vert)->getEdges(); + for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) { + BOP_Edge *edge = m->getEdge(*it); + cout << " " << edge << endl; + } + } + cout << "===========================" << endl; +#endif +} +#endif + +/** + * Simplifies a mesh, merging its faces. + * @param m mesh + * @param v index of the first mergeable vertex (can be removed by merge) + */ + +void BOP_Merge2::mergeFaces(BOP_Mesh *m, BOP_Index v) +{ + m_mesh = m; + +#ifdef DEBUG + cout << "##############################" << endl; +#endif + cleanup( ); + + m_firstVertex = v; + bool cont = false; + + // Merge faces + mergeFaces(); + + do { + // Add quads ... + cont = createQuads(); + // ... and merge new faces + if( cont ) cont = mergeFaces(); + +#ifdef DEBUG + cout << "called mergeFaces " << cont << endl; +#endif + // ... until the merge is not succesful + } while(cont); +} + +void clean_nonmanifold( BOP_Mesh *m ) +{ + return; + + BOP_Edges nme; + BOP_Edges e = m->getEdges(); + for( BOP_IT_Edges it = e.begin(); it != e.end(); ++it ) { + BOP_Indexs faces = (*it)->getFaces(); + if( faces.size() & ~2 ) + nme.push_back(*it); + } + if (nme.size() == 0) return; + for( BOP_IT_Edges it = nme.begin(); it != nme.end(); ++it ) { + if( (*it)->getFaces().size() > 1 ) { + BOP_Indexs faces = (*it)->getFaces(); + for( BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face ) { + MT_Point3 vertex1 = m->getVertex(m->getFace(*face)->getVertex(0))->getPoint(); + MT_Point3 vertex2 = m->getVertex(m->getFace(*face)->getVertex(1))->getPoint(); + MT_Point3 vertex3 = m->getVertex(m->getFace(*face)->getVertex(2))->getPoint(); + if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle + deleteFace(m,m->getFace(*face)); + } + continue; + } + BOP_Face *oface1 = m->getFace((*it)->getFaces().front()); + BOP_Face *oface2, *tmpface; + BOP_Index first =(*it)->getVertex1(); + BOP_Index next =(*it)->getVertex2(); + BOP_Index last = first; + unsigned short facecount = 0; + bool found = false; + BOP_Indexs vertList; +#ifdef DEBUG + cout << " first edge is " << (*it) << endl; +#endif + vertList.push_back(first); + BOP_Edge *edge; + while(true) { + BOP_Vertex *vert = m->getVertex(next); + BOP_Indexs edges = vert->getEdges(); + edge = NULL; + for( BOP_IT_Indexs eit = edges.begin(); eit != edges.end(); ++eit) { + edge = m->getEdge(*eit); + if( edge->getFaces().size() > 1) { + edge = NULL; + continue; + } + if( edge->getVertex1() == next && edge->getVertex2() != last ) { + last = next; + next = edge->getVertex2(); + break; + } + if( edge->getVertex2() == next && edge->getVertex1() != last ) { + last = next; + next = edge->getVertex1(); + break; + } + edge = NULL; + } + if( !edge ) break; +#ifdef DEBUG + cout << " next edge is " << edge << endl; +#endif + tmpface = m->getFace(edge->getFaces().front()); + if( oface1->getOriginalFace() != tmpface->getOriginalFace() ) + oface2 = tmpface; + else + ++facecount; + vertList.push_back(last); + if( vertList.size() > 3 ) break; + if( next == first ) { + found = true; + break; + } + } + if(found) { + edge = *it; +#ifdef DEBUG + cout << " --> found a loop" << endl; +#endif + if( vertList.size() == 3 ) { + BOP_Face3 *face = (BOP_Face3 *)m->getFace(edge->getFaces().front()); + face->getNeighbours(first,last,next); + } else if( vertList.size() == 4 ) { + BOP_Face4 *face = (BOP_Face4 *)m->getFace(edge->getFaces().front()); + face->getNeighbours(first,last,next,last); + } else { +#ifdef DEBUG + cout << "loop has " << vertList.size() << "verts"; +#endif + continue; + } + if(facecount == 1) oface1 = oface2; + next = vertList[1]; + last = vertList[2]; + if( edge->getVertex2() == next ) { + BOP_Face3 *f = new BOP_Face3(next,first,last, + oface1->getPlane(),oface1->getOriginalFace()); + m->addFace( f ); +#ifdef DEBUG + cout << " face is backward: " << f << endl; +#endif + + } else { + BOP_Face3 *f = new BOP_Face3(last,first,next, + oface1->getPlane(),oface1->getOriginalFace()); + m->addFace( f ); +#ifdef DEBUG + cout << " face is forward: " << f << endl; +#endif + } + } + } +} + +/** + * Runs through mesh and makes sure vert/face/edge data is consistent. Most + * importantly: + * (1) mark edges which are no longer used + * (2) remove broken faces from edges + * (3) remove faces from mesh which have a single edge belonging to no other + * face (non-manifold edges) + */ + +void BOP_Merge2::cleanup( void ) +{ + BOP_Edges edges = m_mesh->getEdges(); + for (BOP_IT_Edges edge = edges.begin(); edge != edges.end(); ++edge) { + BOP_Indexs faces = (*edge)->getFaces(); + for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face) { + BOP_Face *f = m_mesh->getFace(*face); + if(f->getTAG()== UNCLASSIFIED) ; + else (*edge)->removeFace(*face); + } + if( (*edge)->getFaces().size() == 0) (*edge)->setUsed(false); + } + + BOP_Vertexs v = m_mesh->getVertexs(); + for( BOP_IT_Vertexs it = v.begin(); it != v.end(); ++it ) { + if( (*it)->getTAG() != BROKEN) { + BOP_Indexs edges = (*it)->getEdges(); + for(BOP_IT_Indexs i = edges.begin();i!=edges.end();i++) + if( m_mesh->getEdge((*i))->getUsed( ) == false) (*it)->removeEdge( *i ); + if( (*it)->getEdges().size() == 0 ) (*it)->setTAG(BROKEN); + } + } + // clean_nonmanifold( m_mesh ); +} + +/** + * Simplifies a mesh, merging its faces. + */ +bool BOP_Merge2::mergeFaces() +{ + BOP_Indexs mergeVertices; + BOP_Vertexs vertices = m_mesh->getVertexs(); + BOP_IT_Vertexs v = vertices.begin(); + const BOP_IT_Vertexs verticesEnd = vertices.end(); + + // Advance to first mergeable vertex + advance(v,m_firstVertex); + BOP_Index pos = m_firstVertex; + + // Add unbroken vertices to the list + while(v!=verticesEnd) { + if ((*v)->getTAG() != BROKEN) { + mergeVertices.push_back(pos); + } + + v++; + pos++; + } + + // Merge faces with that vertices + return mergeFaces(mergeVertices); +} + +/** + * remove edges from vertices when the vertex is removed + */ +void BOP_Merge2::freeVerts(BOP_Index v, BOP_Vertex *vert) +{ + BOP_Indexs edges = vert->getEdges(); + BOP_Vertex *other; + + for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) { + BOP_Edge *edge = m_mesh->getEdge(*it); + BOP_Indexs edges2; + if( edge->getVertex1() != v ) + other = m_mesh->getVertex( edge->getVertex1() ); + else + other = m_mesh->getVertex( edge->getVertex2() ); + other->removeEdge(*it); + vert->removeEdge(*it); + } +} + +/** + * Simplifies a mesh, merging the faces with the specified vertices. + * @param mergeVertices vertices to test + * @return true if a face merge was performed + */ +bool BOP_Merge2::mergeFaces(BOP_Indexs &mergeVertices) +{ + // Check size > 0! + if (mergeVertices.size() == 0) return false; + bool didMerge = false; + + for( BOP_Index i = 0; i < mergeVertices.size(); ++i ) { + BOP_LFaces facesByOriginalFace; + BOP_Index v = mergeVertices[i]; + BOP_Vertex *vert = m_mesh->getVertex(v); +#ifdef DEBUG + cout << "i = " << i << ", v = " << v << ", vert = " << vert << endl; + if (v==48) + cout << "found vert 48" << endl; +#endif + if ( vert->getTAG() != BROKEN ) { + getFaces(facesByOriginalFace,v); + + switch (facesByOriginalFace.size()) { + case 0: + // v has no unbroken faces (so it's a new BROKEN vertex) + freeVerts( v, vert ); + vert->setTAG(BROKEN); + break; + case 2: { +#ifdef DEBUG + cout << "size of fBOF = " << facesByOriginalFace.size() << endl; +#endif + BOP_Faces ff = facesByOriginalFace.front(); + BOP_Faces fb = facesByOriginalFace.back(); + BOP_Index eindexs[2]; + int ecount = 0; + + // look for two edges adjacent to v which contain both ofaces + BOP_Indexs edges = vert->getEdges(); +#ifdef DEBUG + cout << " ff has " << ff.size() << " faces" << endl; + cout << " fb has " << fb.size() << " faces" << endl; + cout << " v has " << edges.size() << " edges" << endl; +#endif + for(BOP_IT_Indexs it = edges.begin(); it != edges.end(); + ++it ) { + BOP_Edge *edge = m_mesh->getEdge(*it); + BOP_Indexs faces = edge->getFaces(); +#ifdef DEBUG + cout << " " << edge << " has " << edge->getFaces().size() << " faces" << endl; +#endif + if( faces.size() == 2 ) { + BOP_Face *f0 = m_mesh->getFace(faces[0]); + BOP_Face *f1 = m_mesh->getFace(faces[1]); + if( f0->getOriginalFace() != f1->getOriginalFace() ) { +#ifdef DEBUG + cout << " " << f0 << endl; + cout << " " << f1 << endl; +#endif + eindexs[ecount++] = (*it); + } + } + } + if(ecount == 2) { +#ifdef DEBUG + cout << " edge indexes are " << eindexs[0]; + cout << " and " << eindexs[1] << endl; +#endif + BOP_Edge *edge = m_mesh->getEdge(eindexs[0]); + BOP_Index N = edge->getVertex1(); + if(N == v) N = edge->getVertex2(); +#ifdef DEBUG + cout << " ## OK, replace "<setTAG(BROKEN); + for(BOP_IT_Indexs it = edges.begin(); it != edges.end(); + ++it ) { + BOP_Edge *edge = m_mesh->getEdge(*it); + edge->setUsed(false); + } + didMerge = true; + } +#ifdef DEBUG + else { + cout << " HUH: ecount was " << ecount << endl; + } +#endif + } + break; + default: + break; + } + } + } + + return didMerge; +} + +void BOP_Merge2::mergeVertex(BOP_Faces &faces, BOP_Index v1, BOP_Index v2) +{ + for(BOP_IT_Faces face=faces.begin();face!=faces.end();face++) { + if( (*face)->size() == 3) + mergeVertex((BOP_Face3 *) *face, v1, v2); + else + mergeVertex((BOP_Face4 *) *face, v1, v2); + (*face)->setTAG(BROKEN); +#ifdef DEBUG + cout << " breaking " << (*face) << endl; +#endif + } +} + +/* + * Remove a face from the mesh and from each edges's face list + */ + +static void deleteFace(BOP_Mesh *m, BOP_Face *face) +{ + BOP_Index l2 = face->getVertex(0); + BOP_Faces faces = m->getFaces(); + for(int i = face->size(); i-- ; ) { + BOP_Indexs edges = m->getVertex(l2)->getEdges(); + BOP_Index l1 = face->getVertex(i); + for(BOP_IT_Indexs it1 = edges.begin(); it1 != edges.end(); ++it1 ) { + BOP_Edge *edge = m->getEdge(*it1); + if( ( edge->getVertex1() == l1 && edge->getVertex2() == l2 ) || + ( edge->getVertex1() == l2 && edge->getVertex2() == l1 ) ) { + BOP_Indexs ef = edge->getFaces(); + for(BOP_IT_Indexs it = ef.begin(); it != ef.end(); ++it ) { + if( m->getFace(*it) == face) { + edge->removeFace(*it); + break; + } + } + break; + } + } + l2 = l1; + } + face->setTAG(BROKEN); +} + +void BOP_Merge2::mergeVertex(BOP_Face3 *face, BOP_Index v1, BOP_Index v2) +{ + BOP_Index next, prev; + face->getNeighbours(v1,prev,next); + + // if new vertex is not already in the tri, make a new tri + if( prev != v2 && next != v2 ) { + m_mesh->addFace( new BOP_Face3(prev,v2,next, + face->getPlane(),face->getOriginalFace()) ); +#ifdef DEBUG + cout << "mv3: add " << prev << "," << v2 << "," << next << endl; + } else { + cout << "mv3: vertex already in tri: doing nothing" << endl; +#endif + } + deleteFace(m_mesh, face); +} + +void BOP_Merge2::mergeVertex(BOP_Face4 *face, BOP_Index v1, BOP_Index v2) +{ + BOP_Index next, prev, opp; + face->getNeighbours(v1,prev,next,opp); + + // if new vertex is already in the quad, replace quad with new tri + if( prev == v2 || next == v2 ) { + m_mesh->addFace( new BOP_Face3(prev,next,opp, + face->getPlane(),face->getOriginalFace()) ); +#ifdef DEBUG + cout << "mv4a: add " << prev << "," << next << "," << opp << endl; +#endif + } + // otherwise make a new quad + else { + m_mesh->addFace( new BOP_Face4(prev,v2,next,opp, + face->getPlane(),face->getOriginalFace()) ); +#ifdef DEBUG + cout << "mv4b: add "<getFaces(); + + // Merge mesh triangles + const BOP_IT_Faces facesIEnd = (faces.end()-1); + const BOP_IT_Faces facesJEnd = faces.end(); + for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) { +#ifdef OLD_QUAD + if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue; + for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { + if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 || + (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; + + + BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ); + if (faceK != NULL) { + // Set triangles to BROKEN + deleteFace(m_mesh, *faceI); + deleteFace(m_mesh, *faceJ); +#ifdef DEBUG + cout << "createQuad: del " << *faceI << endl; + cout << "createQuad: del " << *faceJ << endl; + cout << "createQuad: add " << faceK << endl; +#endif + quads.push_back(faceK); + break; + } + } +#else + if ((*faceI)->getTAG() == BROKEN ) continue; + for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { + if ((*faceJ)->getTAG() == BROKEN || + (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; + + BOP_Face *faceK = NULL; + if((*faceI)->size() == 3) { + if((*faceJ)->size() == 3) + faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ); + else + faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face4*)*faceJ); + } else { + if((*faceJ)->size() == 3) + faceK = createQuad((BOP_Face3*)*faceJ,(BOP_Face4*)*faceI); + else + faceK = createQuad((BOP_Face4*)*faceI,(BOP_Face4*)*faceJ); + } + + if (faceK != NULL) { + // Set triangles to BROKEN + deleteFace(m_mesh, *faceI); + deleteFace(m_mesh, *faceJ); +#ifdef DEBUG + cout << "createQuad: del " << *faceI << endl; + cout << "createQuad: del " << *faceJ << endl; + cout << "createQuad: add " << faceK << endl; +#endif + quads.push_back(faceK); + break; + } + } +#endif + } + + // Add quads to mesh + const BOP_IT_Faces quadsEnd = quads.end(); + for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad); + return (quads.size() > 0); +} + +/** + * Returns a new quad (convex) from the merge of two triangles that share the + * vertex index v. + * @param faceI mesh triangle + * @param faceJ mesh triangle + * @param v vertex index shared by both triangles + * @return a new convex quad if the merge is possible + */ +BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ) +{ + // Test if both triangles share a vertex index + BOP_Index v; + unsigned int i; + for(i=0;i<3 ;i++) { + v = faceI->getVertex(i); + if( faceJ->containsVertex(v) ) break; + } + if (i == 3) return NULL; + + BOP_Face *faceK = NULL; + + // Get faces data + BOP_Index prevI, nextI, prevJ, nextJ; + faceI->getNeighbours(v,prevI,nextI); + faceJ->getNeighbours(v,prevJ,nextJ); + MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); + MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); + MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); + MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); + MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); + + // Quad test + if (prevI == nextJ) { + if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) && + BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) { + faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace()); + faceK->setTAG(faceI->getTAG()); + BOP_Index edge; + m_mesh->getIndexEdge(v,prevI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + } + } + else if (nextI == prevJ) { + if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) && + BOP_convex(vertex,vNextJ,vNextI,vPrevI)) { + faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace()); + faceK->setTAG(faceI->getTAG()); + BOP_Index edge; + m_mesh->getIndexEdge(v,nextI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + } + } + return faceK; +} + +/** + * Returns a new quad (convex) from the merge of two triangles that share the + * vertex index v. + * @param faceI mesh triangle + * @param faceJ mesh triangle + * @param v vertex index shared by both triangles + * @return a new convex quad if the merge is possible + */ +BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face4 *faceJ) +{ + // Test if triangle and quad share a vertex index + BOP_Index v; + unsigned int i; + for(i=0;i<3 ;i++) { + v = faceI->getVertex(i); + if( faceJ->containsVertex(v) ) break; + } + if (i == 3) return NULL; + + BOP_Face *faceK = NULL; + + // Get faces data + BOP_Index prevI, nextI, prevJ, nextJ, oppJ; + faceI->getNeighbours(v,prevI,nextI); + faceJ->getNeighbours(v,prevJ,nextJ,oppJ); + + // Quad test + BOP_Index edge; + if (nextI == prevJ) { + if (prevI == nextJ) { // v is in center + faceK = new BOP_Face3(nextJ,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace()); + faceK->setTAG(faceI->getTAG()); + m_mesh->getIndexEdge(v,prevI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + m_mesh->getIndexEdge(v,nextI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + freeVerts(v, m_mesh->getVertex(v)); + } else if (prevI == oppJ) { // nextI is in center + faceK = new BOP_Face3(v,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace()); + faceK->setTAG(faceI->getTAG()); + m_mesh->getIndexEdge(v,nextI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + m_mesh->getIndexEdge(prevI,nextI,edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + freeVerts(nextI, m_mesh->getVertex(nextI)); + } + } else if (nextI == oppJ && prevI == nextJ ) { // prevI is in center + faceK = new BOP_Face3(prevJ,v,oppJ,faceI->getPlane(),faceI->getOriginalFace()); + faceK->setTAG(faceI->getTAG()); + m_mesh->getIndexEdge(v,prevI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + m_mesh->getIndexEdge(nextI,prevI,edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + freeVerts(prevI, m_mesh->getVertex(prevI)); + } + return faceK; +} + +/** + * Returns a new quad (convex) from the merge of two triangles that share the + * vertex index v. + * @param faceI mesh triangle + * @param faceJ mesh triangle + * @param v vertex index shared by both triangles + * @return a new convex quad if the merge is possible + */ +BOP_Face* BOP_Merge2::createQuad(BOP_Face4 *faceI, BOP_Face4 *faceJ) +{ + BOP_Face *faceK = NULL; + // + // Test if both quads share a vertex index + // + BOP_Index v; + unsigned int i; + for(i=0;i<4 ;i++) { + v = faceI->getVertex(i); + if( faceJ->containsVertex(v) ) break; + } + if (i == 3) return NULL; + + + // Get faces data + BOP_Index prevI, nextI, oppI, prevJ, nextJ, oppJ; + faceI->getNeighbours(v,prevI,nextI,oppI); + faceJ->getNeighbours(v,prevJ,nextJ,oppJ); + + // Quad test + BOP_Index edge; + if (nextI == prevJ) { + if (prevI == nextJ) { // v is in center + faceK = new BOP_Face4(nextI,oppI,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace()); + faceK->setTAG(faceI->getTAG()); + m_mesh->getIndexEdge(v,prevI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + m_mesh->getIndexEdge(v,nextI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + freeVerts(v, m_mesh->getVertex(v)); + } else if (oppI == oppJ) { // nextI is in center + faceK = new BOP_Face4(v,nextJ,oppJ,prevI,faceI->getPlane(),faceI->getOriginalFace()); + faceK->setTAG(faceI->getTAG()); + m_mesh->getIndexEdge(v,nextI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + m_mesh->getIndexEdge(prevI,nextI,edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + freeVerts(nextI, m_mesh->getVertex(nextI)); + } + } else if (prevI == nextJ && oppI == oppJ) { // prevI is in center + faceK = new BOP_Face4(v,nextI,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace()); + faceK->setTAG(faceI->getTAG()); + m_mesh->getIndexEdge(v,prevI,edge); + m_mesh->getVertex(v)->removeEdge(edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + m_mesh->getIndexEdge(nextI,prevI,edge); + m_mesh->getVertex(nextI)->removeEdge(edge); + m_mesh->getVertex(prevI)->removeEdge(edge); + freeVerts(prevI, m_mesh->getVertex(prevI)); + } + return faceK; +} + +/** + * Returns if a index is inside a set of indexs. + * @param indexs set of indexs + * @param i index + * @return true if the index is inside the set, false otherwise + */ +bool BOP_Merge2::containsIndex(BOP_Indexs indexs, BOP_Index i) +{ + const BOP_IT_Indexs indexsEnd = indexs.end(); + for(BOP_IT_Indexs it=indexs.begin();it!=indexsEnd;it++) { + if (*it == i) return true; + } + return false; +} + +/** + * Creates a list of lists L1, L2, ... LN where + * LX = mesh faces with vertex v that come from the same original face + * @param facesByOriginalFace list of faces lists + * @param v vertex index + */ +void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v) +{ + // Get edges with vertex v + + BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges(); + const BOP_IT_Indexs edgeEnd = edgeIndexs.end(); + for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) { + // For each edge, add its no broken faces to the output list + BOP_Edge* edge = m_mesh->getEdge(*edgeIndex); + BOP_Indexs faceIndexs = edge->getFaces(); + const BOP_IT_Indexs faceEnd = faceIndexs.end(); + for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) { + BOP_Face* face = m_mesh->getFace(*faceIndex); + if (face->getTAG() != BROKEN) { + bool found = false; + // Search if we already have created a list for the + // faces that come from the same original face + const BOP_IT_LFaces lfEnd = facesByOriginalFace.end(); + for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin(); + facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) { + if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) { + // Search that the face has not been added to the list before + for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) { + if ((*facesByOriginalFaceX)[i] == face) { + found = true; + break; + } + } + if (!found) { + // Add the face to the list + if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face); + else facesByOriginalFaceX->push_back(face); + found = true; + } + break; + } + } + if (!found) { + // Create a new list and add the current face + BOP_Faces facesByOriginalFaceX; + facesByOriginalFaceX.push_back(face); + facesByOriginalFace.push_back(facesByOriginalFaceX); + } + } + } + } +} + +/** + * Creates a list of lists L1, L2, ... LN where + * LX = mesh faces with vertex v that come from the same original face + * and without any of the vertices that appear before v in vertices + * @param facesByOriginalFace list of faces lists + * @param vertices vector with vertices indexs that contains v + * @param v vertex index + */ +void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v) +{ + // Get edges with vertex v + BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges(); + const BOP_IT_Indexs edgeEnd = edgeIndexs.end(); + for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) { + // Foreach edge, add its no broken faces to the output list + BOP_Edge* edge = m_mesh->getEdge(*edgeIndex); + BOP_Indexs faceIndexs = edge->getFaces(); + const BOP_IT_Indexs faceEnd = faceIndexs.end(); + for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) { + BOP_Face* face = m_mesh->getFace(*faceIndex); + if (face->getTAG() != BROKEN) { + // Search if the face contains any of the forbidden vertices + bool found = false; + for(BOP_IT_Indexs vertex = vertices.begin();*vertex!= v;vertex++) { + if (face->containsVertex(*vertex)) { + // face contains a forbidden vertex! + found = true; + break; + } + } + if (!found) { + // Search if we already have created a list with the + // faces that come from the same original face + const BOP_IT_LFaces lfEnd = facesByOriginalFace.end(); + for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin(); + facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) { + if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) { + // Search that the face has not been added to the list before + for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) { + if ((*facesByOriginalFaceX)[i] == face) { + found = true; + break; + } + } + if (!found) { + // Add face to the list + if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face); + else facesByOriginalFaceX->push_back(face); + found = true; + } + break; + } + } + if (!found) { + // Create a new list and add the current face + BOP_Faces facesByOriginalFaceX; + facesByOriginalFaceX.push_back(face); + facesByOriginalFace.push_back(facesByOriginalFaceX); + } + } + } + } + } +} + +#endif /* BOP_NEW_MERGE */ diff --git a/intern/boolop/intern/BOP_Merge2.h b/intern/boolop/intern/BOP_Merge2.h new file mode 100644 index 00000000000..1e5945a889f --- /dev/null +++ b/intern/boolop/intern/BOP_Merge2.h @@ -0,0 +1,99 @@ +/** + * ***** 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 BOP_MERGE2_H +#define BOP_MERGE2_H + +#include "BOP_Misc.h" + +#ifdef BOP_NEW_MERGE + +#include "BOP_Mesh.h" +#include "BOP_Tag.h" +#include "BOP_MathUtils.h" +#include "MEM_SmartPtr.h" + +typedef vector< BOP_Faces > BOP_LFaces; +typedef vector< BOP_Faces >::iterator BOP_IT_LFaces; + +class BOP_Merge2 { + private: + BOP_Mesh* m_mesh; + BOP_Index m_firstVertex; + static BOP_Merge2 SINGLETON; + + BOP_Merge2() {}; + bool mergeFaces(); + bool mergeFaces(BOP_Indexs &mergeVertices); + bool mergeFaces(BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v); + bool mergeFaces(BOP_Faces &faces, BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v); + BOP_Face *mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v); + BOP_Face *mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Indexs &pending, BOP_Index v); + BOP_Face *mergeFaces(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v); + BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Index v); + BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Indexs &pending, BOP_Index v); + BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face4 *faceJ, BOP_Indexs &pending, BOP_Index v); + bool createQuads(); + bool containsIndex(BOP_Indexs indexs, BOP_Index index); + void getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v); + void getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v); + BOP_Face *createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ); + BOP_Face *createQuad(BOP_Face3 *faceI, BOP_Face4 *faceJ); + BOP_Face *createQuad(BOP_Face4 *faceI, BOP_Face4 *faceJ); + + bool mergeVertex(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v, + BOP_Indexs &mergeVertices); + bool mergeVertex(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v, + BOP_Indexs &pending, BOP_Faces &oldFaces, BOP_Faces &newFaces ); + BOP_Face *find3Neighbor(BOP_Face *faceI, BOP_Face *faceJ, + BOP_Index X, BOP_Index I, BOP_Index P, BOP_Index N ); + BOP_Face *find4Neighbor(BOP_Face *faceI, BOP_Face *faceJ, + BOP_Index X, BOP_Index I, BOP_Index P, BOP_Index N, + BOP_Face **faceL, BOP_Index &O); + BOP_Face3 *collapse(BOP_Face4 *faceC, BOP_Index X); + void mergeFaces(BOP_Face *A, BOP_Face *B, BOP_Index X, + BOP_Index I, BOP_Index N, BOP_Index P, BOP_Faces &newFaces ); + void freeVerts(BOP_Index v, BOP_Vertex *vert); + + void mergeVertex(BOP_Faces&, BOP_Index, BOP_Index); + void mergeVertex(BOP_Face3 *, BOP_Index, BOP_Index); + void mergeVertex(BOP_Face4 *, BOP_Index, BOP_Index); + void cleanup( void ); + + public: + + static BOP_Merge2 &getInstance() { + return SINGLETON; + } + + void mergeFaces(BOP_Mesh *m, BOP_Index v); +}; + +void dumpmesh(BOP_Mesh *, bool); + +#endif /* BOP_NEW_MERGE2 */ +#endif diff --git a/intern/boolop/intern/BOP_Mesh.cpp b/intern/boolop/intern/BOP_Mesh.cpp index 685478fae39..075884a1920 100644 --- a/intern/boolop/intern/BOP_Mesh.cpp +++ b/intern/boolop/intern/BOP_Mesh.cpp @@ -449,6 +449,13 @@ bool BOP_Mesh::getIndexEdge(BOP_Index v1, BOP_Index v2, BOP_Index &e) printf ("found edge (%d %d)\n",v1,v2); #endif e = edge->index; +#ifdef BOP_NEW_MERGE + if( m_edges[e]->getUsed() == false ) { + m_edges[e]->setUsed(true); + m_vertexs[v1]->addEdge(e); + m_vertexs[v2]->addEdge(e); + } +#endif return true; } #ifdef HASH_PRINTF_DEBUG diff --git a/intern/boolop/intern/BOP_Misc.h b/intern/boolop/intern/BOP_Misc.h index 0e009d8ee8d..d021579d161 100644 --- a/intern/boolop/intern/BOP_Misc.h +++ b/intern/boolop/intern/BOP_Misc.h @@ -41,3 +41,14 @@ #define HASH(x) ((x) >> 5) /* each "hash" covers 32 indices */ // #define HASH_PRINTF_DEBUG /* uncomment to enable debug output */ + +/* + * temporary: control which method is used to merge final triangles and + * quads back together after an operation. If both methods are included, + * the "rt" debugging button on the Scene panel (F10) is used to control + * which is active. Setting it to 100 enables the original method, any + * other value enables the new method. + */ + +#define BOP_ORIG_MERGE /* include original merge code */ +#define BOP_NEW_MERGE /* include new merge code */ diff --git a/intern/boolop/intern/BOP_Tag.h b/intern/boolop/intern/BOP_Tag.h index 705f4885866..ead10fa6040 100644 --- a/intern/boolop/intern/BOP_Tag.h +++ b/intern/boolop/intern/BOP_Tag.h @@ -39,7 +39,7 @@ #define OUTON_TAG 0x11 // Above and on the plane #define UNCLASSIFIED_TAG 0x0F // Expecting to be classified -#define PHANTOM_TAG 0x0C // Phantom face +#define PHANTOM_TAG 0x0C // Phantom face: verts form collinear triangle #define OVERLAPPED_TAG 0x0D // Overlapped face #define BROKEN_TAG 0x0B // Splitted and unused ... From 115dfb22ccd267f22b9980652acbf479c8b3ac5a Mon Sep 17 00:00:00 2001 From: Roland Hess Date: Fri, 1 Aug 2008 12:56:29 +0000 Subject: [PATCH 26/58] Ipo Editor would not allow access to either World or Lamp texture Ipos. Now it does. Fixes bug #17379. --- source/blender/blenkernel/BKE_texture.h | 1 + source/blender/blenkernel/intern/texture.c | 15 ++++++++++++++- source/blender/src/editipo.c | 11 ++++++++++- source/blender/src/header_ipo.c | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 78a8f60caeb..fade0f8cbaa 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -62,6 +62,7 @@ struct Tex *copy_texture(struct Tex *tex); void make_local_texture(struct Tex *tex); void autotexname(struct Tex *tex); struct Tex *give_current_texture(struct Object *ob, int act); +struct Tex *give_current_world_texture(void); struct TexMapping *add_mapping(void); void init_mapping(struct TexMapping *texmap); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 37804bf68ac..ad139220785 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -53,6 +53,7 @@ #include "DNA_world_types.h" #include "DNA_brush_types.h" #include "DNA_node_types.h" +#include "DNA_scene_types.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -731,7 +732,7 @@ Tex *give_current_texture(Object *ob, int act) bNode *node; if(ob==0) return 0; - if(ob->totcol==0) return 0; + if(ob->totcol==0 && !(ob->type==OB_LAMP)) return 0; if(ob->type==OB_LAMP) { la=(Lamp *)ob->data; @@ -775,6 +776,18 @@ Tex *give_current_texture(Object *ob, int act) return tex; } +Tex *give_current_world_texture(void) +{ + MTex *mtex = 0; + Tex *tex = 0; + + if(!(G.scene->world)) return 0; + + mtex= G.scene->world->mtex[(int)(G.scene->world->texact)]; + if(mtex) tex= mtex->tex; + + return tex; +} /* ------------------------------------------------------------------------- */ diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index c5dd41e16d5..63c301658f2 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -82,6 +82,7 @@ #include "BKE_group.h" #include "BKE_ipo.h" #include "BKE_key.h" +#include "BKE_main.h" #include "BKE_material.h" #include "BKE_particle.h" #include "BKE_texture.h" @@ -933,6 +934,9 @@ static void make_editipo(void) ob->ipowin= ID_TE; make_texture_editipo(G.sipo); } + else if(G.scene->world && give_current_world_texture()) { + make_texture_editipo(G.sipo); + } } else if(G.sipo->blocktype==ID_CA) { if (ob) { @@ -1120,6 +1124,11 @@ static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname *from= (ID *)tex; if(tex) *ipo= tex->ipo; } + else if(G.scene->world) { + Tex *tex= give_current_world_texture(); + *from= (ID *)tex; + if(tex) *ipo= tex->ipo; + } } else if(blocktype==ID_MA) { if(ob) { @@ -6002,4 +6011,4 @@ void move_to_frame(void) } } BIF_undo_push("Set frame to selected Ipo vertex"); -} +} \ No newline at end of file diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index 15caf325ec6..59d542e72ec 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -970,7 +970,7 @@ static char *ipo_modeselect_pup(void) if(ob && ob->type==OB_LAMP) str += sprintf(str,formatstring, "Lamp",ID_LA, ICON_LAMP); - if(ob && give_current_texture(ob, ob->actcol)) + if((ob && give_current_texture(ob, ob->actcol))||(give_current_world_texture())) str += sprintf(str,formatstring, "Texture",ID_TE, ICON_TEXTURE); if(ob){ From fc52146342bf2116db92f9b3b4d718178946986d Mon Sep 17 00:00:00 2001 From: Mal Duffin Date: Fri, 1 Aug 2008 21:12:47 +0000 Subject: [PATCH 27/58] --- source/blender/blenloader/intern/writefile.c | 2 +- source/blender/src/header_info.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 73abf362d12..3a70438dd13 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2275,7 +2275,7 @@ static int handle_append_runtime(int handle, char *exename, char **cause_r) { unsigned char buf[1024]; int count, progfd= -1; - if (!runtime) { + if (!BLI_exists(runtime)) { cause= "Unable to find runtime"; goto cleanup; } diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index dac7c7bc2c6..d972f4e6368 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -1078,9 +1078,9 @@ static uiBlock *info_filemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot Subwindow|Ctrl F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 24, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot All|Ctrl Shift F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 25, ""); #if GAMEBLENDER == 1 - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Game As Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, ""); #ifdef _WIN32 - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Dynamic Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 23, ""); +// uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Dynamic Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 23, ""); #endif #endif uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); From aa02e605f1eb4d34f6e7b62a0647d23f784de553 Mon Sep 17 00:00:00 2001 From: Mal Duffin Date: Fri, 1 Aug 2008 21:17:54 +0000 Subject: [PATCH 28/58] Fix for GE Make Runtime menu option Doh - I forgot to add a comment to the previous commit. This adds a file exists check for Make Dynamic Runtime for the GE. It also removes this menu option for now, as the required file ( blenderdynplayer.exe ) hasn't been included with the Blender app for quite a few releases ( therefore the feature has been broken ). I also renamed the option, to make it a bit more understandable. This might even be better moved to the Game menu, but I didn't want to do that ( yet :) ) --- source/blender/src/header_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index d972f4e6368..c14e88770f9 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -1080,7 +1080,7 @@ static uiBlock *info_filemenu(void *arg_unused) #if GAMEBLENDER == 1 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Game As Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, ""); #ifdef _WIN32 -// uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Dynamic Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 23, ""); +// uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Dynamic Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 23, ""); #endif #endif uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); From 451c00697f774cfcc8feb6881de8c3be229373f0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 2 Aug 2008 00:25:50 +0000 Subject: [PATCH 29/58] Scons - Mingw Compiling Fix: When using BF_SPLIT_SRCS as a hack to get some of the larger libs compiled, there were some problems linking Blender related to some boolean calls. This commit tweaks the priorities for the boolean libs for the 'intern' group so that they get linked before the src libs are. --- intern/boolop/SConscript | 2 +- intern/bsp/SConscript | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/boolop/SConscript b/intern/boolop/SConscript index a3f3c0b6433..bec263f251f 100644 --- a/intern/boolop/SConscript +++ b/intern/boolop/SConscript @@ -8,7 +8,7 @@ incs += ' ../../source/blender/makesdna ../../intern/guardedalloc' incs += ' ../../source/blender/blenlib' if (env['OURPLATFORM'] == 'win32-mingw'): - env.BlenderLib ('blender_bop', sources, Split(incs) , [], libtype=['common','intern'], priority = [5,50] ) + env.BlenderLib ('blender_bop', sources, Split(incs) , [], libtype=['common','intern'], priority = [30,85] ) else: env.BlenderLib ('blender_bop', sources, Split(incs) , [], libtype='common', priority = 5 ) diff --git a/intern/bsp/SConscript b/intern/bsp/SConscript index 88d2529ae59..39f278625a9 100644 --- a/intern/bsp/SConscript +++ b/intern/bsp/SConscript @@ -6,7 +6,7 @@ sources = env.Glob('intern/*.cpp') incs = 'intern ../container ../moto/include ../memutil' if (env['OURPLATFORM'] == 'win32-mingw'): - env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype=['common','intern'], priority=[26,26] ) + env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype=['common','intern'], priority=[26,69] ) else: env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype='core', priority=26 ) From b11790e08fc61dfc9fce017bde7d7c1ec6cb5f98 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Sat, 2 Aug 2008 06:11:35 +0000 Subject: [PATCH 30/58] * Minor tweaks to file menu item naming --- source/blender/src/header_info.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index c14e88770f9..6e264590082 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -1026,7 +1026,7 @@ static uiBlock *info_externalfiles(void *arg_unused) block= uiNewBlock(&curarea->uiblocks, "info_externalfiles", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); uiBlockSetButmFunc(block, do_info_externalfiles, NULL); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pack into Blend", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pack into .blend file", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, ""); #if 0 uiDefBut(block, BUTM, 1, "Unpack Data to current dir", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 2, "Removes all packed files from the project and saves them to the current directory"); #endif @@ -1036,8 +1036,8 @@ static uiBlock *info_externalfiles(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make all Paths Relative", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make all Paths Absolute", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 11, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Report Missing Files", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 12, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Missing Files", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 13, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Report Missing Files...", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 12, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Missing Files...", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 13, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); From 38aa350173f4e34f2cc2b32bd9c0c52bda31a987 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Sat, 2 Aug 2008 06:29:15 +0000 Subject: [PATCH 31/58] * (slightly modified) old patch #7471 from Davide Vercelli - menu items for Show All Layers/Show Previous layers in the 3D View. Sorry this took so long! --- source/blender/src/header_view3d.c | 15 +++++++++++++-- source/blender/src/toolbox.c | 9 ++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 0b48db461e6..4a7772fd10b 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -166,9 +166,9 @@ void do_layer_buttons(short event) if(event==-1 && (G.qual & LR_CTRLKEY)) { G.vd->scenelock= !G.vd->scenelock; do_view3d_buttons(B_SCENELOCK); - } else if (event==-1) { + } else if (event<0) { if(G.vd->lay== (1<<20)-1) { - if(G.qual & LR_SHIFTKEY) G.vd->lay= oldlay; + if(event==-2 || G.qual & LR_SHIFTKEY) G.vd->lay= oldlay; } else { oldlay= G.vd->lay; @@ -605,6 +605,9 @@ static void do_view3d_viewmenu(void *arg, int event) case 21: /* Grease Pencil */ add_blockhandler(curarea, VIEW3D_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW); break; + case 22: /* View all layers */ + do_layer_buttons(-2); + break; } allqueue(REDRAWVIEW3D, 1); } @@ -648,6 +651,11 @@ static uiBlock *view3d_viewmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + if(G.vd->lay== (1<<20)-1) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View Previous Layers|Shift ~", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 22, ""); + else uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show All Layers| ~", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 22, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + if(G.vd->localview) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); if(!G.vd->localview) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Global View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); @@ -726,6 +734,9 @@ void do_view3d_select_object_typemenu(void *arg, int event) case 10: /* Lamp */ selectall_type(OB_LAMP); break; + case 20: + do_layer_buttons(-2); + break; } allqueue(REDRAWVIEW3D, 0); } diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 94d38ee1635..8a8d7c8cec7 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -125,8 +125,6 @@ void asciitoraw(int ch, unsigned short *event, unsigned short *qual) { - if( isalpha(ch)==0 ) return; - if( isupper(ch) ) { *qual= LEFTSHIFTKEY; ch= tolower(ch); @@ -804,7 +802,10 @@ static void tb_do_hotkey(void *arg, int event) case 'd': key= PAGEDOWNKEY; break; } } - else asciitoraw(event, &key, &qual[3]); + else if (isalpha(event)) + asciitoraw(event, &key, &qual[3]); + else if (event == '~') + key = ACCENTGRAVEKEY; for (i=0;i<4;i++) { @@ -1213,6 +1214,8 @@ static TBitem tb_view[]= { { 0, "Ortho/Perspective|NumPad 5", TB_PAD|'5', NULL}, { 0, "Local/Global View|NumPad /", TB_PAD|'/', NULL}, { 0, "SEPR", 0, NULL}, +{ 0, "Show All Layers|Shift ~", TB_SHIFT|'~', NULL}, +{ 0, "SEPR", 0, NULL}, { 0, "Align View", 0, tb_view_alignview}, { 0, "SEPR", 0, NULL}, { 0, "View Selected|NumPad .", TB_PAD|'.', NULL}, From 82d87b2ab9d467ced67129c0fe602de2ca8c0b9c Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Sat, 2 Aug 2008 06:31:56 +0000 Subject: [PATCH 32/58] * patch #17394 by Vilem Novak - add menu item for 'Make Proxy Object'. Thanks! --- source/blender/src/header_view3d.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 4a7772fd10b..d834bd70321 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -651,7 +651,7 @@ static uiBlock *view3d_viewmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - if(G.vd->lay== (1<<20)-1) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View Previous Layers|Shift ~", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 22, ""); + if(G.vd->lay== (1<<20)-1) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Previous Layers|Shift ~", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 22, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show All Layers| ~", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 22, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -2478,8 +2478,11 @@ static void do_view3d_edit_objectmenu(void *arg, int event) case 15: /* Object Panel */ add_blockhandler(curarea, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW); break; + case 16: /* make proxy object*/ + make_proxy(); + break; #ifdef WITH_VERSE - case 16: /* Share Object at Verse server */ + case 17: /* Share Object at Verse server */ if(session_list.first != session_list.last) session = session_menu(); else session = session_list.first; if(session) b_verse_push_object(session, ob); @@ -2504,7 +2507,7 @@ static uiBlock *view3d_edit_objectmenu(void *arg_unused) if (base) ob= base->object; if(ob && (ob->type == OB_MESH) && (!ob->vnode)) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Share at Verse Server", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Share at Verse Server", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); } } @@ -2530,6 +2533,7 @@ static uiBlock *view3d_edit_objectmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Proxy|Ctrl Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, ""); uiDefIconTextBlockBut(block, view3d_edit_object_makelinksmenu, NULL, ICON_RIGHTARROW_THIN, "Make Links", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, view3d_edit_object_singleusermenu, NULL, ICON_RIGHTARROW_THIN, "Make Single User", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, view3d_edit_object_makelocalmenu, NULL, ICON_RIGHTARROW_THIN, "Make Local", 0, yco-=20, 120, 19, ""); From 341655eab72d4e77da8b7de8c1108daf06809118 Mon Sep 17 00:00:00 2001 From: Andrea Weikert Date: Sat, 2 Aug 2008 09:44:01 +0000 Subject: [PATCH 33/58] == imagebrowser == - HKEY now toggles hide/show dotfiles --- source/blender/src/editimasel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/src/editimasel.c b/source/blender/src/editimasel.c index 67e10d771e0..97ddc2e0f1d 100644 --- a/source/blender/src/editimasel.c +++ b/source/blender/src/editimasel.c @@ -1076,6 +1076,12 @@ void winqreadimaselspace(ScrArea *sa, void *spacedata, BWinEvent *evt) toggle_blockhandler(sa, IMASEL_HANDLER_IMAGE, UI_PNL_UNSTOW); scrarea_queue_winredraw(sa); break; + case HKEY: + simasel->flag ^= FILE_HIDE_DOT; + BIF_filelist_free(simasel->files); + do_draw= 1; + do_headdraw= 1; + break; case PKEY: if(G.qual & LR_SHIFTKEY) { extern char bprogname[]; /* usiblender.c */ From 03f9c6a3fc5968a4bfeff159341d47bf3b24d766 Mon Sep 17 00:00:00 2001 From: Mal Duffin Date: Sat, 2 Aug 2008 17:08:16 +0000 Subject: [PATCH 34/58] Copies all required DLLS for Save Game as Runtime. Under Windows, all DLLs are copied to the same folder as the runtime .EXE, so that the process becomes a single click and deploy solution. Linux doesn't require this ( thx for info centralnoise ) and will update to work on OS/X after I do a bit of research on .a and .so files ( thx for info kaito ). --- source/blender/src/header_info.c | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index 6e264590082..4e43819cb71 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -540,6 +540,40 @@ static void check_packAll() } } +static void copy_game_dll(char *dll_filename, char *source_dir, char *dest_dir) +{ + char source_filename[FILE_MAX]; + char dest_filename[FILE_MAX]; + + strcpy( source_filename, source_dir ); + strcat( source_filename, dll_filename ); + + strcpy( dest_filename, dest_dir ); + strcat( dest_filename, dll_filename ); + + if(!BLI_exists(dest_filename)) { + BLI_copy_fileops( source_filename, dest_filename ); + } +} + +static void copy_all_game_dlls(char *str) +{ +#define GAME_DLL_COUNT 7 + char *game_dll_list[GAME_DLL_COUNT]={"gnu_gettext.dll", "libpng.dll", "libtiff.dll", "pthreadVC2.dll", "python25.dll", "SDL.dll", "zlib.dll"}; + + char dest_dir[FILE_MAX]; + char source_dir[FILE_MAX]; + int i; + + strcpy(source_dir, get_install_dir()); + strcat(source_dir, "\\"); + BLI_split_dirfile_basic(str, dest_dir, NULL); + + for (i= 0; i< GAME_DLL_COUNT; i++) { + copy_game_dll(game_dll_list[i], source_dir, dest_dir ); + }; +} + static int write_runtime(char *str, char *exename) { char *freestr= NULL; @@ -587,7 +621,14 @@ static void write_runtime_check(char *str) #endif write_runtime(str, player); + +#ifdef _WIN32 + // get a list of the .DLLs in the Blender folder and copy all of these to the destination folder if they don't exist + copy_all_game_dlls(str); +#endif } + + /* end keyed functions */ /************************** MAIN MENU *****************************/ From e632b966ecf28e9db0be882f048fa6e903e63df8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 Aug 2008 21:39:01 +0000 Subject: [PATCH 35/58] BKE_global.h include path wasnt correct. made boxpack2d.c a bit more readable. no functionality changes. --- intern/boolop/intern/BOP_Interface.cpp | 2 +- source/blender/blenlib/intern/boxpack2d.c | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/intern/boolop/intern/BOP_Interface.cpp b/intern/boolop/intern/BOP_Interface.cpp index 898ca708204..c6bcb4a74ce 100644 --- a/intern/boolop/intern/BOP_Interface.cpp +++ b/intern/boolop/intern/BOP_Interface.cpp @@ -37,7 +37,7 @@ #include "BOP_Chrono.h" #if defined(BOP_ORIG_MERGE) && defined(BOP_NEW_MERGE) -#include "../../source/blender/blenkernel/BKE_global.h" +#include "../../../source/blender/blenkernel/BKE_global.h" #endif BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC, diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c index acd53e5d516..db7bae8a91d 100644 --- a/source/blender/blenlib/intern/boxpack2d.c +++ b/source/blender/blenlib/intern/boxpack2d.c @@ -42,6 +42,8 @@ #define TRF 2 #define TLF 4 #define BRF 8 +#define CORNERFLAGS (BLF|TRF|TLF|BRF) + #define BL 0 #define TR 1 #define TL 2 @@ -159,7 +161,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) vert->blb = vert->brb = vert->tlb =\ vert->isect_cache[0] = vert->isect_cache[1] =\ vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = 15 &~ TRF; + vert->free = CORNERFLAGS &~ TRF; vert->trb = box; vert->index = i; i++; box->v[BL] = vert; vert++; @@ -167,7 +169,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) vert->trb= vert->brb = vert->tlb =\ vert->isect_cache[0] = vert->isect_cache[1] =\ vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = 15 &~ BLF; + vert->free = CORNERFLAGS &~ BLF; vert->blb = box; vert->index = i; i++; box->v[TR] = vert; vert++; @@ -175,7 +177,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) vert->trb = vert->blb = vert->tlb =\ vert->isect_cache[0] = vert->isect_cache[1] =\ vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = 15 &~ BRF; + vert->free = CORNERFLAGS &~ BRF; vert->brb = box; vert->index = i; i++; box->v[TL] = vert; vert++; @@ -183,7 +185,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) vert->trb = vert->blb = vert->brb =\ vert->isect_cache[0] = vert->isect_cache[1] =\ vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = 15 &~ TLF; + vert->free = CORNERFLAGS &~ TLF; vert->tlb = box; vert->index = i; i++; box->v[BR] = vert; vert++; From bf168dc3c532d9703b7fbaa470191d67b533bb08 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 2 Aug 2008 22:11:22 +0000 Subject: [PATCH 36/58] Small update to get the BlenderPlayer compiling (also needed for 2.47) --- projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj | 1 + .../gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.vcproj | 1 + source/gameengine/GamePlayer/common/windows/GPW_Canvas.h | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj b/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj index 9d5a9f55074..323d2cc9b04 100644 --- a/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj +++ b/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj @@ -237,6 +237,7 @@ BasicRuntimeChecks="3" RuntimeLibrary="1" DefaultCharIsUnsigned="TRUE" + RuntimeTypeInfo="TRUE" UsePrecompiledHeader="2" PrecompiledHeaderFile="..\..\..\..\build\msvc_7\source\gameengine\ketsji\debug\KX_ketsji.pch" AssemblerListingLocation="..\..\..\..\build\msvc_7\source\gameengine\ketsji\debug\" diff --git a/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.vcproj b/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.vcproj index a8d6e77cd58..33806e32d65 100644 --- a/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.vcproj +++ b/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Sumo/PHY_Sumo.vcproj @@ -171,6 +171,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="1" + RuntimeTypeInfo="TRUE" UsePrecompiledHeader="2" PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\source\gameengine\physics\sumo\debug\PHY_Sumo.pch" AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\source\gameengine\physics\sumo\debug\" diff --git a/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h index bb1abd71505..bf8cb720811 100644 --- a/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h +++ b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h @@ -36,7 +36,7 @@ #include #include -#include +//#include #include "GPC_Canvas.h" From ad2be5f64f6f37f3e6591aadc2a4e4a4c4026bd9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 3 Aug 2008 01:00:51 +0000 Subject: [PATCH 37/58] Bugfix for weird + in the code, no idea why it compiled (yet some selfcollision bug to fix) [no 2.47 fix] --- source/blender/blenkernel/intern/collision.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 5b3cec25772..e6dcc82e129 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1661,7 +1661,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) ); if(collobjs) - + MEM_freeN(collobjs); + MEM_freeN(collobjs); return MIN2 ( ret, 1 ); } From 1d49ed89cbbb8359a61eb2ced25f942825e129b0 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 3 Aug 2008 01:41:57 +0000 Subject: [PATCH 38/58] Bugfix for non working selfcollisions [no 2.47 bugfix] --- source/blender/blenkernel/intern/collision.c | 219 +++++++++---------- 1 file changed, 105 insertions(+), 114 deletions(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index e6dcc82e129..cfcab54058d 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1291,116 +1291,6 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col return 1; } -int cloth_do_selfcollisions(ClothModifierData * clmd) -{ - int ret2 = 0, l; - Cloth *cloth = clmd->clothObject; - - if ( clmd->clothObject->bvhselftree ) - { - for(l = 0; l < clmd->coll_parms->self_loop_count; l++) - { - BVHTreeOverlap *overlap = NULL; - ClothVertex *verts = clmd->clothObject->verts; // needed for openMP - int k; - int ret = 0, result = 0; - - // search for overlapping collision pairs - overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); - -// #pragma omp parallel for private(k, i, j) schedule(static) - for ( k = 0; k < result; k++ ) - { - float temp[3]; - float length = 0; - float mindistance; - int i, j; - - i = overlap[k].indexA; - j = overlap[k].indexB; - - mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - continue; - } - } - - VECSUB ( temp, verts[i].tx, verts[j].tx ); - - if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; - - // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) - { - continue; - } - - length = Normalize ( temp ); - - if ( length < mindistance ) - { - float correction = mindistance - length; - - if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, -correction ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - } - else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, correction ); - VECADD ( verts[i].tx, verts[i].tx, temp ); - } - else - { - VecMulf ( temp, -correction*0.5 ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - - VECSUB ( verts[i].tx, verts[i].tx, temp ); - } - ret = 1; - ret2 += ret; - } - else - { - // check for approximated time collisions - } - } - - if ( overlap ) - MEM_freeN ( overlap ); - - if(!ret) - break; - - } - //////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////// - // SELFCOLLISIONS: update velocities - //////////////////////////////////////////////////////////// - if ( ret2 ) - { - int i; - ClothVertex *verts = clmd->clothObject->verts; // needed for openMP - - for ( i = 0; i < cloth->numverts; i++ ) - { - if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); - } - } - } - //////////////////////////////////////////////////////////// - } - return ret2; -} // return all collision objects in scene // collision object will exclude self @@ -1547,7 +1437,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f { Cloth *cloth=NULL; BVHTree *cloth_bvh=NULL; - int i=0, numfaces = 0, numverts = 0; + int i=0, numfaces = 0, numverts = 0, k, l, j; int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; @@ -1647,16 +1537,117 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f VECADD ( verts[i].tx, verts[i].txold, verts[i].tv ); } //////////////////////////////////////////////////////////// - + //////////////////////////////////////////////////////////// // Test on *simple* selfcollisions //////////////////////////////////////////////////////////// if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { - ret2 += cloth_do_selfcollisions(clmd); + for(l = 0; l < clmd->coll_parms->self_loop_count; l++) + { + // TODO: add coll quality rounds again + BVHTreeOverlap *overlap = NULL; + int result = 0; + + // collisions = 1; + verts = cloth->verts; // needed for openMP + + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + verts = cloth->verts; + + if ( cloth->bvhselftree ) + { + // search for overlapping collision pairs + overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); + + // #pragma omp parallel for private(k, i, j) schedule(static) + for ( k = 0; k < result; k++ ) + { + float temp[3]; + float length = 0; + float mindistance; + + i = overlap[k].indexA; + j = overlap[k].indexB; + + mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + continue; + } + } + + VECSUB ( temp, verts[i].tx, verts[j].tx ); + + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + + // check for adjacent points (i must be smaller j) + if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) + { + continue; + } + + length = Normalize ( temp ); + + if ( length < mindistance ) + { + float correction = mindistance - length; + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + } + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); + } + else + { + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); + } + ret = 1; + ret2 += ret; + } + else + { + // check for approximated time collisions + } + } + + if ( overlap ) + MEM_freeN ( overlap ); + + } + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // SELFCOLLISIONS: update velocities + //////////////////////////////////////////////////////////// + if ( ret2 ) + { + for ( i = 0; i < cloth->numverts; i++ ) + { + if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); + } + } + } + //////////////////////////////////////////////////////////// } - //////////////////////////////////////////////////////////// } while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) ); From 7a14a3580bdd942bfcf8a299899f03abbc5814f1 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 3 Aug 2008 11:40:09 +0000 Subject: [PATCH 39/58] Little speedup for kdop-bvh --- source/blender/blenlib/intern/BLI_kdopbvh.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index a97b9ca6672..4ceb9762a7b 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -484,15 +484,14 @@ static char get_largest_axis(float *bv) } } -static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char lastaxis) +static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end) { - char laxis; int i, tend; BVHNode *tnode; int slice = (end-start+tree->tree_type-1)/tree->tree_type; //division rounded up // Determine which axis to split along - laxis = get_largest_axis(node->bv); + char laxis = get_largest_axis(node->bv); // split nodes along longest axis for (i=0; start < end; start += slice, i++) //i counts the current child @@ -515,7 +514,7 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char if(tend != end) partition_nth_element(tree->nodes, start, end, tend, laxis); refit_kdop_hull(tree, tnode, start, tend); - bvh_div_nodes(tree, tnode, start, tend, laxis); + bvh_div_nodes(tree, tnode, start, tend); } node->totnode++; } @@ -586,7 +585,7 @@ void BLI_bvhtree_balance(BVHTree *tree) // refit root bvh node refit_kdop_hull(tree, tree->nodes[tree->totleaf], 0, tree->totleaf); // create + balance tree - bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf, 0); + bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf); // verify_tree(tree); } From 27b259345e4a23abef42b603f01dc77082791f9a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 3 Aug 2008 11:55:45 +0000 Subject: [PATCH 40/58] Grease Pencil Drawing: Some WIP code for 'nicer' drawing of thick 2d-strokes that will hopefully result in smoother lines, particularly with abrupt direction changes. Currently the code is hidden behind the rt button (for rt != 0), as in some cases, it still looks rather bad. --- source/blender/src/drawgpencil.c | 330 ++++++++++++++++++++++--------- 1 file changed, 234 insertions(+), 96 deletions(-) diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index 733310bfda7..ee28049e2c0 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -310,6 +310,8 @@ short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa) /* ************************************************** */ /* GREASE PENCIL DRAWING */ +/* ----- General Defines ------ */ + /* flags for sflag */ enum { GP_DRAWDATA_NOSTATUS = (1<<0), /* don't draw status info */ @@ -317,7 +319,9 @@ enum { GP_DRAWDATA_ONLYV2D = (1<<2), /* only draw 'canvas' strokes */ }; -/* draw stroke in buffer */ +/* ----- Tool Buffer Drawing ------ */ + +/* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thickness, short dflag, short sflag) { tGPspoint *pt; @@ -377,115 +381,232 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick } } -/* draw a given stroke */ -static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy) +/* ----- Existing Strokes Drawing (3D and Point) ------ */ + +/* draw a given stroke - just a single dot (only one point) */ +static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, int winy) { - bGPDspoint *pt; - int i; - - /* error checking */ - if ((points == NULL) || (totpoints <= 0)) - return; - - /* check if stroke can be drawn */ - if ((dflag & GP_DRAWDATA_ONLY3D) && !(sflag & GP_STROKE_3DSPACE)) - return; - if (!(dflag & GP_DRAWDATA_ONLY3D) && (sflag & GP_STROKE_3DSPACE)) - return; - if ((dflag & GP_DRAWDATA_ONLYV2D) && !(sflag & GP_STROKE_2DSPACE)) - return; - if (!(dflag & GP_DRAWDATA_ONLYV2D) && (sflag & GP_STROKE_2DSPACE)) - return; - - /* if drawing a single point, draw it larger */ - if (totpoints == 1) { - /* draw point */ - if (sflag & GP_STROKE_3DSPACE) { - glBegin(GL_POINTS); - glVertex3f(points->x, points->y, points->z); - glEnd(); - } - else if (sflag & GP_STROKE_2DSPACE) { - glBegin(GL_POINTS); - glVertex2f(points->x, points->y); - glEnd(); - } - else { - const float x= (points->x / 1000 * winx); - const float y= (points->y / 1000 * winy); - - glBegin(GL_POINTS); - glVertex2f(x, y); - glEnd(); - } + /* draw point */ + if (sflag & GP_STROKE_3DSPACE) { + glBegin(GL_POINTS); + glVertex3f(points->x, points->y, points->z); + glEnd(); + } + else if (sflag & GP_STROKE_2DSPACE) { + glBegin(GL_POINTS); + glVertex2f(points->x, points->y); + glEnd(); } else { - float oldpressure = 0.0f; + const float x= (points->x / 1000 * winx); + const float y= (points->y / 1000 * winy); + + glBegin(GL_POINTS); + glVertex2f(x, y); + glEnd(); + } +} + +/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */ +static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy) +{ + bGPDspoint *pt; + float oldpressure = 0.0f; + int i; + + /* draw stroke curve */ + glBegin(GL_LINE_STRIP); + for (i=0, pt=points; i < totpoints && pt; i++, pt++) { + if (fabs(pt->pressure - oldpressure) > 0.2f) { + glEnd(); + glLineWidth(pt->pressure * thickness); + glBegin(GL_LINE_STRIP); + + glVertex3f(pt->x, pt->y, pt->z); + + oldpressure = pt->pressure; + } + else + glVertex3f(pt->x, pt->y, pt->z); + } + glEnd(); + + /* draw debug points of curve on top? */ + if (debug) { + glBegin(GL_POINTS); + for (i=0, pt=points; i < totpoints && pt; i++, pt++) + glVertex3f(pt->x, pt->y, pt->z); + glEnd(); + } +} + +/* ----- Fancy 2D-Stroke Drawing ------ */ + +/* draw a given stroke in 2d */ +static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy) +{ + /* if thickness is less than 3, 'smooth' opengl lines look better */ + if ((thickness < 3) || (G.rt==0)) { + bGPDspoint *pt; + int i; - /* draw stroke curve */ glBegin(GL_LINE_STRIP); for (i=0, pt=points; i < totpoints && pt; i++, pt++) { - float x, y, z; - - if (sflag & GP_STROKE_3DSPACE) { - x= pt->x; - y= pt->y; - z= pt->z; - } - else if (sflag & GP_STROKE_2DSPACE) { - x= pt->x; - y= pt->y; - z= 0; + if (sflag & GP_STROKE_2DSPACE) { + glVertex2f(pt->x, pt->y); } else { - x= (pt->x / 1000 * winx); - y= (pt->y / 1000 * winy); - z= 0; - } - - if (fabs(pt->pressure - oldpressure) > 0.2f) { - glEnd(); - glLineWidth(pt->pressure * thickness); - glBegin(GL_LINE_STRIP); + const float x= (pt->x / 1000 * winx); + const float y= (pt->y / 1000 * winy); - if (sflag & GP_STROKE_3DSPACE) - glVertex3f(x, y, z); - else - glVertex2f(x, y); - - oldpressure = pt->pressure; - } - else { - if (sflag & GP_STROKE_3DSPACE) - glVertex3f(x, y, z); - else - glVertex2f(x, y); + glVertex2f(x, y); } } glEnd(); + } + else { /* tesselation code: currently only enabled with rt != 0 */ + bGPDspoint *pt1, *pt2; + float p0[2], p1[2], pm[2]; + int i; - /* draw debug points of curve on top? */ - if (debug) { - glBegin(GL_POINTS); - for (i=0, pt=points; i < totpoints && pt; i++, pt++) { - if (sflag & GP_STROKE_3DSPACE) { - glVertex3f(pt->x, pt->y, pt->z); - } - else if (sflag & GP_STROKE_2DSPACE) { - glVertex2f(pt->x, pt->y); - } - else { - const float x= (pt->x / 1000 * winx); - const float y= (pt->y / 1000 * winy); - - glVertex2f(x, y); - } + glShadeModel(GL_FLAT); + glBegin(GL_QUAD_STRIP); + + for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) { + float s0[2], s1[2]; /* segment 'center' points */ + float t0[2], t1[2]; /* tesselated coordinates */ + float m1[2], m2[2]; /* gradient and normal */ + float pthick, dist; /* thickness at segment point, and length of segment */ + float sminorang; /* minor angle between strokes */ + + /* get x and y coordinates from points */ + if (sflag & GP_STROKE_2DSPACE) { + s0[0]= pt1->x; s0[1]= pt1->y; + s1[0]= pt2->x; s1[1]= pt2->y; } - glEnd(); + else { + s0[0]= (pt1->x / 1000 * winx); + s0[1]= (pt1->y / 1000 * winy); + s1[0]= (pt2->x / 1000 * winx); + s1[1]= (pt2->y / 1000 * winy); + } + + /* calculate gradient and normal - 'angle'=(ny/nx) */ + m1[1]= s1[1] - s0[1]; + m1[0]= s1[0] - s0[0]; + dist = Vec2Lenf(s0, s1); + m2[1]= -(m1[0]) / dist; + m2[0]= m1[1] / dist; + + /* if the first segment, initialise the first segment using segment's normal */ + if (i == 0) { + pthick= (pt1->pressure * thickness); + + // TODO: also draw/do a round end-cap first + + p0[0]= s0[0] - (pthick * m2[0]); + p0[1]= s0[1] - (pthick * m2[1]); + p1[0]= s1[0] + (pthick * m2[0]); + p1[1]= s1[1] + (pthick * m2[1]); + + Vec2Copyf(pm, m1); + } + + /* if the minor angle between the current segment and the previous one is less than 90 degrees */ + if (i) + sminorang= NormalizedVecAngle2_2D(pm, m1); + else + sminorang= 0.0f; + + if ((IS_EQ(sminorang, 0)==0) && (abs(sminorang) < M_PI_2) ) + { + float closep[2]; + + /* recalculate startpoint of segment, where the new start-line: + * - starts a new gl-quad-strip + * - uses the vert of old startpoint closer to our endpoint + * - distance between new startpoints = distance between old startpoints + * - new startpoints occur on same gradient as old segment does (has potential for some 'minor' overlap, but ok) + */ + + /* find the closer vertex, and distance between startpoints */ + if (Vec2Lenf(p0, s1) > Vec2Lenf(p1, s1)) + Vec2Copyf(closep, p1); + else + Vec2Copyf(closep, p0); + + /* determine which side this closer vertex should be on */ + pthick= (pt1->pressure * thickness * 2); + if ( ((closep[0] - s0[0]) > 0) || ((closep[1] - s0[1]) > 0) ) { + /* assumes this is the 'second' point, (i.e. the 'plus' one), so the other is subtracting */ + p0[0]= closep[0] - (pthick * pm[0]); + p0[1]= closep[1] - (pthick * pm[1]); + p1[0]= closep[0]; + p1[1]= closep[1]; + } + else if ( ((closep[0] - s0[0]) < 0) || ((closep[1] - s0[1]) < 0) ) { + /* assumes this is the 'first' point, (i.e. the 'minus' one), so the other is adding */ + p0[0]= closep[0]; + p0[1]= closep[1]; + p1[0]= closep[0] + (pthick * pm[0]); + p1[1]= closep[1] + (pthick * pm[1]); + } + + /* reset gl-states! */ + glEnd(); + glBegin(GL_QUAD_STRIP); + } + + /* do the end of this segment */ + pthick= (pt2->pressure * thickness); + t0[0] = s1[0] - (pthick * m2[0]); + t0[1] = s1[1] - (pthick * m2[1]); + t1[0] = s1[0] + (pthick * m2[0]); + t1[1] = s1[1] + (pthick * m2[1]); + + /* draw this segment */ + glVertex2f(p0[0], p0[1]); + glVertex2f(p1[0], p1[1]); + glVertex2f(t0[0], t0[1]); + glVertex2f(t1[0], t1[1]); + + // TODO: draw end cap if last segment + if (i == totpoints-2) { + + } + + /* store current points for next segment to use */ + Vec2Copyf(p0, t0); + Vec2Copyf(p1, t1); + Vec2Copyf(pm, m1); } + + glEnd(); + } + + /* draw debug points of curve on top? (original stroke points) */ + if (debug) { + bGPDspoint *pt; + int i; + + glBegin(GL_POINTS); + for (i=0, pt=points; i < totpoints && pt; i++, pt++) { + if (sflag & GP_STROKE_2DSPACE) { + glVertex2f(pt->x, pt->y); + } + else { + const float x= (pt->x / 1000 * winx); + const float y= (pt->y / 1000 * winy); + + glVertex2f(x, y); + } + } + glEnd(); } } +/* ----- General Drawing ------ */ + /* draw a set of strokes */ static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, short debug, short lthick, float color[4]) @@ -495,9 +616,26 @@ static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, shor /* set color first (may need to reset it again later too) */ glColor4f(color[0], color[1], color[2], color[3]); - for (gps= gpf->strokes.first; gps; gps= gps->next) { - /* just draw the stroke once */ - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); + for (gps= gpf->strokes.first; gps; gps= gps->next) { + /* check if stroke can be drawn */ + if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE)) + continue; + if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE)) + continue; + if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE)) + continue; + if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE)) + continue; + if ((gps->points == 0) || (gps->totpoints < 1)) + continue; + + /* check which stroke-drawer to use */ + if (gps->totpoints == 1) + gp_draw_stroke_point(gps->points, gps->flag, winx, winy); + else if (dflag & GP_DRAWDATA_ONLY3D) + gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); + else if (gps->totpoints > 1) + gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); } } @@ -656,7 +794,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) glColor4f(0, 0, 0, 1); } -/* ----------- */ +/* ----- Grease Pencil Sketches Drawing API ------ */ /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, second time with onlyv2d=0 for screen-aligned strokes From cad3b73144c2ee82feb9659c130664baf9a1aa4d Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 3 Aug 2008 15:35:56 +0000 Subject: [PATCH 41/58] == Sequencer == This fixes: [#17413] Sequencer: Blender crashes pressing R on a color strip --- source/blender/src/editseq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index 12019a9dab9..e9d0b57a166 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -644,6 +644,7 @@ static int seq_is_parent(Sequence *par, Sequence *seq) static int seq_is_predecessor(Sequence *pred, Sequence *seq) { + if (!pred) return 0; if(pred == seq) return 0; else if(seq_is_parent(pred, seq)) return 1; else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1; From 7fc6741bcf631c14a0009b051c248e9750fb9987 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 3 Aug 2008 15:45:53 +0000 Subject: [PATCH 42/58] == Sequencer == This fixes: [#17405] Sequencer: unselected black strips are unreadable using [#17418] Fix for bug #17405: unselected black seq strips text unreadable Thanks to Roelf De Kock for providing the patch and mindrones for the bug report :) --- source/blender/src/drawseq.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index cc431c73a2e..71a777c9056 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -98,7 +98,7 @@ int no_rightbox=0, no_leftbox= 0; static void draw_seq_handle(Sequence *seq, SpaceSeq *sseq, float pixelx, short direction); static void draw_seq_extensions(Sequence *seq, SpaceSeq *sseq); -static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2); +static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2, char *background_col); static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2); static void draw_seq_strip(struct Sequence *seq, struct ScrArea *sa, struct SpaceSeq *sseq, int outline_tint, float pixelx); @@ -604,7 +604,7 @@ static void draw_seq_extensions(Sequence *seq, SpaceSeq *sseq) } /* draw info text on a sequence strip */ -static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2) +static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2, char *background_col) { float v1[2], v2[2]; int len, size; @@ -670,8 +670,13 @@ static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2) mval[1]= 1; areamouseco_to_ipoco(G.v2d, mval, &x1, &x2); - if(seq->flag & SELECT) cpack(0xFFFFFF); - else cpack(0); + if(seq->flag & SELECT){ + cpack(0xFFFFFF); + }else if ((((int)background_col[0] + (int)background_col[1] + (int)background_col[2]) / 3) < 50){ + cpack(0x505050); /* use lighter text colour for dark background */ + }else{ + cpack(0); + } glRasterPos3f(x1, y1+SEQ_STRIP_OFSBOTTOM, 0.0); BMF_DrawString(G.font, strp); } @@ -740,7 +745,7 @@ so wave file sample drawing precission is zoom adjusted static void draw_seq_strip(Sequence *seq, ScrArea *sa, SpaceSeq *sseq, int outline_tint, float pixelx) { float x1, x2, y1, y2; - char col[3], is_single_image; + char col[3], background_col[3], is_single_image; /* we need to know if this is a single image/color or not for drawing */ is_single_image = (char)check_single_seq(seq); @@ -755,13 +760,14 @@ static void draw_seq_strip(Sequence *seq, ScrArea *sa, SpaceSeq *sseq, int outli /* get the correct color per strip type*/ - get_seq_color3ubv(seq, col); + //get_seq_color3ubv(seq, col); + get_seq_color3ubv(seq, background_col); /* draw the main strip body */ if (is_single_image) /* single image */ - draw_shadedstrip(seq, col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2); + draw_shadedstrip(seq, background_col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2); else /* normal operation */ - draw_shadedstrip(seq, col, x1, y1, x2, y2); + draw_shadedstrip(seq, background_col, x1, y1, x2, y2); /* draw additional info and controls */ if (seq->type == SEQ_RAM_SOUND) @@ -814,7 +820,7 @@ static void draw_seq_strip(Sequence *seq, ScrArea *sa, SpaceSeq *sseq, int outli /* nice text here would require changing the view matrix for texture text */ if( (x2-x1) / pixelx > 32) { - draw_seq_text(seq, x1, x2, y1, y2); + draw_seq_text(seq, x1, x2, y1, y2, background_col); } } From 855fa737d70d4b01ef129a27ffc7d89b65dbc590 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 3 Aug 2008 15:56:35 +0000 Subject: [PATCH 43/58] == Sequencer == Fixes: [#15082] Sequencer: for image strips, the Input file field disappears if the cursor is out of the selected strip also it wasn't really a bug, since the file name of image input strips _has_ to depend on CFRA. Well, we choose the next possible image strip, which is most likely the thing, most people expected... --- source/blender/src/buttons_scene.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 3b0167d673c..fb6a7636e16 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -763,7 +763,16 @@ static void seq_panel_input() } if (last_seq->type == SEQ_IMAGE) { - StripElem * se = give_stripelem(last_seq, CFRA); + int cfra = CFRA; + StripElem * se; + + if(last_seq->startdisp >cfra) { + cfra = last_seq->startdisp; + } else if (last_seq->enddisp <= cfra) { + cfra = last_seq->enddisp - 1; + } + + se = give_stripelem(last_seq, cfra); if (se) { uiDefBut(block, TEX, From ac7aef6b3dd95aeadec78d83be8b9ac38e0a45e1 Mon Sep 17 00:00:00 2001 From: Remigiusz Fiedler Date: Sun, 3 Aug 2008 15:57:09 +0000 Subject: [PATCH 44/58] DXF-importer script. Works well with 2.46winXP Please commit to 2.47 branch patch history: v1.12 - 2008.08.03 c2 warningfix: relocating of globals: layersmap, oblist c2 modif UI: buttons newScene+targetLayer moved to start panel v1.12 - 2008.07.04 c1 added control Curve's OrderU parameter c1 modif UI: preset buttons X-2D-3D moved to start panel b6 added handling exception of not registered LAYERs (Hammer-HL-editor DXF output) b5 rebuild UI: global preset 2D for Curve-Import b5 added UI-options: PL-MESH N+N plmesh_flip and normals_out b5 added support for SPLINEs, added control OrderU parameter b5 rewrote draw module for NURBS_curve and Bezier_curve v1.12 - 2008.06.22 b4 change versioning system 1.0.12 -> 1.12 b4 print at start version-info to console b3 bugfix: ob.name conflict with existing meshes (different ob.name/mesh.name) --- release/scripts/import_dxf.py | 916 ++++++++++++++++++++-------------- 1 file changed, 549 insertions(+), 367 deletions(-) diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py index ce7df610d98..09e51c22a9f 100644 --- a/release/scripts/import_dxf.py +++ b/release/scripts/import_dxf.py @@ -2,15 +2,15 @@ """ Name: 'Autodesk DXF (.dxf)' -Blender: 244 +Blender: 246 Group: 'Import' Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).' """ __author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)' -__version__ = '1.0.12 - 2008.06.05 by migius' +__version__ = '1.12 - 2008.07.04 by migius' __url__ = ["http://blenderartists.org/forum/showthread.php?t=84319", "http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"] -__email__ = ["Kitsune_e(at)yahoo.com", "migius(at)4d-vectors.de"] +__email__ = ["migius(at)4d-vectors.de","Kitsune_e(at)yahoo.com"] __bpydoc__ = """\ This script imports objects from DXF (2d/3d) into Blender. @@ -19,7 +19,7 @@ Supported DXF format versions: from (r2.5) r12 up to 2008. Enhanced features are: - configurable object filtering and geometry manipulation, - configurable material pre-processing, -- DXF-data analyze and raporting. +- DXF-code analyze and reporting. Supported DXF r12 objects: LINE, @@ -41,10 +41,10 @@ XREF (External Reference). Supported DXF>r12 objects: ELLIPSE, -LWPOLYLINE (LightWeight Polylines), -(wip v1.0.12) SPLINE, -(wip v1.0.13) MLINE, -(wip v1.0.13) MTEXT +LWPOLYLINE (LightWeight Polyline), +SPLINE, +(wip v1.13) MLINE, +(wip v1.13) MTEXT Unsupported objects: DXF r12: DIMENSION. @@ -60,7 +60,7 @@ Supported layout modes: Supported scene definition objescts produced with AVE_RENDER: scene: selection of lights assigned to the camera, lights: DIRECT, OVERHEAD, SH_SPOT, -(wip v1.0.13 import of AVE_RENDER material definitions) +(wip v1.13 import of AVE_RENDER material definitions) Hierarchy: Entire DXF BLOCK hierarchy is preserved after import into Blender @@ -73,7 +73,7 @@ thickness, width, color, layer, -(wip v1.0.12: XDATA, grouped status) +(wip v1.13: XDATA, grouped status) It is recommended to use DXF-object properties for assign Blender materials. Notes: @@ -109,9 +109,22 @@ History: -- bug: Registry recall from hd_cache ?? only win32 bug?? -- support DXF-definitions of scene, lights and cameras -- support ortho mode for VIEWs and VPORTs as cameras - -- add support for SPLINEs - v1.0.12: 2008.06.05 by migius + + v1.12 - 2008.08.03 by migius + c2 warningfix: relocating of globals: layersmap, oblist + c2 modif UI: buttons newScene+targetLayer moved to start panel + v1.12 - 2008.07.04 by migius + c1 added control Curve's OrderU parameter + c1 modif UI: preset buttons X-2D-3D moved to start panel + b6 added handling exception of not registered LAYERs (Hammer-HL-editor DXF output) + b5 rebuild UI: global preset 2D for Curve-Import + b5 added UI-options: PL-MESH N+N plmesh_flip and normals_out + b5 added support for SPLINEs, added control OrderU parameter + b5 rewrote draw module for NURBS_curve and Bezier_curve + v1.12 - 2008.06.22 by migius + b4 change versioning system 1.0.12 -> 1.12 + b4 print at start version-info to console b3 bugfix: ob.name conflict with existing meshes (different ob.name/mesh.name) v1.0.12: 2008.05.24 by migius b2 added support for LWPOLYLINEs @@ -310,16 +323,16 @@ except ImportError: #print 'psyco not imported' pass -print '\n\n\n\n' -print 'DXF-Importer *** start ***' #--------------------- +#try: Curve.orderU + +print '\n\n\n' +print 'DXF-Importer v%s *** start ***' %(__version__) #--------------------- SCENE = None WORLDX = Mathutils.Vector((1,0,0)) WORLDY = Mathutils.Vector((1,1,0)) WORLDZ = Mathutils.Vector((0,0,1)) -oblist = [] #to be sure, it is an empty list - G_SCALE = 1.0 #(0.0001-1000) global scaling factor for all dxf data G_ORIGIN_X = 0.0 #global translation-vector (x,y,z) in DXF units G_ORIGIN_Y = 0.0 @@ -335,12 +348,15 @@ MIN_WIDTH = MIN_DIST * 10.0 #minimal width by forced width TRIM_LIMIT = 3.0 #limit for triming of polylines-wide-segments (values:0.0 - 5.0) ELEVATION = 0.0 #standard elevation = coordinate Z -TARGET_LAYER = 3 #target blender_layer -GROUP_BYLAYER = 0 #(0/1) all entities from same layer import into one blender-group -cur_COUNTER = 0 #counter for progress_bar -M_OBJ = False BYBLOCK = 0 BYLAYER = 256 +TARGET_LAYER = 3 #target blender_layer +GROUP_BYLAYER = 0 #(0/1) all entities from same layer import into one blender-group +LAYER_DEF_NAME = 'AAAA' #default layer name +LAYER_DEF_COLOR = 4 #default layer color +E_M = 0 +LAB = "*) parts under construction" +M_OBJ = 0 FILENAME_MAX = 180 #max length of path+file_name string (FILE_MAXDIR + FILE_MAXFILE) MAX_NAMELENGTH = 17 #max_effective_obnamelength in blender =21=17+(.001) @@ -366,27 +382,27 @@ class View: #----------------------------------------------------------------- self.type = obj.type self.name = obj.get_type(2)[0] - self.data = obj.data[:] +# self.data = obj.data[:] - self.centerX = getit(obj.data, 10, 0.0) #view center pointX (in DCS) - self.centerY = getit(obj.data, 20, 0.0) #view center pointY (in DCS) + self.centerX = getit(obj, 10, 0.0) #view center pointX (in DCS) + self.centerY = getit(obj, 20, 0.0) #view center pointY (in DCS) self.height = obj.get_type(40)[0] #view height (in DCS) self.width = obj.get_type(41)[0] #view width (in DCS) self.dir = [0,0,0] - self.dir[0] = getit(obj.data, 11, 0.0) #view directionX from target (in WCS) - self.dir[1] = getit(obj.data, 21, 0.0) # - self.dir[2] = getit(obj.data, 31, 0.0) # + self.dir[0] = getit(obj, 11, 0.0) #view directionX from target (in WCS) + self.dir[1] = getit(obj, 21, 0.0) # + self.dir[2] = getit(obj, 31, 0.0) # self.target = [0,0,0] - self.target[0] = getit(obj.data, 12, 0.0) #target pointX(in WCS) - self.target[1] = getit(obj.data, 22, 0.0) # - self.target[2] = getit(obj.data, 32, 0.0) # + self.target[0] = getit(obj, 12, 0.0) #target pointX(in WCS) + self.target[1] = getit(obj, 22, 0.0) # + self.target[2] = getit(obj, 32, 0.0) # self.length = obj.get_type(42)[0] #Lens length - self.clip_front = getit(obj.data, 43) #Front clipping plane (offset from target point) - self.clip_back = getit(obj.data, 44) #Back clipping plane (offset from target point) + self.clip_front = getit(obj, 43) #Front clipping plane (offset from target point) + self.clip_back = getit(obj, 44) #Back clipping plane (offset from target point) self.twist = obj.get_type(50)[0] #view twist angle in degrees self.flags = getit(obj, 70, 0) @@ -450,28 +466,28 @@ class Vport: #----------------------------------------------------------------- self.type = obj.type self.name = obj.get_type(2)[0] - self.data = obj.data[:] +# self.data = obj.data[:] #print 'deb:vport name, data:', self.name #------- #print 'deb:vport data:', self.data #------- self.height = obj.get_type(40)[0] #vport height (in DCS) - self.centerX = getit(obj.data, 12, 0.0) #vport center pointX (in DCS) - self.centerY = getit(obj.data, 22, 0.0) #vport center pointY (in DCS) + self.centerX = getit(obj, 12, 0.0) #vport center pointX (in DCS) + self.centerY = getit(obj, 22, 0.0) #vport center pointY (in DCS) self.width = self.height * obj.get_type(41)[0] #vport aspect ratio - width (in DCS) self.dir = [0,0,0] - self.dir[0] = getit(obj.data, 16, 0.0) #vport directionX from target (in WCS) - self.dir[1] = getit(obj.data, 26, 0.0) # - self.dir[2] = getit(obj.data, 36, 0.0) # + self.dir[0] = getit(obj, 16, 0.0) #vport directionX from target (in WCS) + self.dir[1] = getit(obj, 26, 0.0) # + self.dir[2] = getit(obj, 36, 0.0) # self.target = [0,0,0] - self.target[0] = getit(obj.data, 17, 0.0) #target pointX(in WCS) - self.target[1] = getit(obj.data, 27, 0.0) # - self.target[2] = getit(obj.data, 37, 0.0) # + self.target[0] = getit(obj, 17, 0.0) #target pointX(in WCS) + self.target[1] = getit(obj, 27, 0.0) # + self.target[2] = getit(obj, 37, 0.0) # self.length = obj.get_type(42)[0] #Lens length - self.clip_front = getit(obj.data, 43) #Front clipping plane (offset from target point) - self.clip_back = getit(obj.data, 44) #Back clipping plane (offset from target point) + self.clip_front = getit(obj, 43) #Front clipping plane (offset from target point) + self.clip_back = getit(obj, 44) #Back clipping plane (offset from target point) self.twist = obj.get_type(51)[0] #view twist angle self.flags = getit(obj, 70, 0) @@ -528,29 +544,36 @@ class Layer: #----------------------------------------------------------------- """Class for objects representing dxf LAYERs. """ def __init__(self, obj, name=None, color=None, frozen=None): - """Expects an object of type layer as input. + """Expects an dxfobject of type layer as input. + if no dxfobject - creates surogate layer with default parameters """ - self.type = obj.type - self.data = obj.data[:] - if name: - self.name = name - #self.bfname = name #--todo---see layernamesmap in f_getLayersmap --- - else: - self.name = obj.get_type(2)[0] #layer name of object - - if color: - self.color = color - else: - self.color = obj.get_type(62)[0] #color of object - - if frozen: - self.frozen = frozen - else: - self.flags = obj.get_type(70)[0] - self.frozen = self.flags & 1 + if obj==None: + self.type = 'layer' + if name: self.name = name + else: self.name = LAYER_DEF_NAME + if color: self.color = color + else: self.color = LAYER_DEF_COLOR + if frozen!=None: self.frozen = frozen + else: self.frozen = 0 + else: + if obj.type=='layer': + self.type = obj.type + #self.data = obj.data[:] + if name: self.name = name + #self.bfname = name #--todo---see layernamesmap in f_getLayersmap --- + else: self.name = obj.get_type(2)[0] #layer name of object + + if color: self.color = color + else: self.color = obj.get_type(62)[0] #color of object + + if frozen!=None: self.frozen = frozen + else: + self.flags = obj.get_type(70)[0] + self.frozen = self.flags & 1 + def __repr__(self): return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color) @@ -615,15 +638,15 @@ class Solid: #----------------------------------------------------------------- raise TypeError, "Wrong type \'%s\' for solid/trace object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] self.space = getit(obj, 67, 0) self.thic = getit(obj, 39, 0) self.color_index = getit(obj, 62, BYLAYER) - self.layer = getit(obj.data, 8, None) - self.extrusion = get_extrusion(obj.data) - self.points = self.get_points(obj.data) + self.layer = getit(obj, 8, None) + self.extrusion = get_extrusion(obj) + self.points = self.get_points(obj) @@ -736,16 +759,16 @@ class Line: #----------------------------------------------------------------- if not obj.type == 'line': raise TypeError, "Wrong type \'%s\' for line object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] self.space = getit(obj, 67, 0) self.thic = getit(obj, 39, 0) #print 'deb:self.thic: ', self.thic #--------------------- self.color_index = getit(obj, 62, BYLAYER) - self.layer = getit(obj.data, 8, None) - self.extrusion = get_extrusion(obj.data) - self.points = self.get_points(obj.data) + self.layer = getit(obj, 8, None) + self.extrusion = get_extrusion(obj) + self.points = self.get_points(obj) def get_points(self, data): @@ -883,16 +906,16 @@ class Point: #----------------------------------------------------------------- if not obj.type == 'point': raise TypeError, "Wrong type %s for point object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] self.space = getit(obj, 67, 0) self.thic = getit(obj, 39, 0) #print 'deb:self.thic: ', self.thic #--------------------- self.color_index = getit(obj, 62, BYLAYER) - self.layer = getit(obj.data, 8, None) - self.extrusion = get_extrusion(obj.data) - self.points = self.get_points(obj.data) + self.layer = getit(obj, 8, None) + self.extrusion = get_extrusion(obj) + self.points = self.get_points(obj) def get_points(self, data): @@ -922,7 +945,7 @@ class Point: #----------------------------------------------------------------- thic = settings.var['thick_min'] if thic < settings.var['dist_min']: thic = settings.var['dist_min'] - if True: #--todo-- points_as in [1,3,4,5]: + if points_as in [1,3,4,5]: if True: # points_as in [1,5]: # as 'empty' c = 'Empty' elif points_as == 3: # as 'thin sphere' @@ -969,11 +992,8 @@ class Polyline: #-------------------------------------------------------------- if not obj.type == 'polyline': raise TypeError, "Wrong type %s for polyline object!" %obj.type self.type = obj.type - self.data = obj.data[:] - #print 'deb:polyline.obj.data[:]:\n', obj.data[:] #------------------------ - self.points = [] +# self.data = obj.data[:] - # optional data (with defaults) self.space = getit(obj, 67, 0) self.elevation = getit(obj, 30, 0) #print 'deb:elevation: ', self.elevation #--------------- @@ -983,7 +1003,7 @@ class Polyline: #-------------------------------------------------------------- self.flags = getit(obj, 70, 0) self.closed = self.flags & 1 # closed in the M direction self.curved = self.flags & 2 # Bezier-curve-fit vertices have been added - self.spline = self.flags & 4 # Bspline-fit vertices have been added + self.spline = self.flags & 4 # NURBS-curve-fit vertices have been added self.poly3d = self.flags & 8 # 3D-polyline self.plmesh = self.flags & 16 # 3D-polygon mesh self.closeN = self.flags & 32 # closed in the N direction @@ -1002,18 +1022,18 @@ class Polyline: #-------------------------------------------------------------- self.vectorsN = getit(obj, 72, None) # PolyMesh: expansion in M-direction / PolyFace: number of faces #self.resolM = getit(obj, 73, None) # resolution of surface in M direction #self.resolN = getit(obj, 74, None) # resolution of surface in N direction - self.curvetyp = getit(obj, 75, 0) # type of curve/surface: 0=None/5=Quadric/6=Cubic/8=Bezier - self.curvNormal = False - self.curvQBspline = False - self.curvCBspline = False + self.curvNoFitted = False + self.curvQuadrati = False + self.curvCubicBsp = False self.curvBezier = False - if self.curvetyp == 0: self.curvNormal = True - elif self.curvetyp == 5: self.curvQBspline = True - elif self.curvetyp == 6: self.curvCBspline = True - elif self.curvetyp == 8: self.curvBezier = True + curvetype = getit(obj, 75, 0) # type of curve/surface: 0=None/5=Quadric/6=Cubic/8=Bezier + if curvetype == 0: self.curvNoFitted = True + elif curvetype == 5: self.curvQuadrati = True + elif curvetype == 6: self.curvCubicBsp = True + elif curvetype == 8: self.curvBezier = True - self.layer = getit(obj.data, 8, None) - self.extrusion = get_extrusion(obj.data) + self.layer = getit(obj, 8, None) + self.extrusion = get_extrusion(obj) self.points = [] #list with vertices coordinats self.faces = [] #list with vertices assigment to faces @@ -1026,9 +1046,65 @@ class Polyline: #-------------------------------------------------------------- + def doubles_out(self, settings, d_points): + """routine to sort out of double.vertices----------------------------- + """ + minimal_dist = settings.var['dist_min'] * 0.1 + dv_count = 0 + temp_points = [] + for i in xrange(len(d_points)-1): + point = d_points[i] + point2 = d_points[i+1] + #print 'deb:double.vertex p1,p2', point, point2 #------------------------ + delta = Mathutils.Vector(point2.loc) - Mathutils.Vector(point.loc) + if delta.length > minimal_dist: + temp_points.append(point) + else: + dv_count+=1 + #print 'deb:drawPoly2d double.vertex sort out! count=', dv_count #------------------------ + temp_points.append(d_points[-1]) #------ incl. last vertex ------------- + #if self.closed: temp_points.append(d_points[1]) #------ loop start vertex ------------- + d_points = temp_points #-----vertex.list without "double.vertices" + #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ + return d_points + + + def tribles_out(self, settings, d_points): + """routine to sort out of three_in_place.vertices----------------------------- + """ + minimal_dist = settings.var['dist_min'] * 0.1 + dv_count = 0 + temp_points = [] + for i in xrange(len(d_points)-2): + point1 = d_points[i] + point2 = d_points[i+1] + point3 = d_points[i+2] + #print 'deb:double.vertex p1,p2', point, point2 #------------------------ + delta12 = Mathutils.Vector(point2.loc) - Mathutils.Vector(point1.loc) + delta23 = Mathutils.Vector(point3.loc) - Mathutils.Vector(point2.loc) + if delta12.length < minimal_dist and delta23.length < minimal_dist: + dv_count+=1 + else: + temp_points.append(point1) + #print 'deb:drawPoly2d double.vertex sort out! count=', dv_count #------------------------ + point1 = d_points[-2] + point2 = d_points[-1] + delta12 = Mathutils.Vector(point2.loc) - Mathutils.Vector(point1.loc) + if delta12.length > minimal_dist: + temp_points.append(d_points[-2]) #------ incl. 2last vertex ------------- + temp_points.append(d_points[-1]) #------ incl. 1last vertex ------------- + #if self.closed: temp_points.append(d_points[1]) #------ loop start vertex ------------- + d_points = temp_points #-----vertex.list without "double.vertices" + #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ + return d_points + + def draw(self, settings): #-------------%%%% DRAW POLYLINE %%%--------------- """for POLYLINE: generate Blender_geometry. """ + #print 'deb:drawPOLYLINE.START:----------------' #------------------------ + #print 'deb:POLYLINEdraw self.pltype:', self.pltype #------------------------ + #print 'deb:POLYLINEdraw self.points:\n', self.points #------------------------ ob = [] #---- 3dPolyFace - mesh with free topology if self.pltype=='plface' and settings.drawTypes['plmesh']: @@ -1036,22 +1112,30 @@ class Polyline: #-------------------------------------------------------------- #---- 3dPolyMesh - mesh with ortogonal topology elif self.pltype=='plmesh' and settings.drawTypes['plmesh']: ob = self.drawPlMesh(settings) + #---- 2dPolyline - plane polyline with arc/wide/thic segments elif self.pltype=='poly2d' and settings.drawTypes['polyline']: - if settings.var['plines_as'] == 5: # and self.spline: + if settings.var['plines_as'] in [5,6]: # and self.spline: ob = self.drawPolyCurve(settings) else: ob = self.drawPoly2d(settings) + #---- 3dPolyline - non-plane polyline (thin segments = without arc/wide/thic) elif self.pltype=='poly3d' and settings.drawTypes['pline3']: - if settings.var['plines3_as'] == 5: # and self.spline: + if settings.var['plines3_as'] in [5,6]: # and self.spline: + ob = self.drawPolyCurve(settings) + else: + ob = self.drawPoly2d(settings) + + #---- Spline - curved polyline (thin segments = without arc/wide/thic) + elif self.pltype=='spline' and settings.drawTypes['spline']: + if settings.var['splines_as'] in [5,6]: ob = self.drawPolyCurve(settings) else: ob = self.drawPoly2d(settings) return ob - def drawPlFace(self, settings): #---- 3dPolyFace - mesh with free topology """Generate the geometery of polyface. """ @@ -1065,6 +1149,10 @@ class Polyline: #-------------------------------------------------------------- else: points.append(point.loc) + if settings.var['plmesh_flip']: # ---------------------- + for face in faces: + face.reverse() + face = [face[-1]] + face[:-1] #print 'deb:drawPlFace: len of points_list:\n', len(points) #----------------------- #print 'deb:drawPlFace: len of faces_list:\n', len(faces) #----------------------- @@ -1076,6 +1164,10 @@ class Polyline: #-------------------------------------------------------------- ob = SCENE.objects.new(me) # create a new mesh_object me.verts.extend(points) # add vertices to mesh me.faces.extend(faces) # add faces to the mesh + if settings.var['normals_out']: # ---------------------- + #me.flipNormals() + me.recalcNormals(0) + #me.update() #print 'deb:drawPlFace: len of me.faces:\n', len(me.faces) #----------------------- if settings.var['meshSmooth_on']: # ---------------------- @@ -1123,7 +1215,10 @@ class Polyline: #-------------------------------------------------------------- ob = SCENE.objects.new(me) # create a new mesh_object me.verts.extend([point.loc for point in self.points]) # add vertices to mesh me.faces.extend(faces) # add faces to the mesh - + if settings.var['normals_out']: # ---------------------- + #me.flipNormals() + me.recalcNormals(0) + #me.update() if settings.var['meshSmooth_on']: # ---------------------- for i in xrange(len(faces)): me.faces[i].smooth = True @@ -1142,9 +1237,9 @@ class Polyline: #-------------------------------------------------------------- #print 'deb:drawPoly2d exit, cause POLYLINE has less than 2 vertices' #--------- return - if self.spline: pline_typ = 'ps' # Polyline-nurbSpline - elif self.curved: pline_typ = 'pc' # Polyline-bezierCurve - else: pline_typ = 'pl' # Polyline + if self.spline: pline_typ = 'ps' # Polyline-NURBSpline + elif self.curved: pline_typ = 'pc' # Polyline-BezierCurve + else: pline_typ = 'pl' # Polyline classic obname = '%s_%s' %(pline_typ, self.layer) # create object_name from layer name obname = obname[:MAX_NAMELENGTH] d_points = [] @@ -1160,6 +1255,10 @@ class Polyline: #-------------------------------------------------------------- point.loc[2] = self.elevation d_points.append(point) + #d_points = self.tribles_out(settings, d_points) + #d_points = self.doubles_out(settings, d_points) + #print 'deb:drawPolyCurve d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ + thic = set_thick(self.thic, settings) if thic != 0.0: #hack: Blender<2.45 curve-extrusion LocZ = d_points[0].loc[2] @@ -1173,12 +1272,14 @@ class Polyline: #-------------------------------------------------------------- pline = Curve.New(obname) # create new curve data #pline.setResolu(24) #--todo----- - if self.spline: # NURBSplines-----OK----- + if False: #old self.spline: # NURBSplines-----OK----- #print 'deb:polyline2dCurve.draw self.spline!' #--------------- weight1 = 0.5 weight2 = 1.0 - # generate middlepoints except start/end-segments --- - if self.curvQBspline: + if self.curvQuadrati: + # Bezier-curve form simulated in NURBS-curve + # generate middlepoints except start/end-segments --- + #print 'deb:polyline2dCurve.draw extraQBspline!' #--------------- temp_points = [] point = d_points[0].loc point.append(weight1) @@ -1231,7 +1332,27 @@ class Polyline: #-------------------------------------------------------------- else: curve.flagU = 0 # Set curve not cyclic=open - elif self.curved: #--Bezier-curves---OK------- + if self.spline: # NURBSplines-----OK----- + #print 'deb:polyline2dCurve.draw self.spline!' #--------------- + nurbs_points = [] + for d in d_points: + pkt = d.loc + pkt.append(d.weight) + nurbs_points.append(pkt) + firstpoint = nurbs_points[0] + curve = pline.appendNurb(firstpoint) + curve.setType(4) # set curvetype NURBS + for point in nurbs_points[1:]: + curve.append(point) + if self.closed: + curve.flagU = 1+0 # Set curve cyclic=close and uni + else: + curve.flagU = 0+2 # Set curve not cyclic=open + try: curve.orderU = 5 # works only with >2.46svn080625 + except AttributeError: pass + #print 'deb: dir(curve):', dir(curve) #---------------- + + elif False: #orig self.curved: #--Bezier-curves---OK------- #print 'deb:polyline2dCurve.draw self.curved!' #--------------- curve = pline.appendNurb(BezTriple.New(d_points[0])) for p in d_points[1:]: @@ -1245,7 +1366,45 @@ class Polyline: #-------------------------------------------------------------- curve[0].handleTypes = [FREE, ALIGN] #remi--todo----- curve[-1].handleTypes = [ALIGN, FREE] #remi--todo----- - else: #--straight line- and arc-segments----OK------ + elif self.curved: #--SPLINE as Bezier-curves---wip------ + #print 'deb:polyline2dCurve.draw self.curved!' #--------------- + begtangent, endtangent = None, None + if d_points[0].tangent: + begtangent = d_points[0] + d_points = d_points[1:] + if d_points[-1].tangent: + endtangent = d_points[-1] + d_points = d_points[:-1] + curve = pline.appendNurb(BezTriple.New(d_points[0])) + for p in d_points[1:]: + curve.append(BezTriple.New(p)) + for point in curve: + point.handleTypes = [AUTO, AUTO] + #curve.setType(1) #Bezier curve + if self.closed: + curve.flagU = 5 #1 # Set curve cyclic=close + else: + curve.flagU = 4 #0 # Set curve not cyclic=open + if begtangent: + #print 'deb:polyline2dCurve.draw curve[0].vec:', curve[0].vec #----- + #print 'deb:polyline2dCurve.draw begtangent:', begtangent #----- + p0h1,p0,p0h2 = curve[0].vec + p0h1 = [p0h1[i]+begtangent[i] for i in range(3)] + curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2)) + curve[0].handleTypes = [FREE, ALIGN] #remi--todo----- + if endtangent: + #print 'deb:polyline2dCurve.draw curve[-1].vec:', curve[-1].vec #----- + #print 'deb:polyline2dCurve.draw endtangent:', endtangent #----- + p0h1,p0,p0h2 = curve[-1].vec + p0h2 = [p0h2[i]+endtangent[i] for i in range(3)] + #print 'deb:drawPlineCurve: p0h2:', p0h2 #---------- + curve.__setitem__(-1,BezTriple.New(p0h1+p0+p0h2)) + #print 'deb:polyline2dCurve.draw curve[-1].vec:', curve[-1].vec #----- + curve[-1].handleTypes = [ALIGN, FREE] #remi--todo----- + + + + else: #-- only straight line- and arc-segments----OK------ #print 'deb:polyline2dCurve.draw curve:', curve #----- points = [] arc_res = settings.var['curve_arc'] @@ -1403,8 +1562,10 @@ class Polyline: #-------------------------------------------------------------- #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ #print 'deb:drawPoly2d d_pointsList ======:\n ', d_points #------------------------ + d_points = self.doubles_out(settings, d_points) + #print 'deb:drawPolyCurve d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ - # routine to sort out of "double.vertices" ------------------------------------ + """# routine to sort out of "double.vertices" ------------------------------------ minimal_dist = settings.var['dist_min'] * 0.1 temp_points = [] for i in xrange(len(d_points)-1): @@ -1419,6 +1580,7 @@ class Polyline: #-------------------------------------------------------------- #if self.closed: temp_points.append(d_points[1]) #------ loop start vertex ------------- d_points = temp_points #-----vertex.list without "double.vertices" #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ + """ #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ if len(d_points) < 2: #if too few vertex, then return @@ -1836,12 +1998,16 @@ class Vertex(object): #-------------------------------------------------------- self.swidth = None #0 self.ewidth = None #0 self.bulge = 0 + self.tangent = False + self.weight = 1.0 if obj is not None: if not obj.type == 'vertex': raise TypeError, "Wrong type %s for vertex object!" %obj.type self.type = obj.type - self.data = obj.data[:] - self.get_props(obj.data) +# self.data = obj.data[:] + self.get_props(obj) + else: + pass #print 'deb:Vertex.init.END:----------------' #------------------------ @@ -1862,18 +2028,22 @@ class Vertex(object): #-------------------------------------------------------- self.flags = getit(data, 70, 0) # flags self.curved = self.flags&1 # Bezier-curve-fit:additional-vertex - self.curv_t = self.flags&2 # Bezier-curve-fit:tangent exists - self.spline = self.flags&8 # Bspline-fit:additional-vertex - self.splin2 = self.flags&16 # Bspline-fit:control-vertex + self.curved_t = self.flags&2 # Bezier-curve-fit:tangent exists + self.spline = self.flags&8 # NURBSpline-fit:additional-vertex + self.spline_c = self.flags&16 # NURBSpline-fit:control-vertex self.poly3d = self.flags&32 # polyline3d:control-vertex self.plmesh = self.flags&64 # polymesh3d:control-vertex self.plface = self.flags&128 # polyface # if PolyFace.Vertex with Face_definition - if self.curv_t: - self.curv_tangent = getit(data, 50, None) # curve_tangent + if self.curved_t: + self.curve_tangent = getit(data, 50, None) # curve_tangent + if not self.curve_tangent==None: + self.tangent = True + #elif self.spline_c: # NURBSpline:control-vertex + # self.weight = getit(data, 41, 1.0) # weight od control point - if self.plface and not self.plmesh: + elif self.plface and not self.plmesh: v1 = getit(data, 71, 0) # polyface:Face.vertex 1. v2 = getit(data, 72, 0) # polyface:Face.vertex 2. v3 = getit(data, 73, 0) # polyface:Face.vertex 3. @@ -1938,8 +2108,7 @@ class Vertex(object): #-------------------------------------------------------- class Spline(Polyline): #----------------------------------------------------------------- """Class for objects representing dxf SPLINEs. """ - def __init__(self, obj): - """Expects an entity object of type spline as input. + """Expects an entity object of type spline as input. 100 - Subclass marker (AcDbSpline) 210,220, 230 - Normal vector (omitted if the spline is nonplanar) X,Y,Z values of normal vector 70 - Spline flag (bit coded): @@ -1963,12 +2132,13 @@ class Spline(Polyline): #------------------------------------------------------ DXF: X value; APP: 3D point, Y and Z values of control points (in WCS) (one entry per control point) 11,21, 31 - Fit points (in WCS) one entry per fit point. X,Y,Z values of fit points (in WCS) (one entry per fit point) - """ + """ + def __init__(self, obj): #print 'deb:Spline.START:----------------' #------------------------ if not obj.type == 'spline': raise TypeError, "Wrong type %s for spline object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # required data self.num_points = obj.get_type(73)[0] @@ -1992,30 +2162,42 @@ DXF: X value; APP: 3D point, Y and Z values of control points (in WCS) (one entr self.planar = self.flags & 8 # Planar self.linear = self.flags & 16 # Linear (and Planar) - self.degree = getit(obj, 71, 0) # Degree of the spline curve - self.curvNormal = False - self.curvQBspline = False - self.curvCBspline = False + self.curvNoFitted = False + self.curvQuadrati = False + self.curvCubicBsp = False self.curvBezier = False - if self.degree == 0: self.curvNormal = True - elif self.degree == 1: self.curvQBspline = True - elif self.degree == 2: self.curvCBspline = True + self.degree = getit(obj, 71, 0) # Degree of the spline curve + if self.degree == 0: self.curvNoFitted = True + elif self.degree == 1: self.curvQuadrati = True + elif self.degree == 2: self.curvCubicBsp = True #elif self.degree == 3: self.curvBezier = True - elif self.degree == 3: self.spline = True + #elif self.degree == 3: self.spline = True - self.num_knots = getit(obj, 72, 0) # Number of knots - self.num_contr = getit(obj, 73, 0) # Number of control points - self.num_fitpk = getit(obj, 74, 0) # Number of fit points (if any) + self.knotpk_len = getit(obj, 72, 0) # Number of knots + self.ctrlpk_len = getit(obj, 73, 0) # Number of control points + self.fit_pk_len = getit(obj, 74, 0) # Number of fit points (if any) - self.layer = getit(obj.data, 8, None) - self.extrusion = get_extrusion(obj.data) + #print 'deb:Spline self.fit_pk_len=', self.fit_pk_len #------------------------ + #self.fit_pk_len = 0 # temp for debug + if self.fit_pk_len and 'spline_as'==5: + self.spline = False + self.curved = True + else: + self.spline = True + self.curved = False + + self.knotpk_tol = getit(obj, 42, 0.0000001) # Knot tolerance (default = 0.0000001) + self.ctrlpk_tol = getit(obj, 43, 0.0000001) # Control-point tolerance (default = 0.0000001) + self.fit_pk_tol = getit(obj, 44, 0.0000000001) # Fit tolerance (default = 0.0000000001) + + self.layer = getit(obj, 8, None) + self.extrusion = get_extrusion(obj) + + self.pltype = 'spline' # spline is a 2D- or 3D-polyline self.points = self.get_points(obj.data) - - if self.planar: self.pltype = 'poly2d' - else: self.pltype = 'poly3d' - self.curved = False - #self.curved = False + #self.knots_val = self.get_knots_val(obj.data) # 40 - Knot value (one entry per knot) + #self.knots_wgh = self.get_knots_wgh(obj.data) # 41 - Weight (default 1) #print 'deb:Spline obj.data:\n', obj.data #------------------------ #print 'deb:Spline self.points:\n', self.points #------------------------ @@ -2032,61 +2214,70 @@ DXF: X value; APP: 3D point, Y and Z values of control points (in WCS) (one entr 20:yvalue for each vert """ - num = self.num_contr point = None points = [] + pointend = None #point = Vertex() - for item in data: - #print 'deb:Spline item:', item #------------------------ - if item[0] == 10: # control point - if point: points.append(point) - point = Vertex() - point.curved = True - point.x = item[1] - elif item[0] == 20: # 20 = y - point.y = item[1] - elif item[0] == 30: # 30 = z - point.z = item[1] + if self.spline: # NURBSpline definition + for item in data: + #print 'deb:Spline.get_points spilne_item:', item #------------------------ + if item[0] == 10: # control point + if point: points.append(point) + point = Vertex() + point.curved = True + point.x = item[1] + elif item[0] == 20: # 20 = y + point.y = item[1] + elif item[0] == 30: # 30 = z + point.z = item[1] + elif item[0] == 41: # 41 = weight + point.weight = item[1] + #print 'deb:Spline.get_points control point:', point #------------------------ - elif item[0] == 11: # fit point - if point: points.append(point) - point = Vertex() - point.curved = True - point.x = item[1] - elif item[0] == 21: # 20 = y - point.y = item[1] - elif item[0] == 31: # 30 = z - point.z = item[1] + elif self.curved: # Bezier definition + for item in data: + #print 'deb:Spline.get_points curved_item:', item #------------------------ + if item[0] == 11: # fit point + if point: points.append(point) + point = Vertex() + point.tangent = False + point.x = item[1] + elif item[0] == 21: # 20 = y + point.y = item[1] + elif item[0] == 31: # 30 = z + point.z = item[1] + #print 'deb:Spline.get_points fit point:', point #------------------------ - elif item[0] == 12: # start tangent - if point: points.append(point) - point = Vertex() - point.curved = True - point.x = item[1] - elif item[0] == 22: # = y - point.y = item[1] - elif item[0] == 32: # = z - point.z = item[1] + elif item[0] == 12: # start tangent + if point: points.append(point) + point = Vertex() + point.tangent = True + point.x = item[1] + elif item[0] == 22: # = y + point.y = item[1] + elif item[0] == 32: # = z + point.z = item[1] + #print 'deb:Spline.get_points fit begtangent:', point #------------------------ - elif item[0] == 13: # end tangent - if point: points.append(point) - point = Vertex() - point.curved = True - point.x = item[1] - elif item[0] == 23: # 20 = y - point.y = item[1] - elif item[0] == 33: # 30 = z - point.z = item[1] + elif item[0] == 13: # end tangent + if point: points.append(point) + pointend = Vertex() + pointend.tangent = True + pointend.x = item[1] + elif item[0] == 23: # 20 = y + pointend.y = item[1] + elif item[0] == 33: # 30 = z + pointend.z = item[1] + #print 'deb:Spline.get_points fit endtangent:', pointend #------------------------ points.append(point) + if self.curved and pointend: + points.append(pointend) #print 'deb:Spline points:\n', points #------------------------ return points - - def __repr__(self): return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - class LWpolyline(Polyline): #------------------------------------------------------------- @@ -2099,7 +2290,7 @@ class LWpolyline(Polyline): #-------------------------------------------------- if not obj.type == 'lwpolyline': raise TypeError, "Wrong type %s for polyline object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # required data self.num_points = obj.get_type(90)[0] @@ -2118,8 +2309,8 @@ class LWpolyline(Polyline): #-------------------------------------------------- self.flags = getit(obj, 70, 0) self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen - self.layer = getit(obj.data, 8, None) - self.extrusion = get_extrusion(obj.data) + self.layer = getit(obj, 8, None) + self.extrusion = get_extrusion(obj) self.points = self.get_points(obj.data) @@ -2167,72 +2358,10 @@ class LWpolyline(Polyline): #-------------------------------------------------- return points - def __repr__(self): return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - def draw_old(self, settings): - """for LWPOLYLINE: generate Blender_geometry. - """ - #print 'deb:LWpolyline.draw.START:----------------' #------------------------ - points = [] - obname = 'lw_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - #settings.var['curves_on'] == True - #print 'deb:index_len: ', len(self.points) #------------------ - for i, point in enumerate(self.points): - #print 'deb:index: ', i #------------------ - if not point.bulge: - points.append(point.loc) - elif point.bulge and not self.closed and i == len(self.points)-1: - points.append(point.loc) - elif point.bulge: # - if i == len(self.points)-1: - point2 = self.points[0] - else: - point2 = self.points[i+1] - arc_res = settings.var['arc_res']/sqrt(settings.var['arc_rad']) - verts, center = calcBulge(point, point2, arc_res) -# if i == len(self.points)-1: -# if self.closed: -# verts.pop() #remove last(=first) vertex -# else: -# verts.pop() #remove last vertex, because this point will be writen as the next vertex - points.extend(verts) - - thic = self.thic - if settings.var['thick_force'] and thic == 0: thic = settings.var['thick_min'] - if settings.var['thick_on'] and thic != 0: - len1 = len(points) - points.extend([[point[0], point[1], point[2]+thic] for point in points]) - faces = [] - #print 'deb:len1:', len1 #----------------------- - faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] - if self.closed: - faces.append([len1-1, 0, len1, 2*len1-1]) - #print 'deb:faces_list:\n', faces #----------------------- - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend(points) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - else: - edges = [[num, num+1] for num in xrange(len(points)-1)] - if self.closed: - edges.append([len(points)-1, 0]) - #print 'deb:edges_list:\n', edges #----------------------- - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend(points) # add vertices to mesh - me.edges.extend(edges) # add edges to the mesh - - ob.LocZ = self.elevation - transform(self.extrusion, 0, ob) - - #print 'deb:LWpolyline.draw.END:----------------' #------------------------ - return ob - - class Text: #----------------------------------------------------------------- """Class for objects representing dxf TEXT. """ @@ -2242,7 +2371,7 @@ class Text: #----------------------------------------------------------------- if not obj.type == 'text': raise TypeError, "Wrong type %s for text object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # required data self.height = 1.7 * obj.get_type(40)[0] #text.height @@ -2274,14 +2403,13 @@ class Text: #----------------------------------------------------------------- #3=aligned, 4=middle, 5=fit self.halignment = getit(obj, 72, 0) - self.layer = getit(obj.data, 8, None) - self.loc1, self.loc2 = self.get_loc(obj.data) + self.layer = getit(obj, 8, None) + self.loc1, self.loc2 = self.get_loc(obj) if self.loc2[0] != None and self.halignment != 5: self.loc = self.loc2 else: self.loc = self.loc1 - self.extrusion = get_extrusion(obj.data) - + self.extrusion = get_extrusion(obj) def get_loc(self, data): @@ -2390,13 +2518,13 @@ class Mtext: #----------------------------------------------------------------- if not obj.type == 'mtext': raise TypeError, "Wrong type %s for mtext object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # required data self.height = obj.get_type(40)[0] self.width = obj.get_type(41)[0] self.alignment = obj.get_type(71)[0] # alignment 1=TL, 2=TC, 3=TR, 4=ML, 5=MC, 6=MR, 7=BL, 8=BC, 9=BR - self.value = self.get_text(obj.data) # The text string value + self.value = self.get_text(obj) # The text string value # optional data (with defaults) self.space = getit(obj, 67, 0) @@ -2406,9 +2534,9 @@ class Mtext: #----------------------------------------------------------------- self.width_factor = getit(obj, 42, 1) # Scaling factor along local x axis self.line_space = getit(obj, 44, 1) # percentage of default - self.layer = getit(obj.data, 8, None) - self.loc = self.get_loc(obj.data) - self.extrusion = get_extrusion(obj.data) + self.layer = getit(obj, 8, None) + self.loc = self.get_loc(obj) + self.extrusion = get_extrusion(obj) def get_text(self, data): @@ -2487,7 +2615,7 @@ class Circle: #---------------------------------------------------------------- if not obj.type == 'circle': raise TypeError, "Wrong type %s for circle object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # required data self.radius = obj.get_type(40)[0] @@ -2497,9 +2625,9 @@ class Circle: #---------------------------------------------------------------- self.thic = getit(obj, 39, 0) self.color_index = getit(obj, 62, BYLAYER) - self.layer = getit(obj.data, 8, None) - self.loc = self.get_loc(obj.data) - self.extrusion = get_extrusion(obj.data) + self.layer = getit(obj, 8, None) + self.loc = self.get_loc(obj) + self.extrusion = get_extrusion(obj) @@ -2700,7 +2828,7 @@ class Arc: #----------------------------------------------------------------- if not obj.type == 'arc': raise TypeError, "Wrong type %s for arc object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # required data self.radius = obj.get_type(40)[0] @@ -2712,9 +2840,9 @@ class Arc: #----------------------------------------------------------------- self.thic = getit(obj, 39, 0) self.color_index = getit(obj, 62, BYLAYER) - self.layer = getit(obj.data, 8, None) - self.loc = self.get_loc(obj.data) - self.extrusion = get_extrusion(obj.data) + self.layer = getit(obj, 8, None) + self.loc = self.get_loc(obj) + self.extrusion = get_extrusion(obj) #print 'deb:Arc__init__: center, radius, start, end:\n', self.loc, self.radius, self.start_angle, self.end_angle #--------- @@ -2898,7 +3026,7 @@ class BlockRecord: #----------------------------------------------------------- if not obj.type == 'block_record': raise TypeError, "Wrong type %s for block_record object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # required data self.name = getit(obj, 2, None) @@ -2954,8 +3082,8 @@ class Block: #----------------------------------------------------------------- self.entities = dxfObject('block_contents') #creates empty entities_container for this block self.entities.data = objectify([ent for ent in obj.data if type(ent) != list]) - self.layer = getit(obj.data, 8, None) - self.loc = self.get_loc(obj.data) + self.layer = getit(obj, 8, None) + self.loc = self.get_loc(obj) #print 'deb:Block %s data:\n%s' %(self.name, self.data) #------------ #print 'deb:Block %s self.entities.data:\n%s' %(self.name, self.entities.data) #------------ @@ -2999,11 +3127,11 @@ class Insert: #---------------------------------------------------------------- self.space = getit(obj, 67, 0) self.color_index = getit(obj, 62, BYLAYER) - self.layer = getit(obj.data, 8, None) - self.loc = self.get_loc(obj.data) - self.scale = self.get_scale(obj.data) - self.rows, self.columns = self.get_array(obj.data) - self.extrusion = get_extrusion(obj.data) + self.layer = getit(obj, 8, None) + self.loc = self.get_loc(obj) + self.scale = self.get_scale(obj) + self.rows, self.columns = self.get_array(obj) + self.extrusion = get_extrusion(obj) #self.flags = getit(obj.data, 66, 0) # #self.attrib = self.flags & 1 @@ -3205,7 +3333,7 @@ class Ellipse: #--------------------------------------------------------------- if not obj.type == 'ellipse': raise TypeError, "Wrong type %s for ellipse object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # required data self.ratio = obj.get_type(40)[0] # Ratio of minor axis to major axis @@ -3217,10 +3345,10 @@ class Ellipse: #--------------------------------------------------------------- self.thic = getit(obj, 39, 0.0) self.color_index = getit(obj, 62, BYLAYER) - self.layer = getit(obj.data, 8, None) - self.loc = self.get_loc(obj.data) - self.major = self.get_major(obj.data) - self.extrusion = get_extrusion(obj.data) + self.layer = getit(obj, 8, None) + self.loc = self.get_loc(obj) + self.major = self.get_major(obj) + self.extrusion = get_extrusion(obj) def get_loc(self, data): @@ -3468,14 +3596,14 @@ class Face: #----------------------------------------------------------------- if not obj.type == '3dface': raise TypeError, "Wrong type %s for 3dface object!" %obj.type self.type = obj.type - self.data = obj.data[:] +# self.data = obj.data[:] # optional data (with defaults) self.space = getit(obj, 67, 0) self.color_index = getit(obj, 62, BYLAYER) - self.layer = getit(obj.data, 8, None) - self.points = self.get_points(obj.data) + self.layer = getit(obj, 8, None) + self.points = self.get_points(obj) def get_points(self, data): @@ -3582,11 +3710,11 @@ type_map = { 'point':Point, '3dface':Face, 'line':Line, -# 'mline':MLine, +# 'mline':MLine, 'polyline':Polyline, 'lwpolyline':LWpolyline, 'spline':Spline, -# 'region':Region, +# 'region':Region, 'trace':Solid, 'solid':Solid, 'text':Text, @@ -3623,12 +3751,12 @@ def objectify(data): #--------------------------------------------------------- if item.type == 'vertex': #print 'deb:objectify gosub Vertex--------' #------------- v = Vertex(item) - if pline.spline: # if Bspline-curve + if pline.spline: # if NURBSpline-curve # then for Blender-mesh filter only additional_vertices # OR # then for Blender-curve filter only spline_control_vertices - if (v.spline and not curves_on) or (curves_on and v.splin2): #correct for real NURBS-import - #if (v.spline and not curves_on) or (curves_on and not v.splin2): #fake for Bezier-emulation of NURBS-import + if (v.spline and not curves_on) or (curves_on and v.spline_c): #correct for real NURBS-import + #if (v.spline and not curves_on) or (curves_on and not v.spline_c): #fake for Bezier-emulation of NURBS-import pline.points.append(v) elif pline.curved: # if Bezier-curve # then for Blender-mesh filter only curve_additional_vertices @@ -3685,7 +3813,7 @@ class MatColors: #------------------------------------------------------------- the material. """ - def __init__(self, layersmap): + def __init__(self): """Expects a map - a dictionary mapping layer names to layers. """ #self.layersmap = layersmap # a dictionary of layername:layerobject @@ -3709,8 +3837,9 @@ class MatColors: #------------------------------------------------------------- #layer = Layer(name=color, color=256, frozen=False) #layersmap[color] = layer #color = 0 - if layersmap: color = layersmap[color].color - if color == 256: # color 0 = BYLAYER + if color in layersmap.keys(): + color = layersmap[color].color + if color == 256: # color 256 = BYLAYER #--todo-- should looking for color of LAYER #if layersmap: color = layersmap[color].color color = 3 @@ -3749,7 +3878,7 @@ class MatLayers: #------------------------------------------------------------- the material. """ - def __init__(self, layersmap): + def __init__(self): """Expects a map - a dictionary mapping layer names to layers. """ #self.layersmap = layersmap # a dictionary of layername:layer @@ -3896,6 +4025,11 @@ class Settings: #-------------------------------------------------------------- '0' ] + self.var['groupFilter_on'] = False #deb:remi------------ + self.acceptedLayers = ['3', + '0' + ] + #self.var['blockFilter_on'] = 0 #deb:remi------------ self.acceptedBlocks = ['WALL_1871', 'BOX02' @@ -3953,8 +4087,8 @@ class Settings: #-------------------------------------------------------------- if self.var['optimization'] == 0: self.var['one_mesh_on'] = 0 # The section:tables may be partialy or completely missing. self.layersTable = False - self.colMaterials = MatColors({}) #A container for dxf-color based materials - self.layMaterials = MatLayers({}) #A container for dxf-layer based materials + self.colMaterials = MatColors() #A container for dxf-color based materials + self.layMaterials = MatLayers() #A container for dxf-layer based materials #self.collayMaterials = MatColLayers({}) #A container for dxf-color+layer based materials global layersmap, layernamesmap layersmap, layernamesmap = {}, {} @@ -3974,8 +4108,8 @@ class Settings: #-------------------------------------------------------------- if layers: #---------------------------------- # Read the layers table and get the layer colors layersmap, layernamesmap = getLayersmap(layers) - self.colMaterials = MatColors(layersmap) - self.layMaterials = MatLayers(layersmap) + #self.colMaterials = MatColors() + #self.layMaterials = MatLayers() else: self.write("File contains no table:layers!") @@ -4441,19 +4575,20 @@ def rotXY_Vec(rotation, vec): #------------------------------------------------ -def getLayersmap(layers): #------------------------------------------------------ +def getLayersmap(dxflayers): #------------------------------------------------------ """Build two dictionaries: 1.layername:layer object, and 2.layername:layername_short + gets set of layers from TABLES SECTION LAYERS """ layersmap = {} layernamesmap = {} - for item in layers.data: + for item in dxflayers.data: if type(item) != list and item.type == 'layer': layersmap[item.name] = item layername_short = item.name[:MAX_NAMELENGTH-1] i = 0 #sufix for layernames cause Blender-objectnames-limits while layername_short in layernamesmap.keys(): i += 1 - suffix = str(i) + suffix = str(i) #--todo--set zero-leading number format layername_short = layername_short[:-2] + suffix layernamesmap[item.name] = layername_short @@ -4546,6 +4681,7 @@ def drawer(_type, entities, settings, block_def): #---------------------------- If 'block_def': the entities are to be added to the Blender 'group'. """ + global layersmap, layersmapshort #print 'deb:drawer _type, entities:\n ', _type, entities #----------------------- if entities: @@ -4579,6 +4715,21 @@ def drawer(_type, entities, settings, block_def): #---------------------------- #entities = [entity for entity in entities if entity.layer[0] in ['M','3','0'] and not entity.layer.endswith('H')] entities = [entity for entity in entities if entity.layer in settings.acceptedLayers] + # patch for incomplete layer table in HL2-DXF-files + if layersmap: + for entity in entities: + oblayer = entity.layer + if oblayer not in layersmap.keys(): + layer_obj = Layer(None, name=oblayer) + layersmap[oblayer] = layer_obj + layername_short = oblayer[:MAX_NAMELENGTH-1] + i = 0 #sufix for layernames cause Blender-objectnames-limits + while layername_short in layernamesmap.keys(): + i += 1 + suffix = str(i) #--todo--set zero-leading number format + layername_short = layername_short[:-2] + suffix + layernamesmap[oblayer] = layername_short + # filtering only objects on not-frozen layers if layersmap and not settings.var['layFrozen_on']: entities = [entity for entity in entities if not layersmap[entity.layer].frozen] @@ -4785,7 +4936,7 @@ def setMaterial_from(entity, ob, settings, block_def): #----------------------- mat = settings.colMaterials(entity.color_index) elif settings.var['material_from'] == 2: # 2= material from layer_name - mat = settings.layMaterials(layername = entity.layer) + mat = settings.layMaterials(layername=entity.layer) elif settings.var['material_from'] == 3: # 3= material from layer+color mat = settings.layMaterials(layername=entity.layer, color=entity.color_index) @@ -5104,7 +5255,7 @@ EVENT_HELP = 9 EVENT_PRESETCURV = 10 EVENT_PRESETS = 11 EVENT_DXF_DIR = 12 -EVENT_DXF_NAME = 13 +# = 13 EVENT_LIST = 14 EVENT_ORIGIN = 15 EVENT_SCALE = 16 @@ -5119,12 +5270,12 @@ GUI_B = {} # GUI-buttons dictionary for drawingTypes # settings default, initialize ------------------------ points_as_menu = "convert to: %t|empty %x1|mesh.vertex %x2|thin sphere %x3|thin box %x4|*curve.vertex %x5" -lines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|thin box %x4|curve %x5" +lines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|thin box %x4|Bezier-curve %x5|NURBS-curve %x6" mlines_as_menu = "convert to: %t|*edge %x1|*mesh %x2|*thin cylinder %x3|*thin box %x|*curve %x5" -plines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|curve %x5" -splines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|curve %x5" -plines3_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|curve %x5" -plmesh_as_menu = "convert to: %t|*edge %x1|mesh %x2" +plines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6" +splines_as_menu = "convert to: %t|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6" +plines3_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6" +plmesh_as_menu = "convert to: %t|*edge %x1|mesh %x2|NURBS-surface %x6" solids_as_menu = "convert to: %t|*edge %x1|mesh %x2" blocks_as_menu = "convert to: %t|dupliGroup %x1|*real.Group %x2|*exploded %x3" texts_as_menu = "convert to: %t|text %x1|*mesh %x2|*curve %x5" @@ -5166,6 +5317,9 @@ keywords_org = { 'xref_on' : 1, 'block_nn': 0, 'blockFilter_on': 0, + 'layerFilter_on': 0, + 'colorFilter_on': 0, + 'groupFilter_on': 0, 'newScene_on' : 1, 'target_layer' : TARGET_LAYER, 'group_bylayer_on' : GROUP_BYLAYER, @@ -5187,7 +5341,6 @@ keywords_org = { 'dist_force': 0, 'material_on': 1, 'material_from': 2, - 'pl_3d' : 1, 'fill_on' : 1, 'meshSmooth_on': 1, 'curve_res' : CURV_RESOLUTION, @@ -5197,6 +5350,8 @@ keywords_org = { 'thin_res' : THIN_RESOLUTION, 'pl_trim_max' : TRIM_LIMIT, 'pl_trim_on': 1, + 'plmesh_flip': 0, + 'normals_out': 0, 'paper_space_on': 0, 'layFrozen_on': 0, 'Z_force_on': 0, @@ -5205,7 +5360,7 @@ keywords_org = { 'lines_as' : 2, 'mlines_as' : 2, 'plines_as' : 2, - 'splines_as' : 2, + 'splines_as' : 5, 'plines3_as': 2, 'plmesh_as' : 2, 'solids_as' : 2, @@ -5221,7 +5376,7 @@ drawTypes_org = { 'ellipse': 1, 'mline' : 0, 'polyline': 1, - 'spline': 0, + 'spline': 1, 'plmesh': 1, 'pline3': 1, 'lwpolyline': 1, @@ -5244,6 +5399,9 @@ for k, v in drawTypes_org.iteritems(): GUI_B[k] = Draw.Create(v) #print 'deb:init GUI_A: ', GUI_A #--------------- #print 'deb:init GUI_B: ', GUI_B #--------------- + +model_space_on = Draw.Create(1) + # initialize settings-object controls how dxf entities are drawn settings = Settings(keywords_org, drawTypes_org) @@ -5397,12 +5555,13 @@ def resetDefaultConfig(): #----------------------------------------------- updateConfig(keywords_org, drawTypes_org) -def presetConfig_curv(): #----------------------------------------------- +def presetConfig_curv(activate): #----------------------------------------------- """Sets settings/config/materials for curve representation. """ global GUI_A - if GUI_A['curves_on'].val == 1: + if activate: + GUI_A['curves_on'].val = 1 GUI_A['points_as'].val = 5 GUI_A['lines_as'].val = 5 GUI_A['mlines_as'].val = 5 @@ -5410,11 +5569,12 @@ def presetConfig_curv(): #----------------------------------------------- GUI_A['splines_as'].val = 5 GUI_A['plines3_as'].val = 5 else: + GUI_A['curves_on'].val = 0 GUI_A['points_as'].val = 2 GUI_A['lines_as'].val = 2 GUI_A['mlines_as'].val = 2 GUI_A['plines_as'].val = 2 - GUI_A['splines_as'].val = 2 + GUI_A['splines_as'].val = 6 GUI_A['plines3_as'].val = 2 @@ -5422,7 +5582,7 @@ def resetDefaultConfig_2D(): #----------------------------------------------- """Sets settings/config/materials to defaults 2D. """ -# presetConfig_curv() + presetConfig_curv(1) keywords2d = { 'views_on' : 0, 'cams_on' : 0, @@ -5434,7 +5594,6 @@ def resetDefaultConfig_2D(): #----------------------------------------------- 'width_force': 0, 'dist_on' : 1, 'dist_force': 0, - 'pl_3d' : 0, 'fill_on' : 0, 'pl_trim_on': 1, 'Z_force_on': 0, @@ -5452,9 +5611,9 @@ def resetDefaultConfig_2D(): #----------------------------------------------- 'ellipse': 1, 'mline' : 0, 'polyline': 1, - 'spline': 0, + 'spline': 1, 'plmesh': 0, - 'pline3': 0, + 'pline3': 1, 'lwpolyline': 1, 'text' : 1, 'mtext' : 0, @@ -5472,8 +5631,11 @@ def resetDefaultConfig_3D(): #----------------------------------------------- """Sets settings/config/materials to defaults 3D. """ -# presetConfig_curv() + presetConfig_curv(0) keywords3d = { +# 'views_on' : 1, +# 'cams_on' : 1, +# 'lights_on' : 1, 'vGroup_on' : 1, 'thick_on' : 1, 'thick_force': 0, @@ -5481,7 +5643,6 @@ def resetDefaultConfig_3D(): #----------------------------------------------- 'width_force': 0, 'dist_on' : 1, 'dist_force': 0, - 'pl_3d' : 0, 'fill_on' : 1, 'pl_trim_on': 1, 'Z_force_on': 0, @@ -5499,11 +5660,11 @@ def resetDefaultConfig_3D(): #----------------------------------------------- 'ellipse': 1, 'mline' : 0, 'polyline': 1, - 'spline': 0, + 'spline': 1, 'plmesh': 1, 'pline3': 1, 'lwpolyline': 1, - 'text' : 1, + 'text' : 0, 'mtext' : 0, 'block' : 1, 'insert': 1, @@ -5557,6 +5718,7 @@ def draw_UI(): #--------------------------------------------------------------- """ global GUI_A, GUI_B #__version__ global user_preset, iniFileName, dxfFileName, config_UI, g_scale_as + global model_space_on # This is for easy layout changes but_0c = 70 #button 1.column width @@ -5567,8 +5729,8 @@ def draw_UI(): #--------------------------------------------------------------- butt_margin = 10 menu_w = (3 * butt_margin) + but_0c + but_1c + but_2c + but_3c #menu width - simple_menu_h = 80 - extend_menu_h = 370 + simple_menu_h = 100 + extend_menu_h = 350 y = simple_menu_h # y is menu upper.y if config_UI.val: y += extend_menu_h x = 20 #menu left.x @@ -5584,7 +5746,7 @@ def draw_UI(): #--------------------------------------------------------------- y += 30 colorbox(x, y+20, x+menu_w+menu_margin*2, menu_margin) - Draw.Label("DXF-Importer ver." + __version__, but0c, y, menu_w, 20) + Draw.Label("DXF-Importer v" + __version__, but0c, y, menu_w, 20) if config_UI.val: b0, b0_ = but0c, but_0c + butt_margin @@ -5645,25 +5807,23 @@ def draw_UI(): #--------------------------------------------------------------- y -= 10 y -= 20 Draw.BeginAlign() - GUI_B['plmesh'] = Draw.Toggle('POLY-MESH/FACE', EVENT_NONE, b0, y, b0_+b1_, 20, GUI_B['plmesh'].val, "support dxf-POLYMESH/POLYFACE on/off") + GUI_B['plmesh'] = Draw.Toggle('PL-MESH/FACE', EVENT_NONE, b0, y, b0_+b1_-40, 20, GUI_B['plmesh'].val, "support dxf-POLYMESH/POLYFACE on/off") # GUI_A['plmesh_as'] = Draw.Menu(plmesh_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['plmesh_as'].val, "select target Blender-object") + GUI_A['plmesh_flip'] = Draw.Toggle('N', EVENT_NONE, b1+b1_-40, y, 20, 20, GUI_A['plmesh_flip'].val, "flip DXF normals on/off") + GUI_A['normals_out'] = Draw.Toggle('N', EVENT_NONE, b1+b1_-20, y, 20, 20, GUI_A['normals_out'].val, "force Blender normals to outside on/off") Draw.EndAlign() y -= 20 - Draw.BeginAlign() GUI_B['solid'] = Draw.Toggle('SOLID', EVENT_NONE, b0, y, b0_, 20, GUI_B['solid'].val, "support dxf-SOLID and TRACE on/off") GUI_B['face'] = Draw.Toggle('3DFACE', EVENT_NONE, b1, y, b1_, 20, GUI_B['face'].val, "support dxf-3DFACE on/off") # GUI_A['solids_as'] = Draw.Menu(solids_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['solids_as'].val, "select target Blender-object") - Draw.EndAlign() #print 'deb:support solid, trace', GUI_B['trace'].val, GUI_B['solid'].val # ------------ y -= 20 - Draw.BeginAlign() GUI_B['text'] = Draw.Toggle('TEXT', EVENT_NONE, b0, y, b0_, 20, GUI_B['text'].val, "support dxf-TEXT on/off") GUI_B['mtext'] = Draw.Toggle('*MTEXT', EVENT_NONE, b1, y, b1_, 20, GUI_B['mtext'].val, "(*wip)support dxf-MTEXT on/off") # GUI_A['texts_as'] = Draw.Menu(texts_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['texts_as'].val, "select target Blender-object") - Draw.EndAlign() y -= 20 Draw.BeginAlign() @@ -5671,13 +5831,14 @@ def draw_UI(): #--------------------------------------------------------------- GUI_B['insert'].val = GUI_B['block'].val if GUI_B['block'].val: GUI_A['block_nn'] = Draw.Toggle('n', EVENT_NONE, b1-30, y, 15, 20, GUI_A['block_nn'].val, "support hatch/noname BLOCKs *X... on/off") - GUI_A['blockFilter_on'] = Draw.Toggle('F', EVENT_NONE, b1-15, y, 15, 20, GUI_A['blockFilter_on'].val, "(*wip) support name filtering of BLOCKs on/off") - GUI_A['xref_on'] = Draw.Toggle('Xref', EVENT_NONE, b1, y, 20, 20, GUI_A['xref_on'].val, "support place holder for XREF-BLOCKs on/off") + GUI_A['xref_on'] = Draw.Toggle('Xref', EVENT_NONE, b1-15, y, 35, 20, GUI_A['xref_on'].val, "support for XREF-BLOCKs (place holders) on/off") GUI_A['blocks_as'] = Draw.Menu(blocks_as_menu, EVENT_NONE, b1+20, y, b1_-20, 20, GUI_A['blocks_as'].val, "select target representation for imported BLOCKs") Draw.EndAlign() y -= 20 + y -= 20 + Draw.BeginAlign() GUI_A['views_on'] = Draw.Toggle('views', EVENT_NONE, b0, y, b0_-25, 20, GUI_A['views_on'].val, "imports VIEWs and VIEWPORTs as cameras on/off") GUI_A['cams_on'] = Draw.Toggle('*cams', EVENT_NONE, b1-25, y, b1_-25, 20, GUI_A['cams_on'].val, "(*wip) support ASHADE cameras on/off") @@ -5688,19 +5849,28 @@ def draw_UI(): #--------------------------------------------------------------- if y < y_down: y_down = y # -----end supported objects-------------------------------------- - b0, b0_ = but0c, but_0c + butt_margin - b1, b1_ = but1c, but_1c - y_top = y_down y = y_top y -= 10 y -= 20 + but_ = menu_w / 6 + b0 = but0c + (menu_w - but_*6)/2 Draw.BeginAlign() - GUI_A['material_on'] = Draw.Toggle('material', EVENT_REDRAW, b0, y, b0_-20, 20, GUI_A['material_on'].val, "support for material assignment on/off") - if GUI_A['material_on'].val: - GUI_A['material_from'] = Draw.Menu(material_from_menu, EVENT_NONE, b1-20, y, b1_+20, 20, GUI_A['material_from'].val, "material assignment from?") + GUI_A['paper_space_on'] = Draw.Toggle('paper', EVENT_NONE, b0+but_*0, y, but_, 20, GUI_A['paper_space_on'].val, "import only from Paper-Space on/off") + GUI_A['layFrozen_on'] = Draw.Toggle ('frozen', EVENT_NONE, b0+but_*1, y, but_, 20, GUI_A['layFrozen_on'].val, "import also from frozen LAYERs on/off") + GUI_A['layerFilter_on'] = Draw.Toggle('layer', EVENT_NONE, b0+but_*2, y, but_, 20, GUI_A['layerFilter_on'].val, "(*wip) LAYER filtering on/off") + GUI_A['colorFilter_on'] = Draw.Toggle('color', EVENT_NONE, b0+but_*3, y, but_, 20, GUI_A['colorFilter_on'].val, "(*wip) COLOR filtering on/off") + GUI_A['groupFilter_on'] = Draw.Toggle('group', EVENT_NONE, b0+but_*4, y, but_, 20, GUI_A['groupFilter_on'].val, "(*wip) GROUP filtering on/off") + GUI_A['blockFilter_on'] = Draw.Toggle('block', EVENT_NONE, b0+but_*5, y, but_, 20, GUI_A['blockFilter_on'].val, "(*wip) BLOCK filtering on/off") + #GUI_A['dummy_on'] = Draw.Toggle('-', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['dummy_on'].val, "dummy on/off") Draw.EndAlign() + # -----end filters-------------------------------------- + + b0, b0_ = but0c, but_0c + butt_margin + b1, b1_ = but1c, but_1c + + y -= 10 y -= 20 Draw.BeginAlign() GUI_A['g_origin_on'] = Draw.Toggle('glob.reLoc', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_origin_on'].val, "global relocate all DXF objects on/off") @@ -5750,9 +5920,9 @@ def draw_UI(): #--------------------------------------------------------------- y -= 10 y -= 20 Draw.BeginAlign() - GUI_A['meshSmooth_on'] = Draw.Toggle('smooth', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['meshSmooth_on'].val, "mesh smooth for circles/arcsegments on/off") - GUI_A['pl_trim_on'] = Draw.Toggle('trim', EVENT_NONE, b1-20, y, 32, 20, GUI_A['pl_trim_on'].val, "intersection of POLYLINE-wide-segments on/off") - GUI_A['pl_trim_max'] = Draw.Number('', EVENT_NONE, b1+12, y, b1_-12, 20, GUI_A['pl_trim_max'].val, 0, 5, "limit for intersection of POLYLINE-wide-segments: 0.0-5.0") + GUI_A['meshSmooth_on'] = Draw.Toggle('smooth', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['meshSmooth_on'].val, "mesh smooth for circles/arc-segments on/off") + GUI_A['pl_trim_on'] = Draw.Toggle('trim', EVENT_NONE, b1-20, y, 32, 20, GUI_A['pl_trim_on'].val, "clean intersection of POLYLINE-wide-segments on/off") + GUI_A['pl_trim_max'] = Draw.Number('', EVENT_NONE, b1+12, y, b1_-12, 20, GUI_A['pl_trim_max'].val, 0, 5, "threshold intersection of POLYLINE-wide-segments: 0.0-5.0") Draw.EndAlign() y -= 20 @@ -5765,21 +5935,21 @@ def draw_UI(): #--------------------------------------------------------------- y -= 20 Draw.BeginAlign() - GUI_A['curves_on'] = Draw.Toggle('to Curves', EVENT_PRESETCURV, b0, y, b0_, 20, GUI_A['curves_on'].val, "import into curves instead into meshes on/off") - GUI_A['curve_arc'] = Draw.Number('', EVENT_NONE, b1, y, b1_/2, 20, GUI_A['curve_arc'].val, 3, 32, "Bezier circle: amount of segments: 3-32") - GUI_A['curve_res'] = Draw.Number('', EVENT_NONE, b1+b1_/2, y, b1_/2, 20, GUI_A['curve_res'].val, 1, 128, "Set the Curve's U-resolution value: 1-128") + GUI_A['curve_arc'] = Draw.Number('', EVENT_NONE, b0, y, b0_/2, 20, GUI_A['curve_arc'].val, 3, 32, "Bezier circle: amount of segments: 3-32") + GUI_A['curve_res'] = Draw.Number('', EVENT_NONE, b0+b0_/2, y, b0_/2, 20, GUI_A['curve_res'].val, 1, 128, "Set the Curve's U-resolution value: 1-128") + GUI_A['curves_on'] = Draw.Toggle('to Curves', EVENT_PRESETCURV, b1, y, b1_, 20, GUI_A['curves_on'].val, "set Curve as target object type on/off") Draw.EndAlign() y -= 20 - GUI_A['group_bylayer_on'] = Draw.Toggle('Lay', EVENT_NONE, b0, y, 30, 20, GUI_A['group_bylayer_on'].val, "grouping entities from the same layer on/off") - GUI_A['vGroup_on'] = Draw.Toggle('vGroups', EVENT_NONE, b0+30, y, b1_-10, 20, GUI_A['vGroup_on'].val, "support Blender-VertexGroups on/off") + GUI_A['group_bylayer_on'] = Draw.Toggle('Layer', EVENT_NONE, b0, y, 30, 20, GUI_A['group_bylayer_on'].val, "DXF-entities group by layer on/off") + GUI_A['vGroup_on'] = Draw.Toggle('vGroups', EVENT_NONE, b0+30, y, b1_-10, 20, GUI_A['vGroup_on'].val, "sort faces into VertexGroups on/off") GUI_A['one_mesh_on'] = Draw.Toggle('oneMesh', EVENT_NONE, b1+10, y, b1_-10, 20, GUI_A['one_mesh_on'].val, "draw DXF-entities into one mesh-object. Recommended for big DXF-files. on/off") y -= 30 Draw.BeginAlign() - GUI_A['paper_space_on'] = Draw.Toggle('paper space', EVENT_NONE, b0, y, b0_+20, 20, GUI_A['paper_space_on'].val, "import only layout (paper space) on/off") - GUI_A['layFrozen_on'] = Draw.Toggle('frozen', EVENT_NONE, b1+20, y, b1_-20, 20, GUI_A['layFrozen_on'].val, "import also from frozen layers on/off") - #GUI_A['dummy_on'] = Draw.Toggle('-', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['dummy_on'].val, "dummy on/off") + GUI_A['material_on'] = Draw.Toggle('material', EVENT_REDRAW, b0, y, b0_-20, 20, GUI_A['material_on'].val, "support for material assignment on/off") + if GUI_A['material_on'].val: + GUI_A['material_from'] = Draw.Menu(material_from_menu, EVENT_NONE, b1-20, y, b1_+20, 20, GUI_A['material_from'].val, "material assignment from?") Draw.EndAlign() y_down = y @@ -5821,8 +5991,9 @@ def draw_UI(): #--------------------------------------------------------------- Draw.EndAlign() y -= 30 - GUI_A['newScene_on'] = Draw.Toggle('newScene', EVENT_NONE, b0, y, b0_, 20, GUI_A['newScene_on'].val, "creates new Blender-Scene for each import on/off") - GUI_A['target_layer'] = Draw.Number('layer', EVENT_NONE, b1, y, b1_, 20, GUI_A['target_layer'].val, 1, 18, "imports into this Blender-layer (<19> reserved for block_definitions)") + but, but_ = but2c, 25 + Draw.BeginAlign() + Draw.EndAlign() if y < y_down: y_down = y # -----end options -------------------------------------- @@ -5835,45 +6006,60 @@ def draw_UI(): #--------------------------------------------------------------- y -= 30 Draw.BeginAlign() Draw.PushButton('INI file >', EVENT_CHOOSE_INI, but0c, y, but_0c, 20, 'Select INI-file from project directory') - iniFileName = Draw.String(' :', EVENT_NONE, but1c, y, menu_w-but_0c-butt_margin, 20, iniFileName.val, FILENAME_MAX, "write here the name of the INI-file") + iniFileName = Draw.String(' :', EVENT_NONE, but1c, y, menu_w-but_1c-60, 20, iniFileName.val, FILENAME_MAX, "write here the name of the INI-file") + but = but4c-60 + Draw.PushButton('#', EVENT_PRESETS, but, y, 20, 20, "toggle Preset-INI-files") + Draw.PushButton('L', EVENT_LOAD_INI, but+20, y, 20, 20, 'Loads configuration from ini-file: %s' % iniFileName.val) + Draw.PushButton('S', EVENT_SAVE_INI, but+40, y, 20, 20, 'Saves configuration to ini-file: %s' % iniFileName.val) Draw.EndAlign() - y -= 20 - Draw.BeginAlign() - Draw.PushButton('#', EVENT_PRESETS, but0c, y, 20, 20, "tipist for Preset-INI-files") - Draw.PushButton('Load', EVENT_LOAD_INI, but0c+20, y, but_0c-20, 20, '.Loads configuration from ini-file: %s' % iniFileName.val) - Draw.PushButton('Save', EVENT_SAVE_INI, but1c, y, but_1c-20, 20, 'Saves configuration to ini-file: %s' % iniFileName.val) - Draw.EndAlign() - but_ = (but_2c+but_3c)/4 - but = but2c - Draw.PushButton('reset', EVENT_RESET, but, y, but_, 20, "reset configuration to defaults") - Draw.PushButton('2D', EVENT_PRESET2D, but+but_, y, but_, 20, 'set configuration for 2D import') - Draw.PushButton('3D', EVENT_PRESET3D, but+but_*2, y, but_, 20, 'set configuration for 3D import') - GUI_A['optimization'] = Draw.Number('', EVENT_NONE, but4c-35, y, 35, 20, GUI_A['optimization'].val, 0, 3, "Optimization Level: 0=Debug/directDrawing, 1=Verbose, 2=ProgressBar, 3=silentMode/fastest") + b0, b0_ = but2c, but_2c + butt_margin + b1, b1_ = but3c, but_3c y = simple_menu_h + bm = butt_margin/2 + + #y -= 10 Draw.BeginAlign() Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF-file from project directory') dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, but_1c+but_2c+but_3c-20, 20, dxfFileName.val, FILENAME_MAX, "type the name of DXF-file or type *.dxf for multi-import") - Draw.PushButton('*.*', EVENT_DXF_DIR, but3c+but_3c-20, y, 20, 20, 'Set asterisk * as filter') + Draw.PushButton('*.*', EVENT_DXF_DIR, but3c+but_3c-20, y, 20, 20, 'import all dxf files from this directory') Draw.EndAlign() - - y -= 50 + y -= 30 + config_UI = Draw.Toggle('CONFIG', EVENT_REDRAW, but0c, y, but_0c+bm, 20, config_UI.val, 'Advanced configuration on/off' ) Draw.BeginAlign() - Draw.PushButton('EXIT', EVENT_EXIT, but0c, y, but_0c, 40, '' ) - Draw.PushButton('HELP', EVENT_HELP, but1c, y, but_1c-20, 20, 'calls BlenderWiki for Manual, Updates and Support.') - Draw.PushButton('?', EVENT_LIST, but1c+but_1c-20, y, 20, 20, 'DXF analyze tool: print listing of LAYERs and BLOCKs into the text file .INF') - Draw.PushButton('START IMPORT', EVENT_START, but2c, y, but_2c+but_3c+butt_margin, 40, 'Start the import procedure') + but, but_ = but1c, but_1c+bm + but_ /= 3 + Draw.PushButton('X', EVENT_RESET, but, y, 15, 20, "reset configuration to defaults") + Draw.PushButton('2D', EVENT_PRESET2D, but+but_, y, but_, 20, 'set configuration for 2D import') + Draw.PushButton('3D', EVENT_PRESET3D, but+(but_*2), y, but_, 20, 'set configuration for 3D import') Draw.EndAlign() - config_UI = Draw.Toggle('CONFIG', EVENT_REDRAW, but1c-butt_margin/2, y+20, but_1c+butt_margin, 20, config_UI.val, 'Advanced configuration on/off' ) + Draw.BeginAlign() + GUI_A['newScene_on'] = Draw.Toggle('newScene', EVENT_NONE, but2c, y, but_2c, 20, GUI_A['newScene_on'].val, "create new Scene for each imported dxf file on/off") + GUI_A['target_layer'] = Draw.Number('layer', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['target_layer'].val, 1, 18, "target Blender-layer (<19> reserved for block_definitions)") + Draw.EndAlign() + + y -= 40 + Draw.PushButton('EXIT', EVENT_EXIT, but0c, y, but_0c+bm, 20, '' ) + Draw.PushButton('HELP', EVENT_HELP, but1c, y, but_1c+bm, 20, 'calls DXF-Importer Manual Page on Wiki.Blender.org') + Draw.BeginAlign() + GUI_A['optimization'] = Draw.Number('', EVENT_NONE, but2c, y+20, 40, 20, GUI_A['optimization'].val, 0, 3, "Optimization Level: 0=Debug/directDrawing, 1=Verbose, 2=ProgressBar, 3=SilentMode") + Draw.EndAlign() + Draw.BeginAlign() + Draw.PushButton('TEST', EVENT_LIST, but2c, y, 40, 20, 'DXF-Analyze-Tool: reads data from selected dxf file and writes report in project_directory/dxf_blendname.INF') + Draw.PushButton('START IMPORT', EVENT_START, but2c+40, y, but_2c-40+but_3c+butt_margin, 40, 'Start the import process. For Cancel go to console and hit Ctrl-C') + Draw.EndAlign() + + + y -= 20 Draw.BeginAlign() Draw.Label(' ', but0c-menu_margin, y, menu_margin, 20) - Draw.Label("*) parts under construction", but0c, y, menu_w, 20) + Draw.Label(LAB, but0c, y, menu_w, 20) Draw.Label(' ', but0c+menu_w, y, menu_margin, 20) Draw.EndAlign() @@ -5930,7 +6116,7 @@ def bevent(evt): resetDefaultConfig_3D() Draw.Redraw() elif (evt==EVENT_PRESETCURV): - presetConfig_curv() + presetConfig_curv(GUI_A['curves_on'].val) Draw.Redraw() elif (evt==EVENT_PRESETS): user_preset += 1 @@ -5974,11 +6160,6 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') # update_RegistryKey('dxfFileName', dxfFileName.val) GUI_A['newScene_on'].val = 1 Draw.Redraw() -# elif (evt==EVENT_DXF_NAME): -# dirname == Blender.sys.dirname(Blender.Get('filename')) -# update_RegistryKey('DirName', dirname) -# #print 'deb:EVENT_DXF_NAME dxfFileName.val:', dxfFileName.val #-------------- -# update_RegistryKey('dxfFileName', dxfFileName.val) elif (evt==EVENT_CHOOSE_DXF): filename = '' # '*.dxf' if dxfFileName.val: filename = dxfFileName.val @@ -5986,6 +6167,7 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') elif (evt==EVENT_START): dxfFile = dxfFileName.val #print 'deb: dxfFile file: ', dxfFile #---------------------- + if E_M: dxfFileName.val, dxfFile = e_mode(dxfFile) #evaluation mode update_RegistryKey('dxfFileName', dxfFileName.val) if dxfFile.lower().endswith('*.dxf'): if Draw.PupMenu('DXF importer: OK?|will import all DXF-files from:|%s' % dxfFile) == 1: From b647c5bba52867ac76543744bccbea8c77c902b7 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 3 Aug 2008 16:11:57 +0000 Subject: [PATCH 45/58] == FFMPEG == This fixes: [#16655] Blender crashes when Fraps videos are added to the sequencer (sorry, color conversion is not supported by swscaler for some reason, so currently, only the crash is fixed) --- source/blender/imbuf/intern/anim.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c index 720f5b0f7c8..c0e84b73e47 100644 --- a/source/blender/imbuf/intern/anim.c +++ b/source/blender/imbuf/intern/anim.c @@ -612,6 +612,7 @@ static int startffmpeg(struct anim * anim) { av_free(anim->pFrameRGB); av_free(anim->pFrameDeinterlaced); av_free(anim->pFrame); + anim->pCodecCtx = NULL; return -1; } @@ -639,7 +640,19 @@ static int startffmpeg(struct anim * anim) { PIX_FMT_BGR32, SWS_FAST_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL); - + + if (!anim->img_convert_ctx) { + fprintf (stderr, + "Can't transform color space??? Bailing out...\n"); + avcodec_close(anim->pCodecCtx); + av_close_input_file(anim->pFormatCtx); + av_free(anim->pFrameRGB); + av_free(anim->pFrameDeinterlaced); + av_free(anim->pFrame); + anim->pCodecCtx = NULL; + return -1; + } + return (0); } From df2364ab1a4ad4e09a3870c622d4e41099870e34 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 3 Aug 2008 21:57:52 +0000 Subject: [PATCH 46/58] Update MSVC project files for new Boolean Operation file (BOP_Merge2.cpp) --- intern/boolop/make/msvc_7_0/boolop.vcproj | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/intern/boolop/make/msvc_7_0/boolop.vcproj b/intern/boolop/make/msvc_7_0/boolop.vcproj index 7ae417e42d5..6e6d6abeb43 100644 --- a/intern/boolop/make/msvc_7_0/boolop.vcproj +++ b/intern/boolop/make/msvc_7_0/boolop.vcproj @@ -278,6 +278,9 @@ ECHO Done + + @@ -330,9 +333,15 @@ ECHO Done + + + + From ae762bec91a75a3e66ac7876bb4f0eb23472f7e4 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 3 Aug 2008 21:59:36 +0000 Subject: [PATCH 47/58] BGE patch #17398 approved: implementation of BGE method getVectTo(). --- source/gameengine/Ketsji/KX_GameObject.cpp | 52 ++++++++++++++++++++++ source/gameengine/Ketsji/KX_GameObject.h | 1 + source/gameengine/PyDoc/KX_GameObject.py | 10 +++++ 3 files changed, 63 insertions(+) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 02d1ad1b12b..6e922e421ac 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -914,6 +914,7 @@ PyMethodDef KX_GameObject::Methods[] = { KX_PYMETHODTABLE(KX_GameObject, rayCastTo), KX_PYMETHODTABLE(KX_GameObject, rayCast), KX_PYMETHODTABLE(KX_GameObject, getDistanceTo), + KX_PYMETHODTABLE(KX_GameObject, getVectTo), {NULL,NULL} //Sentinel }; @@ -1555,6 +1556,57 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo, return NULL; } +KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, +"getVectTo(other): get vector and the distance to another point/KX_GameObject\n" +"Returns a 3-tuple with (distance,worldVector,localVector)\n") +{ + MT_Point3 toPoint, fromPoint; + MT_Vector3 toDir, locToDir; + MT_Scalar distance; + + PyObject *returnValue = PyTuple_New(3); + PyObject *pyother; + + if (!returnValue) + { + PyErr_SetString(PyExc_MemoryError, "PyTuple_New() failed"); + return NULL; + } + if (!PyVecArgTo(args, toPoint)) + { + PyErr_Clear(); + if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &pyother)) + { + KX_GameObject *other = static_cast(pyother); + toPoint = other->NodeGetWorldPosition(); + }else + { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); + return NULL; + } + } + + fromPoint = NodeGetWorldPosition(); + toDir = toPoint-fromPoint; + distance = toDir.length(); + + if (MT_fuzzyZero(distance)) + { + //cout << "getVectTo() Error: Null vector!\n"; + locToDir = toDir = MT_Vector3(0.0,0.0,0.0); + distance = 0.0; + } else { + toDir.normalize(); + locToDir = toDir * NodeGetWorldOrientation(); + } + + PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance)); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir)); + + return returnValue; +} + bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 1d36798b12f..4e435e9ddf4 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -756,6 +756,7 @@ public: KX_PYMETHOD_DOC(KX_GameObject,rayCastTo); KX_PYMETHOD_DOC(KX_GameObject,rayCast); KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo); + KX_PYMETHOD_DOC(KX_GameObject,getVectTo); private : diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index 8f17cf26f15..a5ba5b1d634 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -253,6 +253,16 @@ class KX_GameObject: @type other: L{KX_GameObject} or list [x, y, z] @rtype: float """ + def getVectTo(other): + """ + Returns the vector and the distance to another object or point. + The vector is normalized unless the distance is 0, in which a NULL vector is returned. + + @param other: a point or another L{KX_GameObject} to get the vector and distance to. + @type other: L{KX_GameObject} or list [x, y, z] + @rtype: 3-tuple (float, 3-tuple (x,y,z), 3-tuple (x,y,z)) + @return: (distance, globalVector(3), localVector(3)) + """ def rayCastTo(other,dist,prop): """ Look towards another point/object and find first object hit within dist that matches prop. From 3598dcd2796f819bd762f88c2d275816fed0e0d6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Aug 2008 01:57:22 +0000 Subject: [PATCH 48/58] * KX_GameObject.cpp - error with getMesh(), was returning None rather then an error with invalid args. also memory leak with getVectTo() if invalid args were given. * Material.c - functions for get/setRayTransGlossSamples were not being used. * BPY_interface.c - removed function GetName(), since everything else just uses id->name+2. * header_info.c - added ifdef win32 around copy_game_dll since its not needed for other os's yet --- source/blender/python/BPY_interface.c | 28 +++--------- source/blender/python/api2_2x/Material.c | 12 ++++-- source/blender/src/header_info.c | 2 + source/gameengine/Ketsji/KX_GameObject.cpp | 50 ++++++++++------------ 4 files changed, 39 insertions(+), 53 deletions(-) diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 7120e97a62f..06e8c564ef0 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -160,7 +160,6 @@ ScriptError g_script_error; * Function prototypes ***************************************************************************/ PyObject *RunPython( Text * text, PyObject * globaldict ); -char *GetName( Text * text ); PyObject *CreateGlobalDictionary( void ); void ReleaseGlobalDictionary( PyObject * dict ); void DoAllScriptsFromList( ListBase * list, short event ); @@ -651,7 +650,7 @@ int BPY_txt_do_python_Text( struct Text *text ) } /* Create a new script structure and initialize it: */ - script = alloc_libblock( &G.main->script, ID_SCRIPT, GetName( text ) ); + script = alloc_libblock( &G.main->script, ID_SCRIPT, text->id.name+2 ); if( !script ) { printf( "couldn't allocate memory for Script struct!" ); @@ -662,8 +661,7 @@ int BPY_txt_do_python_Text( struct Text *text ) * an error after it will call BPY_Err_Handle below, but the text struct * will have been deallocated already, so we need to copy its name here. */ - BLI_strncpy( textname, GetName( text ), - strlen( GetName( text ) ) + 1 ); + BLI_strncpy( textname, text->id.name+2, 21 ); script->id.us = 1; script->flags = SCRIPT_RUNNING; @@ -2724,8 +2722,7 @@ PyObject *RunPython( Text * text, PyObject * globaldict ) buf = txt_to_buf( text ); text->compiled = - Py_CompileString( buf, GetName( text ), - Py_file_input ); + Py_CompileString( buf, text->id.name+2, Py_file_input ); MEM_freeN( buf ); @@ -2739,15 +2736,6 @@ PyObject *RunPython( Text * text, PyObject * globaldict ) return PyEval_EvalCode( text->compiled, globaldict, globaldict ); } -/***************************************************************************** -* Description: This function returns the value of the name field of the -* given Text struct. -*****************************************************************************/ -char *GetName( Text * text ) -{ - return ( text->id.name + 2 ); -} - /***************************************************************************** * Description: This function creates a new Python dictionary object. *****************************************************************************/ @@ -2809,7 +2797,7 @@ PyObject *importText( char *name ) text = ( Text * ) & ( G.main->text.first ); while( text ) { - if( !strcmp( txtname, GetName( text ) ) ) + if( !strcmp( txtname, text->id.name+2 ) ) break; text = text->id.next; } @@ -2822,8 +2810,7 @@ PyObject *importText( char *name ) if( !text->compiled ) { buf = txt_to_buf( text ); text->compiled = - Py_CompileString( buf, GetName( text ), - Py_file_input ); + Py_CompileString( buf, text->id.name+2, Py_file_input ); MEM_freeN( buf ); if( PyErr_Occurred( ) ) { @@ -2905,7 +2892,7 @@ static PyObject *reimportText( PyObject *module ) /* look up the text object */ text = ( Text * ) & ( G.main->text.first ); while( text ) { - if( !strcmp( txtname, GetName( text ) ) ) + if( !strcmp( txtname, text->id.name+2 ) ) break; text = text->id.next; } @@ -2922,8 +2909,7 @@ static PyObject *reimportText( PyObject *module ) /* compile the buffer */ buf = txt_to_buf( text ); - text->compiled = Py_CompileString( buf, GetName( text ), - Py_file_input ); + text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input ); MEM_freeN( buf ); /* if compile failed.... return this error */ diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index c36213950b0..ccd24a437b5 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -131,11 +131,11 @@ #define EXPP_MAT_RAYMIRRGLOSS_MIN 0.0 #define EXPP_MAT_RAYMIRRGLOSS_MAX 1.0 #define EXPP_MAT_RAYMIRRGLOSSSAMPLES_MIN 0 -#define EXPP_MAT_RAYMIRRGLOSSSAMPLES_MAX 255 +#define EXPP_MAT_RAYMIRRGLOSSSAMPLES_MAX 1024 #define EXPP_MAT_RAYTRANSPGLOSS_MIN 0.0 #define EXPP_MAT_RAYTRANSPGLOSS_MAX 1.0 #define EXPP_MAT_RAYTRANSPGLOSSSAMPLES_MIN 0 -#define EXPP_MAT_RAYTRANSPGLOSSSAMPLES_MAX 255 +#define EXPP_MAT_RAYTRANSPGLOSSSAMPLES_MAX 1024 #define EXPP_MAT_FILTER_MIN 0.0 #define EXPP_MAT_FILTER_MAX 1.0 #define EXPP_MAT_TRANSLUCENCY_MIN 0.0 @@ -738,8 +738,10 @@ static PyMethodDef BPy_Material_methods[] = { "() - Return fresnel power for refractions factor"}, {"getRayTransGloss", ( PyCFunction ) Material_getGlossTrans, METH_NOARGS, "() - Return amount refraction glossiness"}, + {"getRayTransGlossSamples", ( PyCFunction ) Material_getGlossTransSamples, METH_NOARGS, + "() - Return number of sampels for transparent glossiness"}, {"getRayMirrGlossSamples", ( PyCFunction ) Material_getGlossMirrSamples, METH_NOARGS, - "() - Return amount mirror glossiness"}, + "() - Return number of sampels for mirror glossiness"}, {"getFilter", ( PyCFunction ) Material_getFilter, METH_NOARGS, "() - Return the amount of filtering when transparent raytrace is enabled"}, {"getTranslucency", ( PyCFunction ) Material_getTranslucency, METH_NOARGS, @@ -847,8 +849,10 @@ static PyMethodDef BPy_Material_methods[] = { "(f) - Set blend fac for mirror fresnel - [1.0, 5.0]"}, {"setRayTransGloss", ( PyCFunction ) Material_setGlossTrans, METH_VARARGS, "(f) - Set amount refraction glossiness - [0.0, 1.0]"}, + {"setRayTransGlossSamples", ( PyCFunction ) Material_setGlossTransSamples, METH_VARARGS, + "(i) - Set number transparent gloss samples - [1, 1024]"}, {"setRayMirrGlossSamples", ( PyCFunction ) Material_setGlossMirrSamples, METH_VARARGS, - "(f) - Set amount mirror glossiness - [0.0, 1.0]"}, + "(i) - Set number mirror gloss samples - [1, 1024]"}, {"setFilter", ( PyCFunction ) Matr_oldsetFilter, METH_VARARGS, "(f) - Set the amount of filtering when transparent raytrace is enabled"}, {"setTranslucency", ( PyCFunction ) Matr_oldsetTranslucency, METH_VARARGS, diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index 4e43819cb71..a9280d9dd19 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -540,6 +540,7 @@ static void check_packAll() } } +#ifdef _WIN32 static void copy_game_dll(char *dll_filename, char *source_dir, char *dest_dir) { char source_filename[FILE_MAX]; @@ -573,6 +574,7 @@ static void copy_all_game_dlls(char *str) copy_game_dll(game_dll_list[i], source_dir, dest_dir ); }; } +#endif static int write_runtime(char *str, char *exename) { diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 6e922e421ac..6fcd3df2afc 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1368,14 +1368,15 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, { int mesh = 0; - if (PyArg_ParseTuple(args, "|i", &mesh)) + if (!PyArg_ParseTuple(args, "|i", &mesh)) + return NULL; // python sets a simple error + + if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { - if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) - { - KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]); - return meshproxy; - } + KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]); + return meshproxy; } + Py_RETURN_NONE; } @@ -1564,14 +1565,9 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, MT_Vector3 toDir, locToDir; MT_Scalar distance; - PyObject *returnValue = PyTuple_New(3); + PyObject *returnValue; PyObject *pyother; - if (!returnValue) - { - PyErr_SetString(PyExc_MemoryError, "PyTuple_New() failed"); - return NULL; - } if (!PyVecArgTo(args, toPoint)) { PyErr_Clear(); @@ -1581,7 +1577,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, toPoint = other->NodeGetWorldPosition(); }else { - PyErr_SetString(PyExc_TypeError, "Invalid arguments"); + PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type"); return NULL; } } @@ -1599,11 +1595,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, toDir.normalize(); locToDir = toDir * NodeGetWorldOrientation(); } - - PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance)); - PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir)); - PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir)); - + + returnValue = PyTuple_New(3); + if (returnValue) { // very unlikely to fail, python sets a memory error here. + PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance)); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir)); + } return returnValue; } @@ -1640,8 +1638,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, char *propName = NULL; if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) { - PyErr_SetString(PyExc_TypeError, "Invalid arguments"); - return NULL; + return NULL; // python sets simple error } if (!PyVecTo(pyarg, toPoint)) @@ -1706,8 +1703,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, KX_GameObject *other; if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) { - PyErr_SetString(PyExc_TypeError, "Invalid arguments"); - return NULL; + return NULL; // Python sets a simple error } if (!PyVecTo(pyto, toPoint)) @@ -1766,13 +1762,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, if (m_pHitObject) { PyObject* returnValue = PyTuple_New(3); - if (!returnValue) { - PyErr_SetString(PyExc_TypeError, "PyTuple_New() failed"); - return NULL; + if (returnValue) { // unlikely this would ever fail, if it does python sets an error + PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); } - PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); - PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); - PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); return returnValue; } return Py_BuildValue("OOO", Py_None, Py_None, Py_None); From 2e6a3710bba93cf2d6b86cf511a123068ead61bd Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Mon, 4 Aug 2008 11:47:17 +0000 Subject: [PATCH 49/58] * Armature hierarchy selection tools These are for use in pose mode or armature edit mode, to let you quickly traverse up and down a chain of bones. It's quite useful for bones that are in hard-to-click places. The tools are: *Select parent/child ( [ and ] ) selects the parent or child of the active bone, deselecting the original active bone * Extend select parent/child (shift [ and shift ] ) selects the parent or child of the active bone, adding to the selection Thanks to Joshua for reviewing this so promptly! PS. I'd like to use these [ and ] keys more widely in blender as consistent 'select next / previous' tools. I can imagine it being very useful for a lot of things like keyframes, nodes, mesh edges, etc. --- source/blender/include/BIF_editarmature.h | 7 +- source/blender/include/BIF_poseobject.h | 2 + source/blender/src/editarmature.c | 164 +++++++++++----------- source/blender/src/header_view3d.c | 58 ++++++-- source/blender/src/poseobject.c | 61 ++++++++ source/blender/src/space.c | 17 ++- 6 files changed, 213 insertions(+), 96 deletions(-) diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index da98eb3d4f1..13c16749612 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -108,7 +108,8 @@ void mouse_armature(void); void remake_editArmature(void); void selectconnected_armature(void); void selectconnected_posearmature(void); -void select_bone_parent(void); +void armature_select_hierarchy(short direction, short add_to_sel); + void setflag_armature(short mode); void unique_editbone_name (struct ListBase *ebones, char *name); @@ -143,6 +144,10 @@ void set_locks_armature_bones(short lock); #define BONESEL_NOSEL 0x80000000 /* Indicates a negative number */ +/* used in bone_select_hierachy() */ +#define BONE_SELECT_PARENT 0 +#define BONE_SELECT_CHILD 1 + #endif diff --git a/source/blender/include/BIF_poseobject.h b/source/blender/include/BIF_poseobject.h index 58c67ff102a..ab96f7ec03e 100644 --- a/source/blender/include/BIF_poseobject.h +++ b/source/blender/include/BIF_poseobject.h @@ -65,6 +65,8 @@ void pose_assign_to_posegroup(short active); void pose_remove_from_posegroups(void); void pgroup_operation_with_menu(void); +void pose_select_hierarchy(short direction, short add_to_sel); + void pose_select_grouped(short nr); void pose_select_grouped_menu(void); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 3d0f26960d6..80c24f3a989 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -1033,87 +1033,6 @@ static void *get_nearest_bone (short findunsel) return NULL; } -/* used by posemode and editmode */ -void select_bone_parent (void) -{ - Object *ob; - bArmature *arm; - - /* get data */ - if (G.obedit) - ob= G.obedit; - else if (OBACT) - ob= OBACT; - else - return; - arm= (bArmature *)ob->data; - - /* determine which mode armature is in */ - if ((!G.obedit) && (ob->flag & OB_POSEMODE)) { - /* deal with pose channels */ - /* channels are sorted on dependency, so the loop below won't result in a flood-select */ - bPoseChannel *pchan=NULL; - - for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - /* check if bone in original selection */ - if (pchan->bone->flag & BONE_SELECTED) { - bPoseChannel *chanpar= pchan->parent; - - /* check if any parent */ - if ((chanpar) && ((chanpar->bone->flag & BONE_SELECTED)==0)) { - chanpar->bone->flag |= BONE_SELECTED; - select_actionchannel_by_name (ob->action, pchan->name, 1); - } - } - } - } - else if (G.obedit) { - /* deal with editbones */ - EditBone *curbone, *parbone, *parpar; - - /* prevent floods */ - for (curbone= G.edbo.first; curbone; curbone= curbone->next) - curbone->temp= NULL; - - for (curbone= G.edbo.first; curbone; curbone= curbone->next) { - /* check if bone selected */ - if ((curbone->flag & BONE_SELECTED) && curbone->temp==NULL) { - parbone= curbone->parent; - - /* check if any parent */ - if ((parbone) && ((parbone->flag & BONE_SELECTED)==0)) { - /* select the parent bone */ - parbone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); - - /* check if parent has parent */ - parpar= parbone->parent; - - if ((parpar) && (parbone->flag & BONE_CONNECTED)) { - parpar->flag |= BONE_TIPSEL; - } - /* tag this bone to not flood selection */ - parbone->temp= parbone; - } - } - } - - /* to be sure... */ - for (curbone= G.edbo.first; curbone; curbone= curbone->next) - curbone->temp= NULL; - - } - - /* undo + redraw pushes */ - countall(); // flushes selection! - - allqueue (REDRAWVIEW3D, 0); - allqueue (REDRAWBUTSEDIT, 0); - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWOOPS, 0); - - BIF_undo_push("Select Parent"); -} - /* helper for setflag_sel_bone() */ static void bone_setflag (int *bone, int flag, short mode) { @@ -1139,6 +1058,89 @@ static void bone_setflag (int *bone, int flag, short mode) } } +/* Get the first available child of an editbone */ +static EditBone *editbone_get_child(EditBone *pabone, short use_visibility) +{ + Object *ob; + bArmature *arm; + EditBone *curbone, *chbone=NULL; + + if (!G.obedit) return NULL; + else ob= G.obedit; + arm= (bArmature *)ob->data; + + for (curbone= G.edbo.first; curbone; curbone= curbone->next) { + if (curbone->parent == pabone) { + if (use_visibility) { + if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) + chbone = curbone; + } + else + chbone = curbone; + } + } + + return chbone; +} + +void armature_select_hierarchy(short direction, short add_to_sel) +{ + Object *ob; + bArmature *arm; + EditBone *curbone, *pabone, *chbone; + + if (!G.obedit) return; + else ob= G.obedit; + arm= (bArmature *)ob->data; + + for (curbone= G.edbo.first; curbone; curbone= curbone->next) { + if (arm->layer & curbone->layer) { + if (curbone->flag & (BONE_ACTIVE)) { + if (direction == BONE_SELECT_PARENT) { + if (curbone->parent == NULL) continue; + else pabone = curbone->parent; + + if ((arm->layer & pabone->layer) && !(pabone->flag & BONE_HIDDEN_A)) { + pabone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL; + + if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + curbone->flag &= ~BONE_ACTIVE; + break; + } + + } else { // BONE_SELECT_CHILD + chbone = editbone_get_child(curbone, 1); + if (chbone == NULL) continue; + + if ((arm->layer & chbone->layer) && !(chbone->flag & BONE_HIDDEN_A)) { + chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + + if (!add_to_sel) { + curbone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL); + if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL; + } + curbone->flag &= ~BONE_ACTIVE; + break; + } + } + } + } + } + + countall(); // flushes selection! + + allqueue (REDRAWVIEW3D, 0); + allqueue (REDRAWBUTSEDIT, 0); + allqueue (REDRAWBUTSOBJECT, 0); + allqueue (REDRAWOOPS, 0); + + if (direction==BONE_SELECT_PARENT) + BIF_undo_push("Select edit bone parent"); + if (direction==BONE_SELECT_CHILD) + BIF_undo_push("Select edit bone child"); +} + /* used by posemode and editmode */ void setflag_armature (short mode) { diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index d834bd70321..948023bebfb 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1325,12 +1325,21 @@ static void do_view3d_select_armaturemenu(void *arg, int event) case 2: /* Select/Deselect all */ deselectall_armature(1, 1); break; - case 3: /* Select Parent(s) */ - select_bone_parent(); - break; - case 4: /* Swap Select All */ + case 3: /* Swap Select All */ deselectall_armature(3, 1); break; + case 4: /* Select parent */ + armature_select_hierarchy(BONE_SELECT_PARENT, 0); + break; + case 5: /* Select child */ + armature_select_hierarchy(BONE_SELECT_CHILD, 0); + break; + case 6: /* Extend Select parent */ + armature_select_hierarchy(BONE_SELECT_PARENT, 1); + break; + case 7: /* Extend Select child */ + armature_select_hierarchy(BONE_SELECT_CHILD, 1); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -1348,11 +1357,18 @@ static uiBlock *view3d_select_armaturemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Swap Select All|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Parent|[", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Child|]", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Select Parent|Shift [", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Select Child|Shift ]", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Parent(s)|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - if(curarea->headertype==HEADERTOP) { uiBlockSetDirection(block, UI_DOWN); } @@ -1379,12 +1395,21 @@ static void do_view3d_select_pose_armaturemenu(void *arg, int event) case 3: /* Select Target(s) of Constraint(s) */ pose_select_constraint_target(); break; - case 4: /* Select Bone's Parent */ - select_bone_parent(); - break; case 5: /* Swap Select All */ deselectall_posearmature(OBACT, 3, 1); break; + case 6: /* Select parent */ + pose_select_hierarchy(BONE_SELECT_PARENT, 0); + break; + case 7: /* Select child */ + pose_select_hierarchy(BONE_SELECT_CHILD, 0); + break; + case 8: /* Extend Select parent */ + pose_select_hierarchy(BONE_SELECT_PARENT, 1); + break; + case 9: /* Extend Select child */ + pose_select_hierarchy(BONE_SELECT_CHILD, 1); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -1404,8 +1429,17 @@ static uiBlock *view3d_select_pose_armaturemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Swap Select All|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Constraint Target|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Parent(s)|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); - + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Parent|[", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Child|]", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Select Parent|Shift [", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Select Child|Shift ]", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, ""); + if(curarea->headertype==HEADERTOP) { uiBlockSetDirection(block, UI_DOWN); } diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index b054b435002..28b8729a247 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -479,6 +479,67 @@ void pose_select_constraint_target(void) } +void pose_select_hierarchy(short direction, short add_to_sel) +{ + Object *ob= OBACT; + bArmature *arm= ob->data; + bPoseChannel *pchan; + Bone *curbone, *pabone, *chbone; + + /* paranoia checks */ + if (!ob && !ob->pose) return; + if (ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return; + + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + curbone= pchan->bone; + + if (arm->layer & curbone->layer) { + if (curbone->flag & (BONE_ACTIVE)) { + if (direction == BONE_SELECT_PARENT) { + + if (pchan->parent == NULL) continue; + else pabone= pchan->parent->bone; + + if ((arm->layer & pabone->layer) && !(pabone->flag & BONE_HIDDEN_P)) { + + if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; + curbone->flag &= ~BONE_ACTIVE; + pabone->flag |= (BONE_ACTIVE|BONE_SELECTED); + + select_actionchannel_by_name (ob->action, pchan->name, 0); + select_actionchannel_by_name (ob->action, pchan->parent->name, 1); + break; + } + } else { // BONE_SELECT_CHILD + + if (pchan->child == NULL) continue; + else chbone = pchan->child->bone; + + if ((arm->layer & chbone->layer) && !(chbone->flag & BONE_HIDDEN_P)) { + + if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; + curbone->flag &= ~BONE_ACTIVE; + chbone->flag |= (BONE_ACTIVE|BONE_SELECTED); + + select_actionchannel_by_name (ob->action, pchan->name, 0); + select_actionchannel_by_name (ob->action, pchan->child->name, 1); + break; + } + } + } + } + } + + allqueue (REDRAWVIEW3D, 0); + allqueue (REDRAWBUTSOBJECT, 0); + allqueue (REDRAWOOPS, 0); + + if (direction==BONE_SELECT_PARENT) + BIF_undo_push("Select pose bone parent"); + if (direction==BONE_SELECT_CHILD) + BIF_undo_push("Select pose bone child"); +} + /* context: active channel */ void pose_special_editmenu(void) { diff --git a/source/blender/src/space.c b/source/blender/src/space.c index b4702788e0c..8d86336e12e 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -2428,7 +2428,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.qual==LR_ALTKEY && G.obedit->type==OB_ARMATURE) clear_bone_parent(); else if((G.qual==0) && (G.obedit->type==OB_ARMATURE)) - select_bone_parent(); + armature_select_hierarchy(BONE_SELECT_PARENT, 1); // 1 = add to selection else if((G.qual==(LR_CTRLKEY|LR_ALTKEY)) && (G.obedit->type==OB_ARMATURE)) separate_armature(); else if((G.qual==0) && G.obedit->type==OB_MESH) @@ -2458,7 +2458,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) start_RBSimulation(); } else if((G.qual==0) && (OBACT) && (OBACT->type==OB_ARMATURE) && (OBACT->flag & OB_POSEMODE)) - select_bone_parent(); + pose_select_hierarchy(BONE_SELECT_PARENT, 1); // 1 = add to selection else if((G.qual==0)) { start_game(); } @@ -2761,6 +2761,19 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) scrarea_queue_winredraw(curarea); break; + case LEFTBRACKETKEY: + if ((G.obedit) && (G.obedit->type == OB_ARMATURE)) + armature_select_hierarchy(BONE_SELECT_PARENT, (G.qual == LR_SHIFTKEY)); + else if ((ob) && (ob->flag & OB_POSEMODE)) + pose_select_hierarchy(BONE_SELECT_PARENT, (G.qual == LR_SHIFTKEY)); + break; + case RIGHTBRACKETKEY: + if ((G.obedit) && (G.obedit->type == OB_ARMATURE)) + armature_select_hierarchy(BONE_SELECT_CHILD, (G.qual == LR_SHIFTKEY)); + if ((ob) && (ob->flag & OB_POSEMODE)) + pose_select_hierarchy(BONE_SELECT_CHILD, (G.qual == LR_SHIFTKEY)); + break; + case PADSLASHKEY: if(G.qual==0) { if(G.vd->localview) { From 0c9508d24845605eb5a31575abd5cf8dd2eab047 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Mon, 4 Aug 2008 13:57:04 +0000 Subject: [PATCH 50/58] Fix for [#17366] Particle children from particles only take colour from UV-Maps -Some old code in particle rendering hadn't been updated properly. --- .../blender/render/intern/source/convertblender.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index faa7a68f754..e4a5ad67631 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1865,9 +1865,17 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem num= cpa->num; /* get orco */ - psys_particle_on_emitter(ob, psmd, - (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, - cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,nor,0,0,orco,0); + if(part->childtype == PART_CHILD_FACES) { + psys_particle_on_emitter(ob, psmd, + PART_FROM_FACE, cpa->num,DMCACHE_ISCHILD, + cpa->fuv,cpa->foffset,co,nor,0,0,orco,0); + } + else { + ParticleData *par = psys->particles + cpa->parent; + psys_particle_on_emitter(ob, psmd, part->from, + par->num,DMCACHE_ISCHILD,par->fuv, + par->foffset,co,nor,0,0,orco,0); + } if(uvco){ if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ From 9ec6083cfe2a9d272815ce32d8dffe88326985cb Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Mon, 4 Aug 2008 14:17:11 +0000 Subject: [PATCH 51/58] Fix for [#17414] Particles doesn't obey to lattice once children are added -Lattice calculations were left out for children by accident --- source/blender/blenkernel/intern/particle.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 24a3d348ae7..643f90637ad 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3744,6 +3744,9 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey /* TODO: pa_clump vgroup */ do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0); + + if(psys->lattice) + calc_latt_deform(state->co,1.0f); } else{ if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */ From cbec9883f9aad2796ea1200ba3f3c6370a35028a Mon Sep 17 00:00:00 2001 From: Ben Batt Date: Mon, 4 Aug 2008 14:49:55 +0000 Subject: [PATCH 52/58] Fix for [#17376] Applying mirror modifier does not respect UV pinning. The custom data system wasn't swapping pinning or selection flags for MTFace data when face vertices were reordered. --- source/blender/blenkernel/intern/customdata.c | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 9012adb09b7..2c1f6bb84c1 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -265,14 +265,34 @@ static void layerSwap_tface(void *data, int *corner_indices) { MTFace *tf = data; float uv[4][2]; + const static short pin_flags[4] = + { TF_PIN1, TF_PIN2, TF_PIN3, TF_PIN4 }; + const static char sel_flags[4] = + { TF_SEL1, TF_SEL2, TF_SEL3, TF_SEL4 }; + short unwrap = tf->unwrap & ~(TF_PIN1 | TF_PIN2 | TF_PIN3 | TF_PIN4); + char flag = tf->flag & ~(TF_SEL1 | TF_SEL2 | TF_SEL3 | TF_SEL4); int j; for(j = 0; j < 4; ++j) { - uv[j][0] = tf->uv[corner_indices[j]][0]; - uv[j][1] = tf->uv[corner_indices[j]][1]; + int source_index = corner_indices[j]; + + uv[j][0] = tf->uv[source_index][0]; + uv[j][1] = tf->uv[source_index][1]; + + // swap pinning flags around + if(tf->unwrap & pin_flags[source_index]) { + unwrap |= pin_flags[j]; + } + + // swap selection flags around + if(tf->flag & sel_flags[source_index]) { + flag |= sel_flags[j]; + } } memcpy(tf->uv, uv, sizeof(tf->uv)); + tf->unwrap = unwrap; + tf->flag = flag; } static void layerDefault_tface(void *data, int count) From 51d90eeb49f636b4675c04689564eed314369f3e Mon Sep 17 00:00:00 2001 From: Ben Batt Date: Mon, 4 Aug 2008 16:44:13 +0000 Subject: [PATCH 53/58] Fix for [#17291] Array modifier merge caps leaves a whole This code was missing a test_index_face call after merging, so it was making quads with v4 == 0. --- source/blender/blenkernel/intern/modifier.c | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index f13f8ef0298..503654717ae 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -1130,8 +1130,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, mface[numFaces].v1 = vert_map[mface[numFaces].v1]; mface[numFaces].v2 = vert_map[mface[numFaces].v2]; mface[numFaces].v3 = vert_map[mface[numFaces].v3]; - if(mface[numFaces].v4) + if(mface[numFaces].v4) { mface[numFaces].v4 = vert_map[mface[numFaces].v4]; + + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 4); + } + else + { + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 3); + } + origindex[numFaces] = ORIGINDEX_NONE; numFaces++; @@ -1221,8 +1231,17 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, mface[numFaces].v1 = vert_map[mface[numFaces].v1]; mface[numFaces].v2 = vert_map[mface[numFaces].v2]; mface[numFaces].v3 = vert_map[mface[numFaces].v3]; - if(mface[numFaces].v4) + if(mface[numFaces].v4) { mface[numFaces].v4 = vert_map[mface[numFaces].v4]; + + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 4); + } + else + { + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 3); + } origindex[numFaces] = ORIGINDEX_NONE; numFaces++; From 8d285fc10a9a598077141707178aa0089cb6227f Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 4 Aug 2008 17:24:11 +0000 Subject: [PATCH 54/58] Fix for better icc + openmp support using scons --- SConstruct | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index 869ba6454c8..4c3bbf8fad7 100644 --- a/SConstruct +++ b/SConstruct @@ -184,15 +184,16 @@ if env['WITH_BF_OPENMP'] == 1: env['CPPFLAGS'].append('/openmp') env['CXXFLAGS'].append('/openmp') else: - if env['CC'] == 'icc': + if env['CC'][-3:] == 'icc': # to be able to handle CC=/opt/bla/icc case env.Append(LINKFLAGS=['-openmp', '-static-intel']) env['CCFLAGS'].append('-openmp') env['CPPFLAGS'].append('-openmp') env['CXXFLAGS'].append('-openmp') else: - env['CCFLAGS'].append('-fopenmp') - env['CPPFLAGS'].append('-fopenmp') - env['CXXFLAGS'].append('-fopenmp') + env.Append(CCFLAGS=['-fopenmp']) + env.Append(CPPFLAGS=['-fopenmp']) + env.Append(CXXFLAGS=['-fopenmp']) + # env.Append(LINKFLAGS=['-fprofile-generate']) #check for additional debug libnames From 07bc1e56fec864748c160af02659e3fcff317be9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Aug 2008 23:20:12 +0000 Subject: [PATCH 55/58] own bug in weightpaint cleaning, wasnt removing as many groups from verts as it should be. --- release/scripts/weightpaint_clean.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/release/scripts/weightpaint_clean.py b/release/scripts/weightpaint_clean.py index ba1896f011e..ca2184bade4 100644 --- a/release/scripts/weightpaint_clean.py +++ b/release/scripts/weightpaint_clean.py @@ -25,7 +25,7 @@ It removes very low weighted verts from the current group with a weight option. # 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 @@ -51,13 +51,14 @@ def weightClean(me, PREF_THRESH, PREF_KEEP_SINGLE, PREF_OTHER_GROUPS): for wd in vWeightDict: l = len(wd) if not PREF_KEEP_SINGLE or l > 1: + # cant use iteritems because the dict is having items removed for group in wd.keys(): w= wd[group] if w <= PREF_THRESH: # small weight, remove. del wd[group] rem_count +=1 - l-=1 + l-=1 if PREF_KEEP_SINGLE and l == 1: break @@ -117,4 +118,4 @@ def main(): Draw.PupMenu('Removed %i verts from groups' % rem_count) if __name__=='__main__': - main() \ No newline at end of file + main() From 9e968cea4743640848a6e878de7fc1de47dc69b3 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 5 Aug 2008 03:29:46 +0000 Subject: [PATCH 56/58] Bugfix #16673: Segfault when using Bake Constraints Script There were several buggy things here (in order of significance): 1) PyAPI method didn't check to make sure that there was an active posechannel when deleting posechannel constraints. This was required by constraint_active_func() to be able to update the 'active' flags for the constraints in that stack 2) PyAPI method removed the links to the constraint data from the constraints list, even though that wasn't necessary, and may have caused memory leaks. 3) constraint_active_func() had no error checking for no constraints-stack being found --- source/blender/python/api2_2x/Constraint.c | 29 ++++++++++++++++------ source/blender/src/buttons_object.c | 3 ++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index 8db6a49465e..a62a5ee7ed8 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -29,6 +29,7 @@ #include "Constraint.h" /*This must come first*/ +#include "DNA_armature_types.h" #include "DNA_object_types.h" #include "DNA_effect_types.h" #include "DNA_vec_types.h" @@ -43,6 +44,7 @@ #include "BKE_constraint.h" #include "BLI_blenlib.h" #include "BIF_editconstraint.h" +#include "BIF_poseobject.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" #include "butspace.h" @@ -2286,19 +2288,32 @@ static PyObject *ConstraintSeq_moveDown( BPy_ConstraintSeq *self, BPy_Constraint static PyObject *ConstraintSeq_remove( BPy_ConstraintSeq *self, BPy_Constraint *value ) { - bConstraint *con = locate_constr( self, value ); + bConstraint *con = locate_constr(self, value); + bPoseChannel *active= NULL; /* if we can't locate the constraint, return (exception already set) */ - if( !con ) + if (!con) return (PyObject *)NULL; - /* do the actual removal */ - if( self->pchan ) - BLI_remlink( &self->pchan->constraints, con ); - else - BLI_remlink( &self->obj->constraints, con); + /* check if we need to set temporary 'active' flag for pchan */ + if (self->pchan) { + active= get_active_posechannel(self->obj); + + if (active != self->pchan) { + if (active) active->bone->flag &= ~BONE_ACTIVE; + self->pchan->bone->flag |= BONE_ACTIVE; + } + } + + /* del_constr_func() frees constraint + its data */ del_constr_func( self->obj, con ); + /* reset active pchan (if applicable) */ + if (self->pchan && self->pchan!=active) { + if (active) active->bone->flag |= BONE_ACTIVE; + self->pchan->bone->flag &= ~BONE_ACTIVE; + } + /* erase the link to the constraint */ value->con = NULL; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 2c7802c3302..58f3bff09c8 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -173,6 +173,7 @@ static void constraint_active_func(void *ob_v, void *con_v) } lb= get_active_constraints(ob); + if (lb == NULL) return; for(con= lb->first; con; con= con->next) { if(con==con_v) con->flag |= CONSTRAINT_ACTIVE; @@ -307,7 +308,7 @@ void del_constr_func (void *ob_v, void *con_v) } /* remove constraint itself */ lb= get_active_constraints(ob_v); - free_constraint_data (con); + free_constraint_data(con); BLI_freelinkN(lb, con); constraint_active_func(ob_v, NULL); From cd1d46c61d937f63684216f284777f75038f5ed3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Aug 2008 09:35:46 +0000 Subject: [PATCH 57/58] Added GameLogic.Mathutils so Mathutils and its types can be accessed from blenderplayer. also changed importText so it dosnt do a malloc --- .../blenkernel/bad_level_call_stubs/stubs.c | 4 ++ source/blender/python/BPY_interface.c | 38 +++++++------------ source/blender/python/api2_2x/Blender.c | 2 +- source/blender/python/api2_2x/Mathutils.c | 8 ++-- source/blender/python/api2_2x/Mathutils.h | 2 +- source/gameengine/Ketsji/KX_PythonInit.cpp | 9 ++++- source/gameengine/Ketsji/SConscript | 16 +++++++- 7 files changed, 46 insertions(+), 33 deletions(-) diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 3ad11a61de3..561d8d7c2a6 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -117,10 +117,14 @@ float BPY_pydriver_eval(struct IpoDriver *driver) { return 0; } + +/* int EXPP_dict_set_item_str(struct PyObject *dict, char *key, struct PyObject *value) { return 0; } +*/ + void Node_SetStack(struct BPy_Node *self, struct bNodeStack **stack, int type){} void InitNode(struct BPy_Node *self, struct bNode *node){} void Node_SetShi(struct BPy_Node *self, struct ShadeInput *shi){} diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 06e8c564ef0..69bff059356 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -163,7 +163,7 @@ PyObject *RunPython( Text * text, PyObject * globaldict ); PyObject *CreateGlobalDictionary( void ); void ReleaseGlobalDictionary( PyObject * dict ); void DoAllScriptsFromList( ListBase * list, short event ); -PyObject *importText( char *name ); +static PyObject *importText( char *name ); void init_ourImport( void ); void init_ourReload( void ); PyObject *blender_import( PyObject * self, PyObject * args ); @@ -1104,12 +1104,10 @@ int BPY_menu_do_python( short menutype, int event ) *****************************************************************************/ void BPY_free_compiled_text( struct Text *text ) { - if( !text->compiled ) - return; - Py_DECREF( ( PyObject * ) text->compiled ); - text->compiled = NULL; - - return; + if( text->compiled ) { + Py_DECREF( ( PyObject * ) text->compiled ); + text->compiled = NULL; + } } /***************************************************************************** @@ -2780,48 +2778,38 @@ void DoAllScriptsFromList( ListBase * list, short event ) return; } -PyObject *importText( char *name ) +static PyObject *importText( char *name ) { Text *text; - char *txtname; + char txtname[22]; /* 21+NULL */ char *buf = NULL; int namelen = strlen( name ); - - txtname = malloc( namelen + 3 + 1 ); - if( !txtname ) - return NULL; - + + if (namelen>21-3) return NULL; /* we know this cant be importable, the name is too long for blender! */ + memcpy( txtname, name, namelen ); memcpy( &txtname[namelen], ".py", 4 ); - text = ( Text * ) & ( G.main->text.first ); - - while( text ) { + for(text = G.main->text.first; text; text = text->id.next) { if( !strcmp( txtname, text->id.name+2 ) ) break; - text = text->id.next; } - if( !text ) { - free( txtname ); + if( !text ) return NULL; - } if( !text->compiled ) { buf = txt_to_buf( text ); - text->compiled = - Py_CompileString( buf, text->id.name+2, Py_file_input ); + text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input ); MEM_freeN( buf ); if( PyErr_Occurred( ) ) { PyErr_Print( ); BPY_free_compiled_text( text ); - free( txtname ); return NULL; } } - free( txtname ); return PyImport_ExecCodeModule( name, text->compiled ); } diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index 420d292cdce..2b190a6c828 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -1074,7 +1074,7 @@ void M_Blender_Init(void) PyDict_SetItemString(dict, "Material", Material_Init()); PyDict_SetItemString(dict, "Mesh", Mesh_Init()); PyDict_SetItemString(dict, "Metaball", Metaball_Init()); - PyDict_SetItemString(dict, "Mathutils", Mathutils_Init()); + PyDict_SetItemString(dict, "Mathutils", Mathutils_Init("Blender.Mathutils")); PyDict_SetItemString(dict, "Geometry", Geometry_Init()); PyDict_SetItemString(dict, "Modifier", Modifier_Init()); PyDict_SetItemString(dict, "NMesh", NMesh_Init()); diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c index 85c56a61628..217e096060f 100644 --- a/source/blender/python/api2_2x/Mathutils.c +++ b/source/blender/python/api2_2x/Mathutils.c @@ -106,8 +106,9 @@ struct PyMethodDef M_Mathutils_methods[] = { {"Point", (PyCFunction) M_Mathutils_Point, METH_VARARGS, M_Mathutils_Point_doc}, {NULL, NULL, 0, NULL} }; -//----------------------------MODULE INIT------------------------- -PyObject *Mathutils_Init(void) +/*----------------------------MODULE INIT-------------------------*/ +/* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */ +PyObject *Mathutils_Init(char *from) { PyObject *submodule; @@ -125,8 +126,7 @@ PyObject *Mathutils_Init(void) if( PyType_Ready( &quaternion_Type ) < 0 ) return NULL; - submodule = Py_InitModule3("Blender.Mathutils", - M_Mathutils_methods, M_Mathutils_doc); + submodule = Py_InitModule3(from, M_Mathutils_methods, M_Mathutils_doc); return (submodule); } //-----------------------------METHODS---------------------------- diff --git a/source/blender/python/api2_2x/Mathutils.h b/source/blender/python/api2_2x/Mathutils.h index dd9aae2abed..76d53cb6c4c 100644 --- a/source/blender/python/api2_2x/Mathutils.h +++ b/source/blender/python/api2_2x/Mathutils.h @@ -38,7 +38,7 @@ #include "euler.h" #include "point.h" -PyObject *Mathutils_Init( void ); +PyObject *Mathutils_Init( char * from ); PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); PyObject *row_point_multiplication(PointObject* pt, MatrixObject * mat); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index b66c3e42606..57ee52f9880 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -62,6 +62,10 @@ #include "KX_PyMath.h" +extern "C" { + #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use. +} + #include "PHY_IPhysicsEnvironment.h" // FIXME: Enable for access to blender python modules. This is disabled because // python has dependencies on a lot of other modules and is a pain to link. @@ -733,7 +737,10 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook ErrorObject = PyString_FromString("GameLogic.error"); PyDict_SetItemString(d, "error", ErrorObject); - + + // Add Blender.Mathutils module, duplicate code :/ + PyDict_SetItemString(d, "Mathutils", Mathutils_Init("GameLogic.Mathutils")); + // XXXX Add constants here /* To use logic bricks, we need some sort of constants. Here, we associate */ /* constants and sumbolic names. Add them to dictionary d. */ diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index fdac5a71071..f6f744b199a 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -5,7 +5,21 @@ Import ('env') sources = env.Glob('*.cpp') -incs = '. #source/kernel/gen_system #intern/string #intern/guardedalloc' +# Mathutils C files. +sources.extend([\ + '#source/blender/python/api2_2x/Mathutils.c',\ + '#source/blender/python/api2_2x/constant.c',\ + '#source/blender/python/api2_2x/euler.c',\ + '#source/blender/python/api2_2x/gen_utils.c',\ + '#source/blender/python/api2_2x/matrix.c',\ + '#source/blender/python/api2_2x/point.c',\ + '#source/blender/python/api2_2x/quat.c',\ + '#source/blender/python/api2_2x/vector.c',\ +]) + +incs = '. #source/blender/python/api2_2x' # Only for Mathutils! - no other deps + +incs += ' #source/kernel/gen_system #intern/string #intern/guardedalloc' incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #intern/bmfont' incs += ' #intern/SoundSystem #intern/SoundSystem/include #intern/SoundSystem/openal' incs += ' #intern/SoundSystem/dummy #intern/SoundSystem/intern #source/gameengine/Converter' From b277de28958e8113e2b0ec2f595546fa54b81f3b Mon Sep 17 00:00:00 2001 From: Ben Batt Date: Tue, 5 Aug 2008 14:42:04 +0000 Subject: [PATCH 58/58] Fix for [#17421] Issue with Displace modifier not updating with animated textures I have added a dependsOnTime function for the Displace modifier which checks if the displacement texture has IPOs, is a plugin, or uses an animated image. --- source/blender/blenkernel/BKE_texture.h | 1 + source/blender/blenkernel/intern/modifier.c | 15 +++++++++++ source/blender/blenkernel/intern/texture.c | 28 +++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index fade0f8cbaa..c162a04e055 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -73,6 +73,7 @@ void BKE_free_envmap(struct EnvMap *env); struct EnvMap *BKE_add_envmap(void); struct EnvMap *BKE_copy_envmap(struct EnvMap *env); +int BKE_texture_dependsOnTime(const struct Tex *texture); #endif diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 503654717ae..2cb64896d87 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -2999,6 +2999,20 @@ CustomDataMask displaceModifier_requiredDataMask(ModifierData *md) return dataMask; } +static int displaceModifier_dependsOnTime(ModifierData *md) +{ + DisplaceModifierData *dmd = (DisplaceModifierData *)md; + + if(dmd->texture) + { + return BKE_texture_dependsOnTime(dmd->texture); + } + else + { + return 0; + } +} + static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) { @@ -7354,6 +7368,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->initData = displaceModifier_initData; mti->copyData = displaceModifier_copyData; mti->requiredDataMask = displaceModifier_requiredDataMask; + mti->dependsOnTime = displaceModifier_dependsOnTime; mti->foreachObjectLink = displaceModifier_foreachObjectLink; mti->foreachIDLink = displaceModifier_foreachIDLink; mti->updateDepgraph = displaceModifier_updateDepgraph; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index ad139220785..44342c02676 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -845,3 +845,31 @@ void BKE_free_envmap(EnvMap *env) } /* ------------------------------------------------------------------------- */ +int BKE_texture_dependsOnTime(const struct Tex *texture) +{ + if(texture->plugin) + { + // assume all plugins depend on time + return 1; + } + else if(texture->ima) + { + if(texture->ima->source == IMA_SRC_SEQUENCE || + texture->ima->source == IMA_SRC_MOVIE || + texture->ima->source == IMA_SRC_GENERATED) + { + return 1; + } + } + else if(texture->ipo) + { + // assume any ipo means the texture is animated + return 1; + } + else + { + return 0; + } +} + +/* ------------------------------------------------------------------------- */