Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/.blender/.Blanguages1
-rw-r--r--intern/boolop/intern/BOP_Edge.cpp43
-rw-r--r--intern/boolop/intern/BOP_Edge.h13
-rw-r--r--intern/boolop/intern/BOP_Face.cpp2
-rw-r--r--intern/boolop/intern/BOP_Face.h3
-rw-r--r--intern/boolop/intern/BOP_Interface.cpp30
-rw-r--r--intern/boolop/intern/BOP_Merge.cpp3
-rw-r--r--intern/boolop/intern/BOP_Merge.h5
-rw-r--r--intern/boolop/intern/BOP_Merge2.cpp944
-rw-r--r--intern/boolop/intern/BOP_Merge2.h99
-rw-r--r--intern/boolop/intern/BOP_Mesh.cpp11
-rw-r--r--intern/boolop/intern/BOP_Mesh.h7
-rw-r--r--intern/boolop/intern/BOP_Misc.h54
-rw-r--r--intern/boolop/intern/BOP_Tag.h2
-rw-r--r--intern/boolop/intern/BOP_Vertex.cpp19
-rw-r--r--intern/boolop/intern/BOP_Vertex.h5
-rw-r--r--projectfiles_vc7/blender/makesdna/DNA_makesdna.vcproj3
-rw-r--r--projectfiles_vc7/blender/src/BL_src.vcproj15
-rw-r--r--projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj6
-rw-r--r--release/scripts/rvk1_torvk2.py64
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h2
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_idprop.h1
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h7
-rw-r--r--source/blender/blenkernel/BKE_texture.h1
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c122
-rw-r--r--source/blender/blenkernel/intern/collision.c2
-rw-r--r--source/blender/blenkernel/intern/constraint.c142
-rw-r--r--source/blender/blenkernel/intern/customdata.c7
-rw-r--r--source/blender/blenkernel/intern/idprop.c15
-rw-r--r--source/blender/blenkernel/intern/scene.c2
-rw-r--r--source/blender/blenkernel/intern/softbody.c6
-rw-r--r--source/blender/blenkernel/intern/texture.c15
-rw-r--r--source/blender/blenlib/intern/arithb.c5
-rw-r--r--source/blender/blenlib/intern/freetypefont.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c90
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/include/BDR_gpencil.h13
-rw-r--r--source/blender/include/BIF_editaction.h10
-rw-r--r--source/blender/include/BIF_editarmature.h1
-rw-r--r--source/blender/include/BIF_editview.h3
-rw-r--r--source/blender/include/BSE_drawview.h1
-rw-r--r--source/blender/include/butspace.h3
-rw-r--r--source/blender/makesdna/DNA_ID.h3
-rw-r--r--source/blender/makesdna/DNA_action_types.h1
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h6
-rw-r--r--source/blender/makesdna/DNA_armature_types.h3
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h22
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h12
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h2
-rw-r--r--source/blender/makesdna/DNA_object_types.h2
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h1
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_material.c3
-rw-r--r--source/blender/nodes/intern/SHD_util.c4
-rw-r--r--source/blender/nodes/intern/SHD_util.h13
-rw-r--r--source/blender/python/BPY_interface.c2
-rw-r--r--source/blender/python/api2_2x/Armature.c2
-rw-r--r--source/blender/python/api2_2x/Bone.c10
-rw-r--r--source/blender/python/api2_2x/IDProp.c57
-rw-r--r--source/blender/python/api2_2x/doc/Armature.py3
-rw-r--r--source/blender/python/api2_2x/doc/IDProp.py4
-rw-r--r--source/blender/python/api2_2x/doc/Ipo.py4
-rw-r--r--source/blender/python/api2_2x/sceneRender.c38
-rw-r--r--source/blender/src/buttons_editing.c14
-rw-r--r--source/blender/src/buttons_logic.c103
-rw-r--r--source/blender/src/buttons_object.c23
-rw-r--r--source/blender/src/drawaction.c117
-rw-r--r--source/blender/src/drawgpencil.c231
-rw-r--r--source/blender/src/drawnode.c2
-rw-r--r--source/blender/src/drawseq.c2
-rw-r--r--source/blender/src/drawview.c44
-rw-r--r--source/blender/src/editaction.c95
-rw-r--r--source/blender/src/editaction_gpencil.c7
-rw-r--r--source/blender/src/editarmature.c26
-rw-r--r--source/blender/src/editipo.c11
-rw-r--r--source/blender/src/editnode.c16
-rw-r--r--source/blender/src/editobject.c19
-rw-r--r--source/blender/src/editseq.c34
-rw-r--r--source/blender/src/editview.c4
-rw-r--r--source/blender/src/gpencil.c496
-rw-r--r--source/blender/src/header_action.c21
-rw-r--r--source/blender/src/header_ipo.c2
-rw-r--r--source/blender/src/header_view3d.c1
-rw-r--r--source/blender/src/interface.c4
-rw-r--r--source/blender/src/interface_draw.c2
-rw-r--r--source/blender/src/meshlaplacian.c2
-rw-r--r--source/blender/src/outliner.c61
-rw-r--r--source/blender/src/poseobject.c156
-rw-r--r--source/blender/src/sequence.c4
-rw-r--r--source/blender/src/space.c23
-rw-r--r--source/blender/src/transform_conversions.c4
-rw-r--r--source/blender/src/transform_manipulator.c10
-rw-r--r--source/creator/creator.c22
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.cpp1
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp114
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h99
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp1
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp24
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp9
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp677
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.cpp59
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.h16
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp14
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp6
-rw-r--r--source/gameengine/Converter/KX_IpoConvert.cpp59
-rw-r--r--source/gameengine/Converter/KX_IpoConvert.h2
-rw-r--r--source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp13
-rw-r--r--source/gameengine/GameLogic/SCA_ActuatorEventManager.h1
-rw-r--r--source/gameengine/GameLogic/SCA_ActuatorSensor.cpp5
-rw-r--r--source/gameengine/GameLogic/SCA_ActuatorSensor.h2
-rw-r--r--source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp11
-rw-r--r--source/gameengine/GameLogic/SCA_AlwaysEventManager.h1
-rw-r--r--source/gameengine/GameLogic/SCA_EventManager.cpp13
-rw-r--r--source/gameengine/GameLogic/SCA_EventManager.h6
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.cpp27
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.cpp36
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.h14
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickManager.cpp11
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickManager.h1
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardManager.cpp15
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardManager.h1
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.cpp24
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.h7
-rw-r--r--source/gameengine/GameLogic/SCA_MouseManager.cpp14
-rw-r--r--source/gameengine/GameLogic/SCA_MouseManager.h1
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyEventManager.cpp11
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyEventManager.h1
-rw-r--r--source/gameengine/GameLogic/SCA_RandomEventManager.cpp11
-rw-r--r--source/gameengine/GameLogic/SCA_RandomEventManager.h1
-rw-r--r--source/gameengine/GameLogic/SCA_TimeEventManager.cpp5
-rw-r--r--source/gameengine/GameLogic/SCA_TimeEventManager.h1
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp85
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.h14
-rw-r--r--source/gameengine/Ketsji/BL_Material.h5
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp2
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp17
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h3
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp121
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h9
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.cpp127
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.h28
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp64
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h1
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.cpp44
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.h12
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_MaterialIpoController.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_MaterialIpoController.h8
-rw-r--r--source/gameengine/Ketsji/KX_NearSensor.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_NearSensor.h1
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp77
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.h22
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.h3
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.h23
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp9
-rw-r--r--source/gameengine/Ketsji/KX_RayEventManager.cpp9
-rw-r--r--source/gameengine/Ketsji/KX_RayEventManager.h1
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp55
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.cpp31
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.h2
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.h1
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp18
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp97
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h11
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp17
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp6
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h1
-rw-r--r--source/gameengine/PyDoc/BL_ShapeActionActuator.py158
-rw-r--r--source/gameengine/PyDoc/KX_ActuatorSensor.py24
-rw-r--r--source/gameengine/PyDoc/KX_ConstraintActuator.py120
-rw-r--r--source/gameengine/PyDoc/KX_IpoActuator.py19
-rw-r--r--source/gameengine/PyDoc/KX_ObjectActuator.py104
-rw-r--r--source/gameengine/PyDoc/KX_StateActuator.py26
-rw-r--r--source/gameengine/PyDoc/SCA_ISensor.py18
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.cpp43
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.h3
-rw-r--r--source/gameengine/Rasterizer/RAS_CameraData.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp19
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.h11
-rw-r--r--source/gameengine/Rasterizer/RAS_IRasterizer.h10
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.cpp24
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.h7
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp201
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.h30
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp48
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h9
-rw-r--r--source/gameengine/Rasterizer/RAS_Polygon.cpp18
195 files changed, 4659 insertions, 2046 deletions
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
diff --git a/intern/boolop/intern/BOP_Edge.cpp b/intern/boolop/intern/BOP_Edge.cpp
index ac302b530df..44e7d5cb567 100644
--- a/intern/boolop/intern/BOP_Edge.cpp
+++ b/intern/boolop/intern/BOP_Edge.cpp
@@ -75,4 +75,47 @@ 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 <iostream>
+using namespace std;
+
+/**
+ * Implements operator <<.
+ */
+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 13426f6e63c..a817b3d624f 100644
--- a/intern/boolop/intern/BOP_Edge.h
+++ b/intern/boolop/intern/BOP_Edge.h
@@ -29,12 +29,16 @@
#define BOP_EDGE_H
#include "BOP_Indexs.h"
+#include "BOP_Misc.h"
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);
@@ -47,6 +51,15 @@ 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
+
};
#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 <iostream>
#include <vector>
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_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 "<<v<<" with "<<N << endl;
+#endif
+ mergeVertex(ff , v, N );
+ mergeVertex(fb , v, N );
+// now remove v and its edges
+ vert->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 "<<prev<<","<<v2<<","<<next<<","<<opp<<endl;
+#endif
+ }
+ deleteFace(m_mesh, face);
+}
+
+// #define OLD_QUAD
+
+/**
+ * Simplifies the mesh, merging the pairs of triangles that come frome the
+ * same original face and define a quad.
+ * @return true if a quad was added, false otherwise
+ */
+bool BOP_Merge2::createQuads()
+{
+
+ BOP_Faces quads;
+
+ // Get mesh faces
+ BOP_Faces faces = m_mesh->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 5659cd62a3f..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
@@ -794,7 +801,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 +1083,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..d021579d161
--- /dev/null
+++ b/intern/boolop/intern/BOP_Misc.h
@@ -0,0 +1,54 @@
+/**
+ *
+ * $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 */
+
+/*
+ * 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 ...
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 <iomanip>
+
+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
diff --git a/projectfiles_vc7/blender/makesdna/DNA_makesdna.vcproj b/projectfiles_vc7/blender/makesdna/DNA_makesdna.vcproj
index 04d964ba657..6ad16dec52c 100644
--- a/projectfiles_vc7/blender/makesdna/DNA_makesdna.vcproj
+++ b/projectfiles_vc7/blender/makesdna/DNA_makesdna.vcproj
@@ -472,6 +472,9 @@ DNA_makesdna.exe dna.c
RelativePath="..\..\..\source\blender\makesdna\DNA_fileglobal_types.h">
</File>
<File
+ RelativePath="..\..\..\source\blender\makesdna\DNA_gpencil_types.h">
+ </File>
+ <File
RelativePath="..\..\..\source\blender\makesdna\DNA_group_types.h">
</File>
<File
diff --git a/projectfiles_vc7/blender/src/BL_src.vcproj b/projectfiles_vc7/blender/src/BL_src.vcproj
index 226bedbbfd8..153d9a90b23 100644
--- a/projectfiles_vc7/blender/src/BL_src.vcproj
+++ b/projectfiles_vc7/blender/src/BL_src.vcproj
@@ -182,6 +182,9 @@
RelativePath="..\..\..\source\blender\src\drawdeps.c">
</File>
<File
+ RelativePath="..\..\..\source\blender\src\drawgpencil.c">
+ </File>
+ <File
RelativePath="..\..\..\source\blender\src\drawimage.c">
</File>
<File
@@ -233,6 +236,9 @@
RelativePath="..\..\..\source\blender\src\editaction.c">
</File>
<File
+ RelativePath="..\..\..\source\blender\src\editaction_gpencil.c">
+ </File>
+ <File
RelativePath="..\..\..\source\blender\src\editarmature.c">
</File>
<File
@@ -350,6 +356,9 @@
RelativePath="..\..\..\source\blender\src\glutil.c">
</File>
<File
+ RelativePath="..\..\..\source\blender\src\gpencil.c">
+ </File>
+ <File
RelativePath="..\..\..\source\blender\src\hddaudio.c">
</File>
<File
@@ -618,6 +627,9 @@
RelativePath="..\..\..\source\blender\include\BDR_editobject.h">
</File>
<File
+ RelativePath="..\..\..\source\blender\include\BDR_gpencil.h">
+ </File>
+ <File
RelativePath="..\..\..\source\blender\include\BDR_imagepaint.h">
</File>
<File
@@ -636,6 +648,9 @@
RelativePath="..\..\..\source\blender\include\BIF_cursors.h">
</File>
<File
+ RelativePath="..\..\..\source\blender\include\BIF_drawgpencil.h">
+ </File>
+ <File
RelativePath="..\..\..\source\blender\include\BIF_drawimage.h">
</File>
<File
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
@@ -143,9 +143,6 @@
RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderMouseDevice.cpp">
</File>
<File
- RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderPolyMaterial.cpp">
- </File>
- <File
RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderRenderTools.cpp">
</File>
<File
@@ -171,9 +168,6 @@
RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderMouseDevice.h">
</File>
<File
- RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderPolyMaterial.h">
- </File>
- <File
RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderRenderTools.h">
</File>
<File
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
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/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 2d7d0e9286f..2274c54ad3b 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -46,6 +46,7 @@ struct ID;
typedef union {
int i;
float f;
+ double d;
char *str;
struct ID *id;
struct {
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index 739027fc95f..1b07ce50741 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -29,6 +29,13 @@
#ifndef BKE_SHRINKWRAP_H
#define BKE_SHRINKWRAP_H
+/* mesh util */
+//TODO move this somewhere else
+#include "BKE_customdata.h"
+struct DerivedMesh;
+struct Object;
+struct DerivedMesh *object_get_derived_final(struct Object *ob, CustomDataMask dataMask);
+
/* bitset stuff */
//TODO: should move this to other generic lib files?
typedef char* BitSet;
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/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index c913820205b..3ad11a61de3 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -1,4 +1,3 @@
-
/**
* $Id$
*
@@ -355,7 +354,8 @@ TimeMarker *get_frame_marker(int frame){return 0;};
/* editseq.c */
Sequence *get_forground_frame_seq(int frame){return 0;};
-void set_last_seq(Sequence *seq){};
+void clear_last_seq(Sequence *seq){};
+
/* modifier.c stub */
void harmonic_coordinates_bind(struct MeshDeformModifierData *mmd,
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; j<len; j++) {
+ vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[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/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;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 068501780bc..93ba30f8c9b 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -40,6 +40,7 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_action_types.h"
#include "DNA_curve_types.h"
@@ -63,6 +64,7 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_idprop.h"
+#include "BKE_shrinkwrap.h"
#include "BPY_extern.h"
@@ -457,7 +459,6 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
VECCOPY(offs_bone[3], pchan->bone->head);
offs_bone[3][1]+= pchan->bone->parent->length;
-
if (pchan->bone->flag & BONE_HINGE) {
/* pose_mat = par_pose-space_location * chan_mat */
float tmat[4][4];
@@ -558,8 +559,8 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
if (dgroup < 0) return;
/* get DerivedMesh */
- if (G.obedit && G.editMesh) {
- /* we are in editmode, so get a special derived mesh */
+ if ((G.obedit == ob) && (G.editMesh)) {
+ /* target is in editmode, so get a special derived mesh */
dm = CDDM_from_editmesh(G.editMesh, ob->data);
}
else {
@@ -3228,6 +3229,140 @@ static bConstraintTypeInfo CTI_TRANSFORM = {
transform_evaluate /* evaluate */
};
+/* ---------- Shrinkwrap Constraint ----------- */
+static void shrinkwrap_new_data (void *cdata)
+{
+ bShrinkwrapConstraint *data= (bShrinkwrapConstraint *)cdata;
+
+ data->target = NULL;
+ data->dist = 0.0f;
+ data->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
+}
+
+static int shrinkwrap_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bShrinkwrapConstraint *data = con->data;
+ bConstraintTarget *ct;
+
+ SINGLETARGETNS_GET_TARS(con, data->target, ct, list)
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bShrinkwrapConstraint *data = con->data;
+ bConstraintTarget *ct= list->first;
+
+ SINGLETARGETNS_FLUSH_TARS(con, data->target, ct, list, nocopy)
+ }
+}
+
+static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+ if (ct)
+ Mat4One(ct->matrix);
+}
+
+static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
+ bConstraintTarget *ct = targets->first;
+
+ if( VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) )
+ {
+ float co[3] = {0.0f, 0.0f, 0.0f};
+ float no[3] = {0.0f, 0.0f, 1.0f};
+ float dist;
+
+ SpaceTransform transform;
+ DerivedMesh *target = CDDM_copy( object_get_derived_final(ct->tar, CD_MASK_BAREMESH) );
+ BVHTreeRayHit hit;
+ BVHTreeNearest nearest;
+
+ //TODO
+ //Its stupid to create a bvhtree.. if we are only going to project one vertex
+ //But lets do it this way.. (so that in future maybe bvhtree gets a cache system and then the tree would already be build)
+ BVHTreeFromMesh treeData;
+ memset( &treeData, 0, sizeof(treeData) );
+
+ nearest.index = -1;
+ nearest.dist = 100000.0f; //TODO should use FLT_MAX.. but normal projection doenst yet supports it
+
+ if(target != NULL)
+ {
+
+ space_transform_from_matrixs(&transform, cob->matrix, ct->matrix);
+
+ space_transform_apply(&transform, co);
+ space_transform_apply_normal(&transform, no);
+
+
+ switch(scon->shrinkType)
+ {
+ case MOD_SHRINKWRAP_NEAREST_SURFACE:
+ if(bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6) == NULL) return;
+ BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
+ VECCOPY(co, nearest.co);
+
+ dist = VecLenf(co, nearest.co);
+ VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation
+ break;
+
+ case MOD_SHRINKWRAP_NEAREST_VERTEX:
+ if(bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6) == NULL) return;
+ BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
+ VECCOPY(co, nearest.co);
+
+ dist = VecLenf(co, nearest.co);
+ VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation
+ break;
+
+ case MOD_SHRINKWRAP_NORMAL:
+ if(bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6) == NULL) return;
+ if(normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE)
+ return;
+
+ VECCOPY(co, hit.co);
+ break;
+ }
+
+ space_transform_invert(&transform, co);
+ VECADD(cob->matrix[3], cob->matrix[3], co);
+
+
+ if(treeData.tree)
+ BLI_bvhtree_free(treeData.tree);
+
+ target->release(target);
+ }
+
+
+ }
+}
+
+static bConstraintTypeInfo CTI_SHRINKWRAP = {
+ CONSTRAINT_TYPE_SHRINKWRAP, /* type */
+ sizeof(bShrinkwrapConstraint), /* size */
+ "Shrinkwrap", /* name */
+ "bShrinkwrapConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ shrinkwrap_new_data, /* new data */
+ shrinkwrap_get_tars, /* get constraint targets */
+ shrinkwrap_flush_tars, /* flush constraint targets */
+ shrinkwrap_get_tarmat, /* get a target matrix */
+ shrinkwrap_evaluate /* evaluate */
+};
+
+
+
/* ************************* Constraints Type-Info *************************** */
/* All of the constraints api functions use bConstraintTypeInfo structs to carry out
* and operations that involve constraint specifc code.
@@ -3259,6 +3394,7 @@ static void constraints_init_typeinfo () {
constraintsTypeInfo[17]= &CTI_RIGIDBODYJOINT; /* RigidBody Constraint */
constraintsTypeInfo[18]= &CTI_CLAMPTO; /* ClampTo Constraint */
constraintsTypeInfo[19]= &CTI_TRANSFORM; /* Transformation Constraint */
+ constraintsTypeInfo[20]= &CTI_SHRINKWRAP; /* Shrinkwrap Constraint */
}
/* This function should be used for getting the appropriate type-info when only
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/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 2ef2f3a1b77..b16f52571f6 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -54,7 +54,8 @@ static char idp_size_table[] = {
sizeof(float)*16, /*Matrix type, deprecated*/
0, /*arrays don't have a fixed size*/
sizeof(ListBase), /*Group type*/
- sizeof(void*)
+ sizeof(void*),
+ sizeof(double)
};
@@ -365,10 +366,14 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name)
prop = MEM_callocN(sizeof(IDProperty), "IDProperty float");
*(float*)&prop->data.val = val.f;
break;
+ case IDP_DOUBLE:
+ prop = MEM_callocN(sizeof(IDProperty), "IDProperty float");
+ *(double*)&prop->data.val = val.d;
+ break;
case IDP_ARRAY:
{
- /*for now, we only support float and int arrays*/
- if (val.array.type == IDP_FLOAT || val.array.type == IDP_INT) {
+ /*for now, we only support float and int and double arrays*/
+ if (val.array.type == IDP_FLOAT || val.array.type == IDP_INT || val.array.type == IDP_DOUBLE) {
prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
prop->len = prop->totallen = val.array.len;
prop->subtype = val.array.type;
@@ -411,6 +416,10 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name)
prop->type = type;
strncpy(prop->name, name, MAX_IDPROP_NAME);
+
+ /*security null byte*/
+ prop->name[MAX_IDPROP_NAME-1] = 0;
+
return prop;
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 2898dca767c..553107dd264 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -303,7 +303,7 @@ void set_scene_bg(Scene *sce)
int flag;
// Note: this here is defined in editseq.c (BIF_editseq.h), NOT in blenkernel!
- set_last_seq(NULL);
+ clear_last_seq();
G.scene= sce;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 9005db1312f..d5b5ab6d63e 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -2053,7 +2053,6 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
/* check conditions for various options */
do_deflector= query_external_colliders(ob);
- do_effector= pdInitEffectors(ob,NULL);
do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2061,9 +2060,10 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
bproot= sb->bpoint; /* need this for proper spring addressing */
-
-
if (do_springcollision || do_aero) scan_for_ext_spring_forces(ob,timenow);
+ /* after spring scan because it uses Effoctors too */
+ do_effector= pdInitEffectors(ob,NULL);
+
if (do_deflector) {
float defforce[3];
do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
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/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index a31c769a5b3..c1edb7d3ac1 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -2535,11 +2535,6 @@ int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2])
}
-
- /* copied from Geometry.c - todo - move to arithb.c or some other generic place we can reuse */
-#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
-#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0))
-
/**
*
* @param min
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;
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 090b1d7c6b6..ad19cde3c9b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1347,8 +1347,14 @@ void IDP_DirectLinkArray(IDProperty *prop, int switch_endian, void *fd)
prop->data.pointer = newdataadr(fd, prop->data.pointer);
if (switch_endian) {
- for (i=0; i<prop->len; i++) {
- SWITCH_INT(((int*)prop->data.pointer)[i]);
+ if (prop->subtype != IDP_DOUBLE) {
+ for (i=0; i<prop->len; i++) {
+ SWITCH_INT(((int*)prop->data.pointer)[i]);
+ }
+ } else {
+ for (i=0; i<prop->len; i++) {
+ SWITCH_LONGINT(((double*)prop->data.pointer)[i]);
+ }
}
}
}
@@ -1385,6 +1391,24 @@ void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, void *fd)
case IDP_ARRAY:
IDP_DirectLinkArray(prop, switch_endian, fd);
break;
+ case IDP_DOUBLE:
+ /*erg, stupid doubles. since I'm storing them
+ in the same field as int val; val2 in the
+ IDPropertyData struct, they have to deal with
+ endianness specifically
+
+ in theory, val and val2 would've already been swapped
+ if switch_endian is true, so we have to first unswap
+ them then reswap them as a single 64-bit entity.
+ */
+
+ if (switch_endian) {
+ SWITCH_INT(prop->data.val);
+ SWITCH_INT(prop->data.val2);
+ SWITCH_LONGINT(prop->data.val);
+ }
+
+ break;
}
}
@@ -4161,15 +4185,6 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
link_gpencil(fd, sseq->gpd);
}
}
- else if(sl->spacetype==SPACE_ACTION) {
- SpaceAction *sact= (SpaceAction *)sl;
-
- /* WARNING: action-editor doesn't have it's own gpencil data!
- * so only adjust pointer, but DON'T LINK
- */
- if (sact->gpd)
- sact->gpd= newdataadr(fd, sact->gpd);
- }
}
sa->v1= newdataadr(fd, sa->v1);
@@ -4855,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; b<me->fdata.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; a<me->totface; a++, mf++) {
+ if(mf->mat_nr < me->totcol) {
+ ma= newlibadr(fd, lib, me->mat[mf->mat_nr]);
+ texalpha = 0;
+
+ for(b=0; ma && b<MAX_MTEX; b++)
+ if(ma->mtex && ma->mtex[b] && ma->mtex[b]->mapto & MAP_ALPHA)
+ texalpha = 1;
+ }
+ else {
+ ma= NULL;
+ texalpha = 0;
+ }
+
+ for(b=0; b<me->fdata.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 */
@@ -7699,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;
@@ -7716,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/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index b59dd851dfe..73abf362d12 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -533,6 +533,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
if(part->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_PA, "ParticleSettings", 1, part);
+ if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
writestruct(wd, DATA, "PartDeflect", 1, part->pd);
}
part= part->id.next;
diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h
index d0ebd096ecb..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);
@@ -53,8 +62,6 @@ struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd);
struct bGPdata *gpencil_data_getactive(struct ScrArea *sa);
short gpencil_data_setactive(struct ScrArea *sa, struct bGPdata *gpd);
-struct bGPdata *gpencil_data_getetime(struct bScreen *sc);
-void gpencil_data_setetime(struct bScreen *sc, struct bGPdata *gpd);
void gpencil_frame_delete_laststroke(struct bGPDframe *gpf);
@@ -71,6 +78,6 @@ void gpencil_delete_operation(short mode);
void gpencil_delete_menu(void);
//short gpencil_paint(short mousebutton);
-short gpencil_do_paint(struct ScrArea *sa);
+short gpencil_do_paint(struct ScrArea *sa, short mousebutton);
#endif /* BDR_GPENCIL_H */
diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h
index 9f6751daeff..77c2f19bb9b 100644
--- a/source/blender/include/BIF_editaction.h
+++ b/source/blender/include/BIF_editaction.h
@@ -49,7 +49,9 @@ enum {
ACTTYPE_FILLCON,
ACTTYPE_IPO,
ACTTYPE_SHAPEKEY,
- ACTTYPE_GPLAYER
+ ACTTYPE_GPDATABLOCK,
+ ACTTYPE_GPLAYER,
+ ACTTYPE_SPECIALDATA
};
/* Macros for easier/more consistant state testing */
@@ -70,6 +72,8 @@ enum {
#define EDITABLE_ICU(icu) ((icu->flag & IPO_PROTECT)==0)
#define SEL_ICU(icu) (icu->flag & IPO_SELECT)
+#define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND)
+
#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED)==0)
#define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT))
@@ -185,7 +189,7 @@ void action_remove_localmarkers(struct bAction *act);
/* Grease-Pencil Data */
void gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel);
-void deselect_gpencil_layers(struct bGPdata *gpd, short select_mode);
+void deselect_gpencil_layers(void *data, short select_mode);
short is_gplayer_frame_selected(struct bGPDlayer *gpl);
void set_gplayer_frame_selection(struct bGPDlayer *gpl, short mode);
@@ -204,7 +208,7 @@ void mirror_gplayer_frames(struct bGPDlayer *gpl, short mode);
struct Key *get_action_mesh_key(void);
int get_nearest_key_num(struct Key *key, short *mval, float *x);
-void *get_nearest_act_channel(short mval[], short *ret_type);
+void *get_nearest_act_channel(short mval[], short *ret_type, void **owner);
/* Action */
struct bActionChannel *get_hilighted_action_channel(struct bAction* action);
diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h
index 24112c7f11a..da98eb3d4f1 100644
--- a/source/blender/include/BIF_editarmature.h
+++ b/source/blender/include/BIF_editarmature.h
@@ -134,6 +134,7 @@ void transform_armature_mirror_update(void);
void hide_selected_armature_bones(void);
void hide_unselected_armature_bones(void);
void show_all_armature_bones(void);
+void set_locks_armature_bones(short lock);
#define BONESEL_ROOT 0x10000000
#define BONESEL_TIP 0x20000000
diff --git a/source/blender/include/BIF_editview.h b/source/blender/include/BIF_editview.h
index 4ed3d0df367..d2c6c56d01a 100644
--- a/source/blender/include/BIF_editview.h
+++ b/source/blender/include/BIF_editview.h
@@ -34,9 +34,12 @@ 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);
void circle_select(void);
void deselectall(void);
diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h
index 83031ff3bad..e6f22a4fb67 100644
--- a/source/blender/include/BSE_drawview.h
+++ b/source/blender/include/BSE_drawview.h
@@ -76,6 +76,7 @@ void inner_play_anim_loop(int init, int mode);
int play_anim(int mode);
void make_axis_color(char *col, char *col2, char axis);
+char *view3d_get_name(struct View3D *v3d);
/* SMOOTHVIEW */
void smooth_view(struct View3D *v3d, float *ofs, float *quat, float *dist, float *lens);
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index c0542e3f34c..af74946f0e6 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -721,7 +721,8 @@ enum {
B_CONSTRAINT_ADD_PYTHON,
B_CONSTRAINT_ADD_CLAMPTO,
B_CONSTRAINT_ADD_TRANSFORM,
- B_CONSTRAINT_INF
+ B_CONSTRAINT_INF,
+ B_CONSTRAINT_ADD_SHRINKWRAP
};
/* *********************** */
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 60050ea010e..3054e038ba2 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -46,7 +46,7 @@ struct ID;
typedef struct IDPropertyData {
void *pointer;
ListBase group;
- int val, pad;
+ int val, val2; /*note, we actually fit a double into these two ints*/
} IDPropertyData;
typedef struct IDProperty {
@@ -77,6 +77,7 @@ typedef struct IDProperty {
/*the ID link property type hasn't been implemented yet, this will require
some cleanup of blenkernel, most likely.*/
#define IDP_ID 7
+#define IDP_DOUBLE 8
/*add any future new id property types here.*/
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index d7969a7379b..2e8d95335cc 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -184,7 +184,6 @@ typedef struct SpaceAction {
View2D v2d;
bAction *action; /* the currently active action */
- bGPdata *gpd; /* the currently active gpencil block (for editing) */
char mode, autosnap; /* mode: editing context; autosnap: automatic keyframe snapping mode */
short flag, actnr; /* flag: bitmapped settings; */
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index ac9761f165d..7444ce95f56 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -368,9 +368,9 @@ typedef struct FreeCamera {
#define ACT_CONST_DIRPX 1
#define ACT_CONST_DIRPY 2
#define ACT_CONST_DIRPZ 4
-#define ACT_CONST_DIRMX 8
-#define ACT_CONST_DIRMY 16
-#define ACT_CONST_DIRMZ 32
+#define ACT_CONST_DIRNX 8
+#define ACT_CONST_DIRNY 16
+#define ACT_CONST_DIRNZ 32
/* constraint type */
#define ACT_CONST_TYPE_LOC 0
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 673855a6932..0648c535353 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -154,7 +154,8 @@ typedef enum eBone_Flag {
BONE_NO_SCALE = (1<<15), /* No parent scale */
BONE_HIDDEN_PG = (1<<16), /* hidden bone when drawing PoseChannels (for ghost drawing) */
BONE_DRAWWIRE = (1<<17), /* bone should be drawn as OB_WIRE, regardless of draw-types of view+armature */
- BONE_NO_CYCLICOFFSET = (1<<18) /* when no parent, bone will not get cyclic offset */
+ BONE_NO_CYCLICOFFSET = (1<<18), /* when no parent, bone will not get cyclic offset */
+ BONE_EDITMODE_LOCKED = (1<<19), /* bone transforms are locked in EditMode */
} eBone_Flag;
#endif
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 0fe0dace016..e78855b8de6 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -317,6 +317,13 @@ typedef struct bDistLimitConstraint {
int pad;
} bDistLimitConstraint;
+typedef struct bShrinkwrapConstraint {
+ Object *target;
+ float dist; /* distance to kept from target */
+ short shrinkType; /* shrink type (look on MOD shrinkwrap for values) */
+ short pad[5];
+} bShrinkwrapConstraint;
+
/* ------------------------------------------ */
/* bConstraint->type
@@ -344,10 +351,9 @@ typedef enum B_CONSTAINT_TYPES {
CONSTRAINT_TYPE_RIGIDBODYJOINT, /* rigidbody constraint */
CONSTRAINT_TYPE_CLAMPTO, /* clampto constraint */
CONSTRAINT_TYPE_TRANSFORM, /* transformation (loc/rot/size -> loc/rot/size) constraint */
+ CONSTRAINT_TYPE_SHRINKWRAP, /* shrinkwrap (loc/rot) constraint */
-
- /* NOTE: everytime a new constraint is added, update this */
- NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_TRANSFORM
+ NUM_CONSTRAINT_TYPES
} B_CONSTRAINT_TYPES;
/* bConstraint->flag */
@@ -375,11 +381,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/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_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index eafd886981b..dca4e28688d 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -59,6 +59,8 @@ typedef struct bGPDstroke {
#define GP_STROKE_3DSPACE (1<<0)
/* stroke is in 2d-space */
#define GP_STROKE_2DSPACE (1<<1)
+ /* stroke is an "eraser" stroke */
+#define GP_STROKE_ERASER (1<<2)
/* Grease-Pencil Annotations - 'Frame'
@@ -123,16 +125,16 @@ 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 */
- /* draw this datablock's data (not used) */
-#define GP_DATA_DISP (1<<0)
+ /* don't allow painting to occur at all */
+#define GP_DATA_LMBPLOCK (1<<0)
/* show debugging info in viewport (i.e. status print) */
#define GP_DATA_DISPINFO (1<<1)
- /* is the block being shown in Action Editor */
-#define GP_DATA_EDITTIME (1<<2)
+ /* in Action Editor, show as expanded channel */
+#define GP_DATA_EXPAND (1<<2)
/* is the block overriding all clicks? */
#define GP_DATA_EDITPAINT (1<<3)
/* new strokes are added in viewport space */
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/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index c4e8cb4925b..85c49a03569 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -466,9 +466,11 @@ extern Object workob;
#define OB_LOCK_ROTX 8
#define OB_LOCK_ROTY 16
#define OB_LOCK_ROTZ 32
+#define OB_LOCK_ROT 56
#define OB_LOCK_SCALEX 64
#define OB_LOCK_SCALEY 128
#define OB_LOCK_SCALEZ 256
+#define OB_LOCK_SCALE 448
/* ob->softflag in DNA_object_force.h */
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index c0b9a6b9590..7bad8ec3b44 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -257,6 +257,7 @@ typedef struct SpeedControlVars {
#define SEQ_USE_CROP 131072
#define SEQ_USE_COLOR_BALANCE 262144
#define SEQ_USE_PROXY_CUSTOM_DIR 524288
+#define SEQ_ACTIVE 1048576
#define SEQ_COLOR_BALANCE_INVERSE_GAIN 1
#define SEQ_COLOR_BALANCE_INVERSE_GAMMA 2
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c
index bdceb134c0d..9396410f850 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c
@@ -54,7 +54,6 @@ static bNodeSocketType sh_node_material_ext_in[]= {
{ SOCK_VALUE, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_RGBA, 1, "Mirror", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 1, "AmbCol", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 1, "Ambient", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 1, "Emit", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 1, "SpecTra", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
@@ -117,8 +116,6 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
if (node->type == SH_NODE_MATERIAL_EXT) {
if(in[MAT_IN_MIR]->hasinput)
nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]);
- if(in[MAT_IN_AMBCOL]->hasinput)
- nodestack_get_vec(&shi->ambr, SOCK_VECTOR, in[MAT_IN_AMBCOL]);
if(in[MAT_IN_AMB]->hasinput)
nodestack_get_vec(&shi->amb, SOCK_VALUE, in[MAT_IN_AMB]);
if(in[MAT_IN_EMIT]->hasinput)
diff --git a/source/blender/nodes/intern/SHD_util.c b/source/blender/nodes/intern/SHD_util.c
index c9f58fbce49..f673834d2b7 100644
--- a/source/blender/nodes/intern/SHD_util.c
+++ b/source/blender/nodes/intern/SHD_util.c
@@ -164,7 +164,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
case MAT_IN_MIR:
VECCOPY(&ma->mirr, sock->ns.vec); break;
case MAT_IN_AMB:
- VECCOPY(&ma->ambr, sock->ns.vec); break;
+ ma->amb= sock->ns.vec[0]; break;
case MAT_IN_EMIT:
ma->emit= sock->ns.vec[0]; break;
case MAT_IN_SPECTRA:
@@ -188,7 +188,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
case MAT_IN_MIR:
VECCOPY(sock->ns.vec, &ma->mirr); break;
case MAT_IN_AMB:
- VECCOPY(sock->ns.vec, &ma->ambr); break;
+ sock->ns.vec[0]= ma->amb; break;
case MAT_IN_EMIT:
sock->ns.vec[0]= ma->emit; break;
case MAT_IN_SPECTRA:
diff --git a/source/blender/nodes/intern/SHD_util.h b/source/blender/nodes/intern/SHD_util.h
index f75802b7c15..bdb2bb3707d 100644
--- a/source/blender/nodes/intern/SHD_util.h
+++ b/source/blender/nodes/intern/SHD_util.h
@@ -117,13 +117,12 @@ typedef struct ShaderCallData {
#define MAT_IN_REFL 2
#define MAT_IN_NORMAL 3
#define MAT_IN_MIR 4
-#define MAT_IN_AMBCOL 5
-#define MAT_IN_AMB 6
-#define MAT_IN_EMIT 7
-#define MAT_IN_SPECTRA 8
-#define MAT_IN_RAY_MIRROR 9
-#define MAT_IN_ALPHA 10
-#define MAT_IN_TRANSLUCENCY 11
+#define MAT_IN_AMB 5
+#define MAT_IN_EMIT 6
+#define MAT_IN_SPECTRA 7
+#define MAT_IN_RAY_MIRROR 8
+#define MAT_IN_ALPHA 9
+#define MAT_IN_TRANSLUCENCY 10
/* output socket defines */
#define MAT_OUT_COLOR 0
diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c
index 226657655fa..7120e97a62f 100644
--- a/source/blender/python/BPY_interface.c
+++ b/source/blender/python/BPY_interface.c
@@ -410,12 +410,14 @@ void BPY_rebuild_syspath( void )
mod = PyImport_ImportModule( "sys" );
if (!mod) {
printf("error: could not import python sys module. some modules may not import.\n");
+ PyGILState_Release(gilstate);
return;
}
if (!bpy_orig_syspath_List) { /* should never happen */
printf("error refershing python path\n");
Py_DECREF(mod);
+ PyGILState_Release(gilstate);
return;
}
diff --git a/source/blender/python/api2_2x/Armature.c b/source/blender/python/api2_2x/Armature.c
index e9dff098773..0db87c00dd2 100644
--- a/source/blender/python/api2_2x/Armature.c
+++ b/source/blender/python/api2_2x/Armature.c
@@ -1469,6 +1469,8 @@ PyObject *Armature_Init(void)
PyConstant_NewInt("BONE_SELECTED", BONE_SELECTED));
PyModule_AddObject(module, "TIP_SELECTED",
PyConstant_NewInt("TIP_SELECTED", BONE_TIPSEL));
+ PyModule_AddObject(module, "LOCKED_EDIT",
+ PyConstant_NewInt("LOCKED_EDIT", BONE_EDITMODE_LOCKED));
PyModule_AddObject(module, "OCTAHEDRON",
PyConstant_NewInt("OCTAHEDRON", ARM_OCTA));
diff --git a/source/blender/python/api2_2x/Bone.c b/source/blender/python/api2_2x/Bone.c
index 84faf416c5f..948eb007803 100644
--- a/source/blender/python/api2_2x/Bone.c
+++ b/source/blender/python/api2_2x/Bone.c
@@ -368,6 +368,10 @@ static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure)
if (PyList_Append(list,
EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
goto RuntimeError;
+ if(self->editbone->flag & BONE_EDITMODE_LOCKED)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "LOCKED_EDIT")) == -1)
+ goto RuntimeError;
}else{
if(self->flag & BONE_CONNECTED)
if (PyList_Append(list,
@@ -401,6 +405,10 @@ static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure)
if (PyList_Append(list,
EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
goto RuntimeError;
+ if(self->flag & BONE_EDITMODE_LOCKED)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "LOCKED_EDIT")) == -1)
+ goto RuntimeError;
}
return list;
@@ -422,7 +430,7 @@ static int EditBone_CheckValidConstant(PyObject *constant)
return 0;
if (!STREQ3(PyString_AsString(name), "CONNECTED", "HINGE", "NO_DEFORM") &&
!STREQ3(PyString_AsString(name), "ROOT_SELECTED", "BONE_SELECTED", "TIP_SELECTED") &&
- !STREQ2(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT"))
+ !STREQ3(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT", "LOCKED_EDIT"))
return 0;
else
return 1;
diff --git a/source/blender/python/api2_2x/IDProp.c b/source/blender/python/api2_2x/IDProp.c
index f60ebf8dee1..4a51619aec4 100644
--- a/source/blender/python/api2_2x/IDProp.c
+++ b/source/blender/python/api2_2x/IDProp.c
@@ -60,6 +60,8 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
return PyInt_FromLong( (long)prop->data.val );
case IDP_FLOAT:
return PyFloat_FromDouble( (double)(*(float*)(&prop->data.val)) );
+ case IDP_DOUBLE:
+ return PyFloat_FromDouble( (*(double*)(&prop->data.val)) );
case IDP_GROUP:
/*blegh*/
{
@@ -128,7 +130,19 @@ int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject *value)
Py_XDECREF(value);
break;
}
-
+ case IDP_DOUBLE:
+ {
+ double dvalue;
+ if (!PyNumber_Check(value))
+ return EXPP_ReturnIntError(PyExc_TypeError, "expected a float!");
+ value = PyNumber_Float(value);
+ if (!value)
+ return EXPP_ReturnIntError(PyExc_TypeError, "expected a float!");
+ dvalue = (float) PyFloat_AsDouble(value);
+ *(double*)&self->prop->data.val = dvalue;
+ Py_XDECREF(value);
+ break;
+ }
default:
return EXPP_ReturnIntError(PyExc_AttributeError, "attempt to set read-only attribute!");
}
@@ -204,8 +218,8 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
IDPropertyTemplate val = {0};
if (PyFloat_Check(ob)) {
- val.f = (float) PyFloat_AsDouble(ob);
- prop = IDP_New(IDP_FLOAT, val, name);
+ val.d = PyFloat_AsDouble(ob);
+ prop = IDP_New(IDP_DOUBLE, val, name);
} else if (PyInt_Check(ob)) {
val.i = (int) PyInt_AsLong(ob);
prop = IDP_New(IDP_INT, val, name);
@@ -223,7 +237,7 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
val.array.len = PySequence_Length(ob);
for (i=0; i<val.array.len; i++) {
item = PySequence_GetItem(ob, i);
- if (PyFloat_Check(item)) val.array.type = IDP_FLOAT;
+ if (PyFloat_Check(item)) val.array.type = IDP_DOUBLE;
else if (!PyInt_Check(item)) return "only floats and ints are allowed in ID property arrays";
Py_XDECREF(item);
}
@@ -236,7 +250,7 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
((int*)prop->data.pointer)[i] = (int)PyInt_AsLong(item);
} else {
item = PyNumber_Float(item);
- ((float*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
+ ((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
}
Py_XDECREF(item);
}
@@ -334,6 +348,9 @@ PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
case IDP_FLOAT:
return PyFloat_FromDouble(*((float*)&prop->data.val));
break;
+ case IDP_DOUBLE:
+ return PyFloat_FromDouble(*((double*)&prop->data.val));
+ break;
case IDP_INT:
return PyInt_FromLong( (long)prop->data.val );
break;
@@ -347,12 +364,15 @@ PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
"PyList_New() failed" );
for (i=0; i<prop->len; i++) {
- if (prop->subtype == IDP_FLOAT)
+ if (prop->subtype == IDP_FLOAT) {
PyList_SetItem(seq, i,
PyFloat_FromDouble(((float*)prop->data.pointer)[i]));
-
- else PyList_SetItem(seq, i,
- PyInt_FromLong(((int*)prop->data.pointer)[i]));
+ } else if (prop->subtype == IDP_DOUBLE) {
+ PyList_SetItem(seq, i,
+ PyFloat_FromDouble(((double*)prop->data.pointer)[i]));
+ } else { PyList_SetItem(seq, i,
+ PyInt_FromLong(((int*)prop->data.pointer)[i]));
+ }
}
return seq;
}
@@ -451,7 +471,7 @@ PyObject *BPy_IDGroup_GetKeys(BPy_IDProperty *self)
/*set correct group length*/
self->prop->len = i;
- /*free the old list*/
+ /*free the list*/
Py_DECREF(seq);
/*call self again*/
@@ -688,6 +708,9 @@ PyObject *BPy_IDArray_GetItem(BPy_IDArray *self, int index)
case IDP_FLOAT:
return PyFloat_FromDouble( (double)(((float*)self->prop->data.pointer)[index]));
break;
+ case IDP_DOUBLE:
+ return PyFloat_FromDouble( (((double*)self->prop->data.pointer)[index]));
+ break;
case IDP_INT:
return PyInt_FromLong( (long)((int*)self->prop->data.pointer)[index] );
break;
@@ -700,7 +723,8 @@ int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *val)
{
int i;
float f;
-
+ double d;
+
if (index < 0 || index >= self->prop->len)
return EXPP_ReturnIntError( PyExc_RuntimeError,
"index out of range!");
@@ -717,6 +741,17 @@ int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *val)
((float*)self->prop->data.pointer)[index] = f;
Py_XDECREF(val);
break;
+ case IDP_DOUBLE:
+ if (!PyNumber_Check(val)) return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected a float");
+ val = PyNumber_Float(val);
+ if (!val) return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected a float");
+
+ d = (double) PyFloat_AsDouble(val);
+ ((double*)self->prop->data.pointer)[index] = d;
+ Py_XDECREF(val);
+ break;
case IDP_INT:
if (!PyNumber_Check(val)) return EXPP_ReturnIntError( PyExc_TypeError,
"expected an int");
diff --git a/source/blender/python/api2_2x/doc/Armature.py b/source/blender/python/api2_2x/doc/Armature.py
index 68916af6166..9aceb0105e3 100644
--- a/source/blender/python/api2_2x/doc/Armature.py
+++ b/source/blender/python/api2_2x/doc/Armature.py
@@ -89,6 +89,8 @@ Example::
@type BONE_SELECTED: Constant
@var TIP_SELECTED: Tip of the Bone is selected
@type TIP_SELECTED: Constant
+@var LOCKED_EDIT: Prevents the bone from being transformed in editmode
+@type LOCKED_EDIT: Constant
@var OCTAHEDRON: Bones drawn as octahedrons
@type OCTAHEDRON: Constant
@var STICK: Bones drawn as a line
@@ -286,6 +288,7 @@ class Bone:
- Armature.ROOT_SELECTED: Selection of root ball of bone
- Armature.BONE_SELECTED: Selection of bone
- Armature.TIP_SELECTED: Selection of tip ball of bone
+ - Armature.LOCKED_EDIT: Prevents the bone from being transformed in editmode
@type options: List of Constants
@ivar subdivision: The number of bone subdivisions.
@type subdivision: Int
diff --git a/source/blender/python/api2_2x/doc/IDProp.py b/source/blender/python/api2_2x/doc/IDProp.py
index 0a0df335fa3..01d5136cd70 100644
--- a/source/blender/python/api2_2x/doc/IDProp.py
+++ b/source/blender/python/api2_2x/doc/IDProp.py
@@ -18,7 +18,9 @@ class IDGroup:
Note that for arrays, the array type defaults to int unless a float is found
while scanning the template list; if any floats are found, then the whole
- array is float.
+ array is float. Note that double-precision floating point numbers are used for
+ python-created float ID properties and arrays (though the internal C api does
+ support single-precision floats, and the python code will read them).
You can also delete properties with the del operator. For example:
diff --git a/source/blender/python/api2_2x/doc/Ipo.py b/source/blender/python/api2_2x/doc/Ipo.py
index c479926ccf3..d1c72f8cb86 100644
--- a/source/blender/python/api2_2x/doc/Ipo.py
+++ b/source/blender/python/api2_2x/doc/Ipo.py
@@ -250,7 +250,7 @@ class Ipo:
OfsZ, SizeX, SizeY, SizeZ, texR, texG, texB, DefVar, Col, Nor, Var,
Disp.
3. Object Ipo: LocX, LocY, LocZ, dLocX, dLocY, dLocZ, RotX, RotY, RotZ,
- dRotX, dRotY, dRotZ, SizeX, SizeY, SizeZ, dSizeX, dSizeY, dSizeZ,
+ dRotX, dRotY, dRotZ, ScaleX, ScaleY, ScaleZ, dScaleX, dScaleY, dScaleZ,
Layer, Time, ColR, ColG, ColB, ColA, FStreng, FFall, Damping,
RDamp, Perm.
4. Lamp Ipo: Energ, R, G, B, Dist, SpoSi, SpoBl, Quad1, Quad2, HaInt.
@@ -289,7 +289,7 @@ class Ipo:
OfsZ, SizeX, SizeY, SizeZ, texR, texG, texB, DefVar, Col, Nor, Var,
Disp.
3. Object Ipo: LocX, LocY, LocZ, dLocX, dLocY, dLocZ, RotX, RotY, RotZ,
- dRotX, dRotY, dRotZ, SizeX, SizeY, SizeZ, dSizeX, dSizeY, dSizeZ,
+ dRotX, dRotY, dRotZ, ScaleX, ScaleY, ScaleZ, dScaleX, dScaleY, dScaleZ,
Layer, Time, ColR, ColG, ColB, ColA, FStreng, FFall, Damping,
RDamp, Perm.
4. Lamp Ipo: Energ, R, G, B, Dist, SpoSi, SpoBl, Quad1, Quad2, HaInt.
diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c
index d382d450970..22e165cbe9f 100644
--- a/source/blender/python/api2_2x/sceneRender.c
+++ b/source/blender/python/api2_2x/sceneRender.c
@@ -56,6 +56,7 @@ struct View3D; /* keep me up here */
#include "gen_utils.h"
#include "gen_library.h"
+#include "../BPY_extern.h" /* for BPY_do_all_scripts() */
#include "Scene.h"
#include "Group.h"
@@ -469,19 +470,20 @@ PyObject *M_Render_EnableDispWin( PyObject * self )
PyObject *RenderData_Render( BPy_RenderData * self )
{
Scene *oldsce;
+ /* unlock to prevent a deadlock when there are pynodes: */
+ PyThreadState *tstate = NULL;
if (!G.background) {
oldsce = G.scene;
set_scene( self->scene );
+ tstate = PyEval_SaveThread();
BIF_do_render( 0 );
set_scene( oldsce );
}
-
else { /* background mode (blender -b file.blend -P script) */
+ int slink_flag = 0;
Render *re= RE_NewRender(G.scene->id.name);
-
-
int end_frame = G.scene->r.efra;
if (G.scene != self->scene)
@@ -490,11 +492,25 @@ PyObject *RenderData_Render( BPy_RenderData * self )
G.scene->r.efra = G.scene->r.sfra;
+ if (G.f & G_DOSCRIPTLINKS) {
+ BPY_do_all_scripts(SCRIPT_RENDER);
+ G.f &= ~G_DOSCRIPTLINKS; /* avoid FRAMECHANGED events*/
+ slink_flag = 1;
+ }
+
+ tstate = PyEval_SaveThread();
+
RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra);
+ if (slink_flag) {
+ G.f |= G_DOSCRIPTLINKS;
+ BPY_do_all_scripts(SCRIPT_POSTRENDER);
+ }
+
G.scene->r.efra = end_frame;
}
+ PyEval_RestoreThread(tstate);
Py_RETURN_NONE;
}
@@ -565,10 +581,13 @@ PyObject *RenderData_SaveRenderedImage ( BPy_RenderData * self, PyObject *args )
PyObject *RenderData_RenderAnim( BPy_RenderData * self )
{
Scene *oldsce;
-
+ /* unlock to prevent a deadlock when there are pynodes: */
+ PyThreadState *tstate = NULL;
+
if (!G.background) {
oldsce = G.scene;
set_scene( self->scene );
+ tstate = PyEval_SaveThread();
BIF_do_render( 1 );
set_scene( oldsce );
}
@@ -582,9 +601,18 @@ PyObject *RenderData_RenderAnim( BPy_RenderData * self )
if (G.scene->r.sfra > G.scene->r.efra)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"start frame must be less or equal to end frame");
-
+
+ if (G.f & G_DOSCRIPTLINKS)
+ BPY_do_all_scripts(SCRIPT_RENDER);
+
+ tstate = PyEval_SaveThread();
RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra);
+
+ if (G.f & G_DOSCRIPTLINKS)
+ BPY_do_all_scripts(SCRIPT_POSTRENDER);
}
+
+ PyEval_RestoreThread(tstate);
Py_RETURN_NONE;
}
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 252350ea72b..31f4596c264 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -2013,7 +2013,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
lx, (cy -= 19), buttonWidth, 19, &bmd->value,
- 0.0, 0.5, 5, 2,
+ 0.0, 0.5, 5, 4,
"Bevel value/amount");
/*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
lx, (cy -= 19), buttonWidth, 19, &bmd->res,
@@ -4518,11 +4518,12 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", 225, by-19,105, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
/* bone types */
- uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge", -10,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
- uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S", 70,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
- uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform", 90, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
- uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 170,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
- uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide", 250,by-38,80,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+ uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge", -10,by-38,60,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
+ uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S", 50,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
+ uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform", 70, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
+ uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 150,by-38,60,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
+ uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide", 210,by-38,60,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+ uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, REDRAWVIEW3D, "Lock", 270,by-38,60,18, &curBone->flag, 0, 0, 0, 0, "Prevents this bone from being transformed in Edit Mode");
/* layers */
uiBlockBeginAlign(block);
@@ -6335,6 +6336,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/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c
index 441d00ffc30..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, "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, "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, "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, "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_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, "");
- 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, "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, "");
+ }
- 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, "");
+ 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, "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-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");
+ 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, "");
- 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, "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;
@@ -2062,7 +2075,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
coa->time = 0;
uiDefButS(block, MENU, 1, str, xco+10, yco-65, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, "");
- uiDefButS(block, NUM, 0, "Damp:", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "");
+ uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
uiDefBut(block, LABEL, 0, "Min", xco+80, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
uiDefBut(block, LABEL, 0, "Max", xco+80+(width-90)/2, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
@@ -2084,12 +2097,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32";
uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray");
- uiDefButS(block, NUM, 0, "Damp:", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "");
+ uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
uiDefBut(block, LABEL, 0, "Range", xco+80, yco-45, (width-115)/2, 19, NULL, 0.0, 0.0, 0, 0, "Set the maximum length of ray");
uiDefButBitS(block, TOG, ACT_CONST_DISTANCE, B_REDR, "Dist", xco+80+(width-115)/2, yco-45, (width-115)/2, 19, &coa->flag, 0.0, 0.0, 0, 0, "Force distance of object to point of impact of ray");
- if(coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRMX)) fp= coa->minloc;
- else if(coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRMY)) fp= coa->minloc+1;
+ if(coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc;
+ else if(coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1;
else fp= coa->minloc+2;
uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/2, 19, fp+3, 0.0, 2000.0, 10, 0, "Maximum length of ray");
@@ -2124,7 +2137,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4";
uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Select the axis to be aligned along the reference direction");
- uiDefButS(block, NUM, 0, "Damp:", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "");
+ uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
uiDefBut(block, LABEL, 0, "X", xco+80, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
uiDefBut(block, LABEL, 0, "Y", xco+80+(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
uiDefBut(block, LABEL, 0, "Z", xco+80+2*(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
@@ -2133,7 +2146,9 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
uiDefButF(block, NUM, 0, "", xco+80+(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[1], -2000.0, 2000.0, 10, 0, "Y component of reference direction");
uiDefButF(block, NUM, 0, "", xco+80+2*(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[2], -2000.0, 2000.0, 10, 0, "Z component of reference direction");
- uiDefButS(block, NUM, 0, "time", xco+10, yco-84, 70+(width-115)/3, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited");
+ uiDefButS(block, NUM, 0, "time", xco+10, yco-84, 70, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited");
+ uiDefButF(block, NUM, 0, "min", xco+80, yco-84, (width-115)/2, 19, &(coa->minloc[0]), 0.0, 180.0, 10, 1, "Minimum angle (in degree) to maintain with target direction. No correction is done if angle with target direction is between min and max");
+ uiDefButF(block, NUM, 0, "max", xco+80+(width-115)/2, yco-84, (width-115)/2, 19, &(coa->maxloc[0]), 0.0, 180.0, 10, 1, "Maximum angle (in degree) allowed with target direction. No correction is done if angle with target direction is between min and max");
}
str= "Constraint Type %t|Location %x0|Distance %x1|Orientation %x2";
but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &coa->type, 0.0, 0.0, 0, 0, "");
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index ebe770c89e7..c2643aa479b 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) {
@@ -1739,6 +1739,16 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
}
break;
+
+ case CONSTRAINT_TYPE_SHRINKWRAP:
+ {
+ bShrinkwrapConstraint *data = con->data;
+
+ height = 44;
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->target, "Target Object");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "dist", *xco+120, *yco-44, 135, 18, &data->dist, 0.0f, 100.0f, 1.0f, 0.0f, "Distance to target");
+ }
+ break;
default:
height = 0;
break;
@@ -1800,6 +1810,7 @@ static uiBlock *add_constraintmenu(void *arg_unused)
uiDefBut(block, BUTM, B_CONSTRAINT_ADD_MINMAX, "Floor", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK, "Locked Track", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH, "Follow Path", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SHRINKWRAP, "Shrinkwrap" , 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
@@ -2035,6 +2046,14 @@ void do_constraintbuts(unsigned short event)
BIF_undo_push("Add constraint");
}
break;
+ case B_CONSTRAINT_ADD_SHRINKWRAP:
+ {
+ con = add_new_constraint(CONSTRAINT_TYPE_SHRINKWRAP);
+ add_constraint_to_active(ob, con);
+
+ BIF_undo_push("Add constraint");
+ }
+ break;
default:
break;
diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c
index 9b1af3f1a06..0782ccfc7ee 100644
--- a/source/blender/src/drawaction.c
+++ b/source/blender/src/drawaction.c
@@ -89,6 +89,7 @@
#include "BSE_drawnla.h"
#include "BSE_drawipo.h"
+#include "BSE_drawview.h"
#include "BSE_editaction_types.h"
#include "BSE_editipo.h"
#include "BSE_time.h"
@@ -467,7 +468,7 @@ static void draw_channel_names(void)
bActionGroup *grp = NULL;
short indent= 0, offset= 0, sel= 0, group=0;
int expand= -1, protect = -1, special= -1, mute = -1;
- char name[32];
+ char name[64];
/* determine what needs to be drawn */
switch (ale->type) {
@@ -625,6 +626,72 @@ static void draw_channel_names(void)
sprintf(name, "Constraint");
}
break;
+ case ACTTYPE_GPDATABLOCK: /* gpencil datablock */
+ {
+ bGPdata *gpd = (bGPdata *)ale->data;
+ ScrArea *sa = (ScrArea *)ale->owner;
+
+ indent = 0;
+ group= 3;
+
+ /* only show expand if there are any channels */
+ if (gpd->layers.first) {
+ if (gpd->flag & GP_DATA_EXPAND)
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+ }
+
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ /* this shouldn't cause any overflow... */
+ sprintf(name, "3DView: %s", view3d_get_name(sa->spacedata.first));
+ special= ICON_VIEW3D;
+ }
+ break;
+ case SPACE_NODE:
+ {
+ SpaceNode *snode= sa->spacedata.first;
+ char treetype[12];
+
+ if (snode->treetype == 1)
+ sprintf(treetype, "Composite");
+ else
+ sprintf(treetype, "Material");
+ sprintf(name, "Nodes: %s", treetype);
+
+ special= ICON_NODE;
+ }
+ break;
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq= sa->spacedata.first;
+ char imgpreview[10];
+
+ switch (sseq->mainb) {
+ case 1: sprintf(imgpreview, "Image..."); break;
+ case 2: sprintf(imgpreview, "Luma..."); break;
+ case 3: sprintf(imgpreview, "Chroma..."); break;
+ case 4: sprintf(imgpreview, "Histogram"); break;
+
+ default: sprintf(imgpreview, "Sequence"); break;
+ }
+ sprintf(name, "Sequencer: %s", imgpreview);
+
+ special= ICON_SEQUENCE;
+ }
+ break;
+
+ default:
+ {
+ sprintf(name, "<Unknown GP-Data Source>");
+ special= -1;
+ }
+ break;
+ }
+ }
+ break;
case ACTTYPE_GPLAYER: /* gpencil layer */
{
bGPDlayer *gpl = (bGPDlayer *)ale->data;
@@ -632,7 +699,8 @@ static void draw_channel_names(void)
indent = 0;
special = -1;
expand = -1;
-
+ group = 1;
+
if (EDITABLE_GPL(gpl))
protect = ICON_UNLOCKED;
else
@@ -651,8 +719,19 @@ static void draw_channel_names(void)
/* now, start drawing based on this information */
/* draw backing strip behind channel name */
- if (group == 2) {
- /* only for group-channels */
+ if (group == 3) {
+ /* only for gp-data channels */
+ if (ale->owner == curarea) // fixme... currently useless
+ BIF_ThemeColorShade(TH_GROUP_ACTIVE, 10);
+ else
+ BIF_ThemeColorShade(TH_GROUP, 20);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+ gl_round_box(GL_POLYGON, x, yminc, (float)NAMEWIDTH, ymaxc, 8);
+
+ offset = 0;
+ }
+ else if (group == 2) {
+ /* only for action group channels */
if (ale->flag & AGRP_ACTIVE)
BIF_ThemeColorShade(TH_GROUP_ACTIVE, 10);
else
@@ -698,13 +777,19 @@ static void draw_channel_names(void)
offset += 17;
}
- /* draw special icon indicating type of ipo-blocktype?
- * only for expand widgets for Ipo and Constraint Channels
- */
- if (special > 0) {
- offset = (group) ? 29 : 24;
- BIF_icon_draw(x+offset, yminc, special);
- offset += 17;
+ /* draw special icon indicating certain data-types */
+ if (special > -1) {
+ if (group == 3) {
+ /* for gpdatablock channels */
+ BIF_icon_draw(x+offset, yminc, special);
+ offset += 17;
+ }
+ else {
+ /* for ipo/constraint channels */
+ offset = (group) ? 29 : 24;
+ BIF_icon_draw(x+offset, yminc, special);
+ offset += 17;
+ }
}
/* draw name */
@@ -720,13 +805,13 @@ static void draw_channel_names(void)
offset = 0;
/* draw protect 'lock' */
- if (protect > 0) {
+ if (protect > -1) {
offset = 16;
BIF_icon_draw(NAMEWIDTH-offset, yminc, protect);
}
/* draw mute 'eye' */
- if (mute > 0) {
+ if (mute > -1) {
offset += 16;
BIF_icon_draw(NAMEWIDTH-offset, yminc, mute);
}
@@ -1148,12 +1233,6 @@ void drawactionspace(ScrArea *sa, void *spacedata)
G.saction->action= NULL;
}
break;
- case SACTCONT_GPENCIL:
- {
- /* this searching could be slow (so users should pin after this is found) */
- G.saction->gpd= gpencil_data_getetime(G.curscreen);
- }
- break;
}
}
diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c
index 55d0464b9af..733310bfda7 100644
--- a/source/blender/src/drawgpencil.c
+++ b/source/blender/src/drawgpencil.c
@@ -94,6 +94,7 @@
void gp_ui_activelayer_cb (void *gpd, void *gpl)
{
gpencil_layer_setactive(gpd, gpl);
+ allqueue(REDRAWACTION, 0);
}
/* rename layer and set active */
@@ -104,18 +105,21 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg)
BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info[0]), 128);
gpencil_layer_setactive(gpd, gpl);
+ allqueue(REDRAWACTION, 0);
}
/* add a new layer */
void gp_ui_addlayer_cb (void *gpd, void *dummy)
{
gpencil_layer_addnew(gpd);
+ allqueue(REDRAWACTION, 0);
}
/* delete active layer */
void gp_ui_dellayer_cb (void *gpd, void *dummy)
{
gpencil_layer_delactive(gpd);
+ allqueue(REDRAWACTION, 0);
}
/* delete last stroke of active layer */
@@ -134,28 +138,17 @@ void gp_ui_delframe_cb (void *gpd, void *gpl)
gpencil_layer_setactive(gpd, gpl);
gpencil_layer_delframe(gpl, gpf);
-}
-
-
-/* set this set of gpencil data for editing in action editor */
-void gp_ui_dotime_cb (void *gpd_arg, void *dummy)
-{
- bGPdata *gpd= (bGPdata *)gpd_arg;
- /* check if setting or clearing (note: setting was just set...) */
- if (gpd->flag & GP_DATA_EDITTIME)
- gpencil_data_setetime(G.curscreen, gpd);
- else
- gpencil_data_setetime(G.curscreen, NULL);
+ allqueue(REDRAWACTION, 0);
}
-
/* ------- Drawing Code ------- */
/* draw the controls for a given layer */
static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short *xco, short *yco)
{
uiBut *but;
+ short active= (gpl->flag & GP_LAYER_ACTIVE);
short width= 314;
short height;
int rb_col;
@@ -168,40 +161,41 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
uiBlockSetEmboss(block, UI_EMBOSSN);
/* rounded header */
- rb_col= (gpl->flag & GP_LAYER_ACTIVE)?50:20;
- uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, "");
+ if (active) uiBlockSetCol(block, TH_BUT_ACTION);
+ rb_col= (active)?-20:20;
+ uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, "");
+ if (active) uiBlockSetCol(block, TH_AUTO);
/* lock toggle */
uiDefIconButBitI(block, ICONTOG, GP_LAYER_LOCKED, B_REDR, ICON_UNLOCKED, *xco-7, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Layer cannot be modified");
}
- /* when layer is locked or hidden, don't draw the rest of its settings */
+ /* when layer is locked or hidden, only draw header */
if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
- height= 26;
+ char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
- /* draw rest of header */
- {
- /* visibility button (only if hidden but not locked!) */
- if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
- uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
-
- /* name */
- uiDefBut(block, LABEL, 1, gpl->info, *xco+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "Short description of what this layer is for (optional)");
- }
+ height= 26;
- /* draw backdrop */
- uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12, rb_col, "");
+ /* visibility button (only if hidden but not locked!) */
+ if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
+ uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
- /* draw settings... (i.e. just warning for this one) */
+ /* name */
if (gpl->flag & GP_LAYER_HIDE)
- uiDefBut(block, LABEL, 1, "Grease Pencil Layer Hidden", *xco+60, *yco-26, 205, 20, NULL, 0.0, 0.0, 0, 0, "");
+ sprintf(name, "%s (Hidden)", gpl->info);
else
- uiDefBut(block, LABEL, 1, "Grease Pencil Layer Locked", *xco+60, *yco-26, 205, 20, NULL, 0.0, 0.0, 0, 0, "");
+ sprintf(name, "%s (Locked)", gpl->info);
+ uiDefBut(block, LABEL, 1, name, *xco+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "Short description of what this layer is for (optional)");
+ /* delete button (only if hidden but not locked!) */
+ if ((gpl->flag & GP_LAYER_HIDE) & !(gpl->flag & GP_LAYER_LOCKED)) {
+ but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
+ uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
+ }
uiBlockSetEmboss(block, UI_EMBOSS);
}
else {
- height= 100;
+ height= 97;
/* draw rest of header */
{
@@ -211,7 +205,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
uiBlockSetEmboss(block, UI_EMBOSS);
/* name */
- but= uiDefButC(block, TEX, B_REDR, "Info:", *xco+35, *yco, 240, 20, gpl->info, 0, 127, 0, 0, "Short description of what this layer is for (optional)");
+ but= uiDefButC(block, TEX, B_REDR, "Info:", *xco+36, *yco, 240, 19, gpl->info, 0, 127, 0, 0, "Short description of what this layer is for (optional)");
uiButSetFunc(but, gp_ui_renamelayer_cb, gpd, gpl);
/* delete 'button' */
@@ -224,7 +218,9 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
}
/* draw backdrop */
- uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12, rb_col, "");
+ if (active) uiBlockSetCol(block, TH_BUT_ACTION);
+ uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12, rb_col, "");
+ if (active) uiBlockSetCol(block, TH_AUTO);
/* draw settings */
{
@@ -237,21 +233,25 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
/* stroke thickness */
uiDefButS(block, NUMSLI, B_REDR, "Thickness:", *xco, *yco-75, 150, 20, &gpl->thickness, 1, 10, 0, 0, "Thickness of strokes (in pixels)");
+ /* debugging options */
+ if (G.f & G_DEBUG) {
+ uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco, *yco-95, 150, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes");
+ }
/* onion-skinning */
uiBlockBeginAlign(block);
uiDefButBitI(block, TOG, GP_LAYER_ONIONSKIN, B_REDR, "Onion-Skin", *xco+160, *yco-26, 140, 20, &gpl->flag, 0, 0, 0, 0, "Ghost frames on either side of frame");
- uiDefButS(block, NUMSLI, B_REDR, "GStep:", *xco+160, *yco-46, 140, 20, &gpl->gstep, 0, 120, 0, 0, "Maximum frame range on either side of active frame to show (0 = just 'first' available frame on either side)");
+ uiDefButS(block, NUMSLI, B_REDR, "GStep:", *xco+160, *yco-46, 140, 20, &gpl->gstep, 0, 120, 0, 0, "Max number of frames on either side of active frame to show (0 = just 'first' available sketch on either side)");
uiBlockEndAlign(block);
/* options */
- but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer");
- uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
-
- but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame");
- uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
-
- //uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco+160, *yco-75, 130, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes");
+ uiBlockBeginAlign(block);
+ but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)");
+ uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
+
+ but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)");
+ uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
+ uiBlockEndAlign(block);
}
}
@@ -262,36 +262,40 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
/* Draw the contents for a grease-pencil panel. This assumes several things:
* - that panel has been created, is 318 x 204. max yco is 225
* - that a toggle for turning on/off gpencil drawing is 150 x 20, starting from (10,225)
+ * which is basically the top left-hand corner
* It will return the amount of extra space to extend the panel by
*/
short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa)
{
uiBut *but;
bGPDlayer *gpl;
- short xco= 10, yco= 155;
+ short xco= 10, yco= 170;
/* draw gpd settings first */
{
- /* show status info button */
- uiDefButBitI(block, TOG, GP_DATA_DISPINFO, B_REDR, "Show Status Info", 10, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "Display status info about current status of Grease Pencil");
-
- /* add new/duplicate layer buttons */
- but= uiDefBut(block, BUT, B_REDR, "Add New Layer", 10,182,150,20, 0, 0, 0, 0, 0, "Adds a new Grease Pencil Layer");
+ /* add new layer buttons */
+ but= uiDefBut(block, BUT, B_REDR, "Add New Layer", 10,205,150,20, 0, 0, 0, 0, 0, "Adds a new Grease Pencil Layer");
uiButSetFunc(but, gp_ui_addlayer_cb, gpd, NULL);
- /* show override lmb-clicks button */
- uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret LMB-click as new strokes (same as holding Shift-Key per stroke)");
+ /* show override lmb-clicks button + painting lock */
+ uiBlockBeginAlign(block);
+ 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) */
if (sa->spacetype == SPACE_VIEW3D)
- uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Draw in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space");
+ uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space");
else if (sa->spacetype != SPACE_SEQ) /* not available for sequencer yet */
uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas");
-
- /* show edit-in-action button */
- but= uiDefButBitI(block, TOG, GP_DATA_EDITTIME, B_REDR, "Edit Timing", 170, 182, 150, 20, &gpd->flag, 0, 0, 0, 0, "Edit timing of frames for the Grease Pencil block");
- uiButSetFunc(but, gp_ui_dotime_cb, gpd, NULL);
}
/* draw for each layer */
@@ -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)
{
@@ -422,6 +486,21 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
}
}
+/* 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])
+{
+ bGPDstroke *gps;
+
+ /* 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);
+ }
+}
+
/* draw grease-pencil datablock */
static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
{
@@ -437,11 +516,10 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
/* loop over layers, drawing them */
for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
bGPDframe *gpf;
- bGPDstroke *gps;
short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0;
short lthick= gpl->thickness;
- float color[4];
+ float color[4], tcolor[4];
/* don't draw layer if hidden */
if (gpl->flag & GP_LAYER_HIDE)
@@ -459,6 +537,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
/* set color, stroke thickness, and point size */
glLineWidth(lthick);
QUATCOPY(color, gpl->color); // just for copying 4 array elements
+ QUATCOPY(tcolor, gpl->color); // additional copy of color (for ghosting)
glColor4f(color[0], color[1], color[2], color[3]);
glPointSize(gpl->thickness + 2);
@@ -474,11 +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 */
- glColor4f(color[0], color[1], color[2], (color[3]-(i*0.7)));
-
- for (gps= gf->strokes.first; gps; gps= gps->next) {
- gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
- }
+ tcolor[3] = color[3] - (i/gpl->gstep);
+ gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor);
}
else
break;
@@ -489,11 +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 */
- glColor4f(color[0], color[1], color[2], (color[3]-(i*0.7)));
-
- for (gps= gf->strokes.first; gps; gps= gps->next) {
- gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
- }
+ tcolor[3] = color[3] - (i/gpl->gstep);
+ gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor);
}
else
break;
@@ -504,19 +577,14 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
}
else {
/* draw the strokes for the ghost frames (at half of the alpha set by user) */
- glColor4f(color[0], color[1], color[2], (color[3] / 7));
-
if (gpf->prev) {
- for (gps= gpf->prev->strokes.first; gps; gps= gps->next) {
- gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
- }
+ tcolor[3] = (color[3] / 7);
+ gp_draw_strokes(gpf->prev, winx, winy, dflag, debug, lthick, tcolor);
}
- glColor4f(color[0], color[1], color[2], (color[3] / 4));
if (gpf->next) {
- for (gps= gpf->next->strokes.first; gps; gps= gps->next) {
- gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
- }
+ tcolor[3] = (color[3] / 4);
+ gp_draw_strokes(gpf->next, winx, winy, dflag, debug, lthick, tcolor);
}
/* restore alpha */
@@ -525,20 +593,17 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
}
/* draw the strokes already in active frame */
- for (gps= gpf->strokes.first; gps; gps= gps->next) {
- gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
- }
+ tcolor[3]= color[3];
+ 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/drawnode.c b/source/blender/src/drawnode.c
index 3a73ee84ead..853df3bedfc 100644
--- a/source/blender/src/drawnode.c
+++ b/source/blender/src/drawnode.c
@@ -3336,7 +3336,7 @@ static void nodes_panel_gpencil(short cntrl) // NODES_HANDLER_GREASEPENCIL
uiNewPanelHeight(block, 204);
/* draw button for showing gpencil settings and drawings */
- uiDefButBitS(block, TOG, SNODE_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &snode->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Node Editor");
+ uiDefButBitS(block, TOG, SNODE_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &snode->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Node Editor (draw using Shift-LMB)");
/* extend the panel if the contents won't fit */
newheight= draw_gpencil_panel(block, gpd, curarea);
diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c
index c8c74ad8279..cc431c73a2e 100644
--- a/source/blender/src/drawseq.c
+++ b/source/blender/src/drawseq.c
@@ -134,7 +134,7 @@ static void seq_panel_gpencil(short cntrl) // SEQ_HANDLER_GREASEPENCIL
uiNewPanelHeight(block, 204);
/* draw button for showing gpencil settings and drawings */
- uiDefButBitI(block, TOG, SEQ_DRAW_GPENCIL, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sseq->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Sequencer View");
+ uiDefButBitI(block, TOG, SEQ_DRAW_GPENCIL, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sseq->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Sequencer View (draw using Shift-LMB)");
/* extend the panel if the contents won't fit */
newheight= draw_gpencil_panel(block, gpd, curarea);
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
index 14434504e7a..2030eb658de 100644
--- a/source/blender/src/drawview.c
+++ b/source/blender/src/drawview.c
@@ -1502,44 +1502,52 @@ static void draw_view_icon(void)
glDisable(GL_BLEND);
}
-static void draw_viewport_name(ScrArea *sa)
+char *view3d_get_name(View3D *v3d)
{
char *name = NULL;
- char *printable = NULL;
- switch(G.vd->view) {
+ switch (v3d->view) {
case 1:
- if (G.vd->persp == V3D_ORTHO)
- name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Ortho" : "Front Ortho";
+ if (v3d->persp == V3D_ORTHO)
+ name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Ortho" : "Front Ortho";
else
- name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Persp" : "Front Persp";
+ name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Persp" : "Front Persp";
break;
case 3:
- if (G.vd->persp == V3D_ORTHO)
- name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Ortho" : "Right Ortho";
+ if (v3d->persp == V3D_ORTHO)
+ name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Ortho" : "Right Ortho";
else
- name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Persp" : "Right Persp";
+ name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Persp" : "Right Persp";
break;
case 7:
- if (G.vd->persp == V3D_ORTHO)
- name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Ortho" : "Top Ortho";
+ if (v3d->persp == V3D_ORTHO)
+ name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Ortho" : "Top Ortho";
else
- name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Persp" : "Top Persp";
+ name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Persp" : "Top Persp";
break;
default:
- if (G.vd->persp==V3D_CAMOB) {
- if ((G.vd->camera) && (G.vd->camera->type == OB_CAMERA)) {
+ if (v3d->persp==V3D_CAMOB) {
+ if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
Camera *cam;
- cam = G.vd->camera->data;
+ cam = v3d->camera->data;
name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho";
} else {
name = "Object as Camera";
}
} else {
- name = (G.vd->persp == V3D_ORTHO) ? "User Ortho" : "User Persp";
+ name = (v3d->persp == V3D_ORTHO) ? "User Ortho" : "User Persp";
}
+ break;
}
+ return name;
+}
+
+static void draw_viewport_name(ScrArea *sa)
+{
+ char *name = view3d_get_name(sa->spacedata.first);
+ char *printable = NULL;
+
if (G.vd->localview) {
printable = malloc(strlen(name) + strlen(" (Local)_")); /* '_' gives space for '\0' */
strcpy(printable, name);
@@ -1987,6 +1995,8 @@ static void v3d_editarmature_buts(uiBlock *block, Object *ob, float lim)
tfp->ob_eul[0]= 180.0*ebone->roll/M_PI;
uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:", 10, 100, 140, 19, tfp->ob_eul, -lim, lim, 1000, 3, "");
+ uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, REDRAWVIEW3D, "Lock", 160, 100, 140, 19, &(ebone->flag), 0, 0, 0, 0, "Prevents bone from being transformed in edit mode");
+
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailRadius:", 10, 150, 140, 19, &ebone->rad_tail, 0, lim, 10, 3, "");
if (ebone->parent && ebone->flag & BONE_CONNECTED )
@@ -2654,7 +2664,7 @@ static void view3d_panel_gpencil(short cntrl) // VIEW3D_HANDLER_GREASEPENCIL
uiNewPanelHeight(block, 204);
/* draw button for showing gpencil settings and drawings */
- uiDefButBitS(block, TOG, V3D_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &vd->flag2, 0, 0, 0, 0, "Display freehand annotations overlay over this 3D View");
+ uiDefButBitS(block, TOG, V3D_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &vd->flag2, 0, 0, 0, 0, "Display freehand annotations overlay over this 3D View (draw using Shift-LMB)");
/* extend the panel if the contents won't fit */
newheight= draw_gpencil_panel(block, gpd, curarea);
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
index 3251cb33b53..c454715b1df 100644
--- a/source/blender/src/editaction.c
+++ b/source/blender/src/editaction.c
@@ -517,23 +517,43 @@ static void actdata_filter_shapekey (ListBase *act_data, Key *key, int filter_mo
}
}
-static void actdata_filter_gpencil (ListBase *act_data, bGPdata *gpd, int filter_mode)
+
+static void actdata_filter_gpencil (ListBase *act_data, bScreen *sc, int filter_mode)
{
bActListElem *ale;
+ ScrArea *sa;
+ bGPdata *gpd;
bGPDlayer *gpl;
/* check if filtering types are appropriate */
if ( !(filter_mode & (ACTFILTER_IPOKEYS|ACTFILTER_ONLYICU|ACTFILTER_ACTGROUPED)) )
{
- /* loop over layers as the conditions are acceptable */
- for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
- /* only if selected */
- if (!(filter_mode & ACTFILTER_SEL) || SEL_GPL(gpl)) {
- /* only if editable */
- if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
- /* add to list */
- ale= make_new_actlistelem(gpl, ACTTYPE_GPLAYER, NULL, ACTTYPE_NONE);
- if (ale) BLI_addtail(act_data, ale);
+ /* loop over spaces in current screen, finding gpd blocks (could be slow!) */
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ /* try to get gp data */
+ gpd= gpencil_data_getactive(sa);
+ if (gpd == NULL) continue;
+
+ /* add gpd as channel too (if for drawing, and it has layers) */
+ if ((filter_mode & ACTFILTER_FORDRAWING) && (gpd->layers.first)) {
+ /* add to list */
+ ale= make_new_actlistelem(gpd, ACTTYPE_GPDATABLOCK, sa, ACTTYPE_SPECIALDATA);
+ if (ale) BLI_addtail(act_data, ale);
+ }
+
+ /* only add layers if they will be visible (if drawing channels) */
+ if ( !(filter_mode & ACTFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
+ /* loop over layers as the conditions are acceptable */
+ for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+ /* only if selected */
+ if (!(filter_mode & ACTFILTER_SEL) || SEL_GPL(gpl)) {
+ /* only if editable */
+ if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+ /* add to list */
+ ale= make_new_actlistelem(gpl, ACTTYPE_GPLAYER, gpd, ACTTYPE_GPDATABLOCK);
+ if (ale) BLI_addtail(act_data, ale);
+ }
+ }
}
}
}
@@ -637,11 +657,8 @@ int get_nearest_key_num (Key *key, short *mval, float *x)
return (num + 1);
}
-/* this function is used to get a pointer to an action or shapekey
- * datablock, thus simplying that process.
- */
-/* this function is intended for use */
-void *get_nearest_act_channel (short mval[], short *ret_type)
+/* this function finds the channel that mouse is floating over */
+void *get_nearest_act_channel (short mval[], short *ret_type, void **owner)
{
ListBase act_data = {NULL, NULL};
bActListElem *ale;
@@ -652,6 +669,9 @@ void *get_nearest_act_channel (short mval[], short *ret_type)
int clickmin, clickmax;
float x,y;
+ /* init 'owner' return val */
+ *owner= NULL;
+
/* determine what type of data we are operating on */
data = get_action_context(&datatype);
if (data == NULL) {
@@ -679,6 +699,7 @@ void *get_nearest_act_channel (short mval[], short *ret_type)
/* found match */
*ret_type= ale->type;
data= ale->data;
+ *owner= ale->owner;
BLI_freelistN(&act_data);
@@ -854,10 +875,7 @@ void *get_action_context (short *datatype)
case SACTCONT_GPENCIL:
*datatype= ACTCONT_GPENCIL;
- if (G.saction->pin)
- return G.saction->gpd;
- else
- return gpencil_data_getetime(G.curscreen);
+ return G.curscreen; // FIXME: add that dopesheet type thing here!
default: /* includes SACTCONT_DOPESHEET for now */
*datatype= ACTCONT_NONE;
@@ -2327,7 +2345,7 @@ static void numbuts_action ()
void *data;
short datatype;
- void *act_channel;
+ void *act_channel, *channel_owner;
short chantype;
bActionGroup *agrp= NULL;
@@ -2335,6 +2353,7 @@ static void numbuts_action ()
bConstraintChannel *conchan= NULL;
IpoCurve *icu= NULL;
KeyBlock *kb= NULL;
+ bGPdata *gpd= NULL;
bGPDlayer *gpl= NULL;
short mval[2];
@@ -2353,7 +2372,7 @@ static void numbuts_action ()
getmouseco_areawin(mval);
if (mval[0] > NAMEWIDTH)
return;
- act_channel= get_nearest_act_channel(mval, &chantype);
+ act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner);
/* create items for clever-numbut */
if (chantype == ACTTYPE_ACHAN) {
@@ -2451,6 +2470,7 @@ static void numbuts_action ()
}
else if (chantype == ACTTYPE_GPLAYER) {
/* Grease-Pencil Layer */
+ gpd= (bGPdata *)channel_owner;
gpl= (bGPDlayer *)act_channel;
strcpy(str, gpl->info);
@@ -2511,7 +2531,7 @@ static void numbuts_action ()
}
else if (gpl) {
strcpy(gpl->info, str);
- BLI_uniquename(&( ((bGPdata *)data)->layers ), gpl, "GP_Layer", offsetof(bGPDlayer, info), 128);
+ BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info), 128);
if (mute) gpl->flag |= GP_LAYER_HIDE;
else gpl->flag &= ~GP_LAYER_HIDE;;
@@ -2871,9 +2891,10 @@ int select_gplayer_channel (bGPdata *gpd, bGPDlayer *gpl, int selectmode)
gpl->flag ^= GP_LAYER_SELECT;
break;
}
+
flag = (gpl->flag & GP_LAYER_SELECT) ? 1 : 0;
-
- gpencil_layer_setactive(gpd, gpl);
+ if (flag)
+ gpencil_layer_setactive(gpd, gpl);
return flag;
}
@@ -3100,11 +3121,11 @@ void selectall_action_keys (short mval[], short mode, short select_mode)
switch (mode) {
case 0: /* all in channel*/
{
- void *act_channel;
+ void *act_channel, *channel_owner;
short chantype;
/* get channel, and act according to type */
- act_channel= get_nearest_act_channel(mval, &chantype);
+ act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner);
switch (chantype) {
case ACTTYPE_GROUP:
{
@@ -3939,8 +3960,7 @@ static void mouse_action (int selectmode)
static void mouse_actionchannels (short mval[])
{
bAction *act= G.saction->action;
- bGPdata *gpd= G.saction->gpd;
- void *data, *act_channel;
+ void *data, *act_channel, *channel_owner;
short datatype, chantype;
/* determine what type of data we are operating on */
@@ -3948,7 +3968,7 @@ static void mouse_actionchannels (short mval[])
if (data == NULL) return;
/* get channel to work on */
- act_channel= get_nearest_act_channel(mval, &chantype);
+ act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner);
/* action to take depends on what channel we've got */
switch (chantype) {
@@ -4086,8 +4106,17 @@ static void mouse_actionchannels (short mval[])
}
}
break;
+ case ACTTYPE_GPDATABLOCK:
+ {
+ bGPdata *gpd= (bGPdata *)act_channel;
+
+ /* toggle expand */
+ gpd->flag ^= GP_DATA_EXPAND;
+ }
+ break;
case ACTTYPE_GPLAYER:
{
+ bGPdata *gpd= (bGPdata *)channel_owner;
bGPDlayer *gpl= (bGPDlayer *)act_channel;
if (mval[0] >= (NAMEWIDTH-16)) {
@@ -4100,7 +4129,13 @@ static void mouse_actionchannels (short mval[])
}
else {
/* select/deselect */
- select_gplayer_channel(gpd, gpl, SELECT_INVERT);
+ if (G.qual & LR_SHIFTKEY) {
+ select_gplayer_channel(gpd, gpl, SELECT_INVERT);
+ }
+ else {
+ deselect_gpencil_layers(data, 0);
+ select_gplayer_channel(gpd, gpl, SELECT_INVERT);
+ }
}
}
break;
diff --git a/source/blender/src/editaction_gpencil.c b/source/blender/src/editaction_gpencil.c
index b91c5a8b332..14269080b1f 100644
--- a/source/blender/src/editaction_gpencil.c
+++ b/source/blender/src/editaction_gpencil.c
@@ -246,7 +246,7 @@ void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short se
/* De-selects or inverts the selection of Layers for a grease-pencil block
* mode: 0 = default behaviour (select all), 1 = test if (de)select all, 2 = invert all
*/
-void deselect_gpencil_layers (bGPdata *gpd, short mode)
+void deselect_gpencil_layers (void *data, short mode)
{
ListBase act_data = {NULL, NULL};
bActListElem *ale;
@@ -254,7 +254,7 @@ void deselect_gpencil_layers (bGPdata *gpd, short mode)
/* filter data */
filter= ACTFILTER_VISIBLE;
- actdata_filter(&act_data, filter, gpd, ACTCONT_GPENCIL);
+ actdata_filter(&act_data, filter, data, ACTCONT_GPENCIL);
/* See if we should be selecting or deselecting */
if (mode == 1) {
@@ -294,7 +294,6 @@ void delete_gpencil_layers (void)
{
ListBase act_data = {NULL, NULL};
bActListElem *ale, *next;
- bGPdata *gpd;
void *data;
short datatype;
int filter;
@@ -303,7 +302,6 @@ void delete_gpencil_layers (void)
data = get_action_context(&datatype);
if (data == NULL) return;
if (datatype != ACTCONT_GPENCIL) return;
- gpd= (bGPdata *)data;
/* filter data */
filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_CHANNELS | ACTFILTER_SEL);
@@ -311,6 +309,7 @@ void delete_gpencil_layers (void)
/* clean up grease-pencil layers */
for (ale= act_data.first; ale; ale= next) {
+ bGPdata *gpd= (bGPdata *)ale->owner;
bGPDlayer *gpl= (bGPDlayer *)ale->data;
next= ale->next;
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
index 6310dd0a262..3d0f26960d6 100644
--- a/source/blender/src/editarmature.c
+++ b/source/blender/src/editarmature.c
@@ -2709,6 +2709,32 @@ void show_all_armature_bones(void)
BIF_undo_push("Reveal Bones");
}
+/* Sets editmode transform locks for bones (adds if lock==1, clears otherwise) */
+void set_locks_armature_bones(short lock)
+{
+ bArmature *arm= G.obedit->data;
+ EditBone *ebone;
+
+ for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
+ if (arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_SELECTED) {
+ if (lock)
+ ebone->flag |= BONE_EDITMODE_LOCKED;
+ else
+ ebone->flag &= ~BONE_EDITMODE_LOCKED;
+ }
+ }
+ }
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+
+ if (lock)
+ BIF_undo_push("Lock Bones");
+ else
+ BIF_undo_push("Unlock Bones");
+}
+
/* check for null, before calling! */
static void bone_connect_to_existing_parent(EditBone *bone)
{
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/editnode.c b/source/blender/src/editnode.c
index 5c137e67c1a..98f4f1bb46f 100644
--- a/source/blender/src/editnode.c
+++ b/source/blender/src/editnode.c
@@ -2400,7 +2400,7 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
switch(event) {
case LEFTMOUSE:
- if(gpencil_do_paint(sa)) {
+ if(gpencil_do_paint(sa, L_MOUSE)) {
return;
}
else if(fromlib) {
@@ -2421,7 +2421,10 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
break;
case RIGHTMOUSE:
- if(find_indicated_socket(snode, &actnode, &actsock, SOCK_IN)) {
+ if(gpencil_do_paint(sa, R_MOUSE)) {
+ return;
+ }
+ else if(find_indicated_socket(snode, &actnode, &actsock, SOCK_IN)) {
if(actsock->flag & SOCK_SEL) {
snode->edittree->selin= NULL;
actsock->flag&= ~SOCK_SEL;
@@ -2568,8 +2571,13 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
break;
case DELKEY:
case XKEY:
- if(fromlib) fromlib= -1;
- else node_delete(snode);
+ if(G.qual==LR_ALTKEY) {
+ gpencil_delete_menu();
+ }
+ else {
+ if(fromlib) fromlib= -1;
+ else node_delete(snode);
+ }
break;
}
}
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 6af4f47ed11..cbf7691754d 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -2760,7 +2760,7 @@ void special_editmenu(void)
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
}
else if(G.obedit->type==OB_ARMATURE) {
- nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6");
+ nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6|%l|Lock%x7|Unlock%x8");
if(nr==1)
subdivide_armature(1);
if(nr==2) {
@@ -2773,6 +2773,10 @@ void special_editmenu(void)
else if(ELEM3(nr, 4, 5, 6)) {
armature_autoside_names(nr-4);
}
+ else if(nr==7)
+ set_locks_armature_bones(1);
+ else if(nr==8)
+ set_locks_armature_bones(0);
}
else if(G.obedit->type==OB_LATTICE) {
static float weight= 1.0f;
@@ -3502,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);
}
@@ -3688,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/editseq.c b/source/blender/src/editseq.c
index f9432f8e69a..12019a9dab9 100644
--- a/source/blender/src/editseq.c
+++ b/source/blender/src/editseq.c
@@ -122,13 +122,28 @@ Sequence *get_last_seq()
if(!_last_seq_init) {
Editing *ed;
Sequence *seq;
+ Sequence *l_sel = NULL;
+ Sequence *l_act = NULL;
ed= G.scene->ed;
if(!ed) return NULL;
- for(seq= ed->seqbasep->first; seq; seq=seq->next)
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if(seq->flag & SEQ_ACTIVE)
+ l_act = seq;
if(seq->flag & SELECT)
- _last_seq= seq;
+ l_sel = seq;
+ }
+
+ if (l_act) {
+ _last_seq = l_act;
+ } else {
+ _last_seq = l_sel;
+ }
+
+ if (_last_seq) {
+ _last_seq->flag |= SEQ_ACTIVE;
+ }
_last_seq_init = 1;
}
@@ -138,12 +153,23 @@ Sequence *get_last_seq()
void set_last_seq(Sequence *seq)
{
+ if (_last_seq_init && _last_seq) {
+ _last_seq->flag &= ~SEQ_ACTIVE;
+ }
+
_last_seq = seq;
_last_seq_init = 1;
+
+ if (_last_seq) {
+ _last_seq->flag |= SEQ_ACTIVE;
+ }
}
-void clear_last_seq(Sequence *seq)
+void clear_last_seq()
{
+ if (_last_seq_init && _last_seq) {
+ _last_seq->flag &= ~SEQ_ACTIVE;
+ }
_last_seq = NULL;
_last_seq_init = 0;
}
@@ -2261,6 +2287,8 @@ static Sequence *dupli_seq(Sequence *seq)
"handled in duplicate!\nExpect a crash"
" now...\n");
}
+
+ seqn->flag &= ~SEQ_ACTIVE;
return seqn;
}
diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c
index e3ec69975de..a3fcad7885c 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;
@@ -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 fa32b0ac7d4..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"
@@ -57,6 +58,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"
@@ -383,111 +385,6 @@ short gpencil_data_setactive (ScrArea *sa, bGPdata *gpd)
return 0;
}
-/* Find gp-data destined for editing in animation editor (for editing time) */
-bGPdata *gpencil_data_getetime (bScreen *sc)
-{
- bGPdata *gpd= NULL;
- ScrArea *sa;
-
- /* error checking */
- if (sc == NULL)
- return NULL;
-
- /* search through areas, checking if an appropriate gp-block is available
- * (this assumes that only one will have the active flag set)
- */
- for (sa= sc->areabase.first; sa; sa= sa->next) {
- /* handle depending on space type */
- switch (sa->spacetype) {
- case SPACE_VIEW3D: /* 3d-view */
- {
- View3D *v3d= sa->spacedata.first;
- gpd= v3d->gpd;
- }
- break;
- case SPACE_NODE: /* Node Editor */
- {
- SpaceNode *snode= sa->spacedata.first;
- gpd= snode->gpd;
- }
- break;
- case SPACE_SEQ: /* Sequence Editor - Image Preview */
- {
- SpaceSeq *sseq= sa->spacedata.first;
-
- if (sseq->mainb)
- gpd= sseq->gpd;
- else
- gpd= NULL;
- }
- break;
-
- default: /* unsupported space-type */
- gpd= NULL;
- break;
- }
-
- /* check if ok */
- if ((gpd) && (gpd->flag & GP_DATA_EDITTIME))
- return gpd;
- }
-
- /* didn't find a match */
- return NULL;
-}
-
-/* make sure only the specified view can have gp-data for time editing
- * - gpd can be NULL, if we wish to make sure no gp-data is being edited
- */
-void gpencil_data_setetime (bScreen *sc, bGPdata *gpd)
-{
- bGPdata *gpdn= NULL;
- ScrArea *sa;
-
- /* error checking */
- if (sc == NULL)
- return;
-
- /* search through areas, checking if an appropriate gp-block is available
- * (this assumes that only one will have the active flag set)
- */
- for (sa= sc->areabase.first; sa; sa= sa->next) {
- /* handle depending on space type */
- switch (sa->spacetype) {
- case SPACE_VIEW3D: /* 3d-view */
- {
- View3D *v3d= sa->spacedata.first;
- gpdn= v3d->gpd;
- }
- break;
- case SPACE_NODE: /* Node Editor */
- {
- SpaceNode *snode= sa->spacedata.first;
- gpdn= snode->gpd;
- }
- break;
- case SPACE_SEQ: /* Sequence Editor - Image Preview */
- {
- SpaceSeq *sseq= sa->spacedata.first;
- gpdn= sseq->gpd;
- }
- break;
-
- default: /* unsupported space-type */
- gpdn= NULL;
- break;
- }
-
- /* clear flag if a gp-data block found */
- if (gpdn)
- gpdn->flag &= ~GP_DATA_EDITTIME;
- }
-
- /* set active flag for this block (if it is provided) */
- if (gpd)
- gpd->flag |= GP_DATA_EDITTIME;
-}
-
/* -------- GP-Frame API ---------- */
/* delete the last stroke of the given frame */
@@ -721,7 +618,7 @@ void gpencil_delete_actframe (bGPdata *gpd)
* 2 - active frame
* 3 - active layer
*/
-void gpencil_delete_operation (short mode) // unused
+void gpencil_delete_operation (short mode)
{
bGPdata *gpd;
@@ -747,11 +644,15 @@ void gpencil_delete_operation (short mode) // unused
}
/* display a menu for deleting different grease-pencil elements */
-void gpencil_delete_menu (void) // unused
+void gpencil_delete_menu (void)
{
+ bGPdata *gpd= gpencil_data_getactive(NULL);
short mode;
- mode= pupmenu("Erase...%t|Last Stroke%x1|Active Frame%x2|Active Layer%x3");
+ /* only show menu if it will be relevant */
+ if (gpd == NULL) return;
+
+ mode= pupmenu("Grease Pencil Erase...%t|Last Stroke%x1|Active Frame%x2|Active Layer%x3");
if (mode <= 0) return;
gpencil_delete_operation(mode);
@@ -763,7 +664,14 @@ void gpencil_delete_menu (void) // unused
/* ---------- 'Globals' and Defines ----------------- */
/* maximum sizes of gp-session buffer */
-#define GP_STROKE_BUFFER_MAX 500
+#define GP_STROKE_BUFFER_MAX 5000
+
+/* Hardcoded sensitivity thresholds... */
+// TODO: one day, these might be added to the UI if it is necessary
+ /* minimum number of pixels mouse should move before new point created */
+#define MIN_MANHATTEN_PX 3
+ /* minimum length of new segment before new point can be added */
+#define MIN_EUCLIDEAN_PX 20
/* ------ */
@@ -777,7 +685,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 */
@@ -787,6 +695,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 */
@@ -804,9 +718,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;
@@ -944,6 +858,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[])
{
@@ -979,23 +912,23 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[])
}
/* add current stroke-point to buffer (returns whether point was successfully added) */
-static short gp_stroke_addpoint (tGPsdata *p, short mval[], float pressure)
+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)
return GP_STROKEADD_OVERFLOW;
-
/* get pointer to destination point */
- pt= gpd->sbuffer + gpd->sbuffer_size;
-
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, mval, &pt->x);
+ pt= ((tGPspoint *)(gpd->sbuffer) + gpd->sbuffer_size);
- /* 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 */
@@ -1008,35 +941,13 @@ static short gp_stroke_addpoint (tGPsdata *p, short mval[], 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;
-
- /* 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 */
@@ -1062,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++;
}
@@ -1070,10 +986,220 @@ 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 - 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;
+ 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);
+ }
+
+ /* 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 {
+ /* 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 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;
+ }
+ }
+ }
+ }
+}
+
+/* -------- */
+
+/* erase strokes which fall under the eraser strokes */
+static void gp_stroke_doeraser (tGPsdata *p)
+{
+ bGPdata *gpd= p->gpd;
+ bGPDframe *gpf= p->gpf;
+ bGPDstroke *gps, *gpn;
+ short (*mcoords)[2];
+ rcti rect;
+
+ /* get buffer-stroke coordinates as shorts array, and then get bounding box */
+ mcoords= gp_stroke_eraser_2mco(gpd);
+ lasso_select_boundbox(&rect, mcoords, gpd->sbuffer_size);
+
+ /* loop over strokes, checking segments for intersections */
+ for (gps= gpf->strokes.first; gps; gps= gpn) {
+ gpn= gps->next;
+ gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, &rect, gpf, gps);
+ }
+
+ /* free mcoords array */
+ MEM_freeN(mcoords);
+}
+
/* ---------- 'Paint' Tool ------------ */
/* init new stroke */
-static void gp_paint_initstroke (tGPsdata *p)
+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);
@@ -1096,8 +1222,13 @@ static void gp_paint_initstroke (tGPsdata *p)
}
else
p->gpf->flag |= GP_FRAME_PAINT;
-
- /* check if points will need to be made in 3d-space */
+
+ /* set 'eraser' for this stroke if using eraser */
+ p->paintmode= paintmode;
+ if (p->paintmode == GP_PAINTMODE_ERASER)
+ p->gpd->sbuffer_sflag |= GP_STROKE_ERASER;
+
+ /* check if points will need to be made in view-aligned space */
if (p->gpd->flag & GP_DATA_VIEWALIGN) {
switch (p->sa->spacetype) {
case SPACE_VIEW3D:
@@ -1125,11 +1256,15 @@ static void gp_paint_initstroke (tGPsdata *p)
/* 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 */
- gp_stroke_smooth(p);
-
- /* transfer stroke to frame */
- gp_stroke_newfrombuffer(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 */
+ gp_stroke_newfrombuffer(p);
+ }
/* clean up buffer now */
gp_session_validatebuffer(p);
@@ -1151,13 +1286,13 @@ static void gp_paint_cleanup (tGPsdata *p)
//BIF_undo_push("GPencil Stroke");
/* force redraw after drawing action */
- force_draw(0);
+ force_draw_plus(SPACE_ACTION, 0);
}
/* -------- */
/* 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];
@@ -1170,7 +1305,7 @@ short gpencil_paint (short mousebutton)
gp_session_cleanup(&p);
return 0;
}
- gp_paint_initstroke(&p);
+ gp_paint_initstroke(&p, paintmode);
if (p.status == GP_STATUS_ERROR) {
gp_session_cleanup(&p);
return 0;
@@ -1202,7 +1337,7 @@ short gpencil_paint (short mousebutton)
pressure = get_pressure();
/* only add current point to buffer if mouse moved (otherwise wait until it does) */
- if ((mval[0] != prevmval[0]) || (mval[1] != prevmval[1])) {
+ if (gp_stroke_filtermval(&p, mval, prevmval)) {
/* try to add point */
ok= gp_stroke_addpoint(&p, mval, pressure);
@@ -1245,7 +1380,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);
@@ -1259,28 +1397,52 @@ 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 gpencil_do_paint (ScrArea *sa, short mbut)
{
bGPdata *gpd = gpencil_data_getactive(sa);
- short mousebutton = L_MOUSE; /* for now, this is always on L_MOUSE*/
short retval= 0;
/* check if possible to do painting */
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_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 (G.qual == LR_SHIFTKEY) {
- /* try to paint */
- retval = gpencil_paint(mousebutton);
+ 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 */
diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c
index 50d343ca470..4bb7bb9677e 100644
--- a/source/blender/src/header_action.c
+++ b/source/blender/src/header_action.c
@@ -1683,7 +1683,7 @@ void action_buttons(void)
"Channel", xco, -2, xmax-3, 24, "");
xco+= xmax;
}
- else if ((G.saction->gpd) && (G.saction->mode==SACTCONT_GPENCIL)) {
+ else if (G.saction->mode==SACTCONT_GPENCIL) {
xmax= GetButStringLength("Channel");
uiDefPulldownBut(block, action_gplayermenu, NULL,
"Channel", xco, -2, xmax-3, 24, "");
@@ -1722,24 +1722,7 @@ void action_buttons(void)
xco += (90 + 8);
/* MODE-DEPENDENT DRAWING */
- if (G.saction->mode == SACTCONT_GPENCIL) {
- char gp_name[64];
-
- /* pin button */
- uiDefIconButS(block, ICONTOG, B_ACTPIN, ICON_PIN_DEHLT, xco,0,XIC,YIC, &G.saction->pin, 0, 0, 0, 0, "Keeps this view displaying the current data regardless of what Grease Pencil set is active");
- xco += (XIC + 5);
-
- /* just a simple string to help identify if any content */
- glRasterPos2f((float)xco, 5.0);
- BIF_RasterPos((float)xco, 5.0); // stupid texture fonts
- BIF_ThemeColor(TH_TEXT);
-
- sprintf(gp_name, (G.saction->gpd)?"Grease Pencil Data":"<None>");
- xmax= GetButStringLength(gp_name);
- BIF_DrawString(uiBlockGetCurFont(block), gp_name, (U.transopts & USER_TR_BUTTONS));
- xco += xmax;
- }
- else {
+ if (G.saction->mode != SACTCONT_GPENCIL) {
/* NAME ETC */
ob= OBACT;
from = (ID *)ob;
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){
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, "");
diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c
index ba8649eaa86..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);
@@ -5651,6 +5651,8 @@ static int ui_auto_themecol(uiBut *but)
// (weak!) detect if it is a blockloop
if(but->block->dt == UI_EMBOSSP) return TH_MENU_ITEM;
return TH_BUT_POPUP;
+ case ROUNDBOX:
+ return TH_PANEL;
default:
return TH_BUT_NEUTRAL;
}
diff --git a/source/blender/src/interface_draw.c b/source/blender/src/interface_draw.c
index e7041e60003..83ae449b989 100644
--- a/source/blender/src/interface_draw.c
+++ b/source/blender/src/interface_draw.c
@@ -2351,7 +2351,7 @@ static void ui_draw_roundbox(uiBut *but)
{
glEnable(GL_BLEND);
- BIF_ThemeColorShadeAlpha(TH_PANEL, but->a2, but->a2);
+ BIF_ThemeColorShadeAlpha(but->themecol, but->a2, but->a2);
uiSetRoundBox(but->a1);
gl_round_box(GL_POLYGON, but->x1, but->y1, but->x2, but->y2, but->min);
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)
diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c
index 683b06aafc4..3f328a0cfb2 100644
--- a/source/blender/src/outliner.c
+++ b/source/blender/src/outliner.c
@@ -68,6 +68,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
@@ -698,6 +699,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
for (index=0,md=ob->modifiers.first; md; index++,md=md->next) {
TreeElement *te = outliner_add_element(soops, &temod->subtree, ob, temod, TSE_MODIFIER, index);
te->name= md->name;
+ te->directdata = md;
if (md->type==eModifierType_Lattice) {
outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_LINKED_OB, 0);
@@ -3523,6 +3525,27 @@ static void restrictbutton_r_lay_cb(void *poin, void *poin2)
allqueue(REDRAWBUTSSCENE, 0);
}
+static void restrictbutton_modifier_cb(void *poin, void *poin2)
+{
+ Object *ob = (Object *)poin;
+
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ object_handle_update(ob);
+ countall();
+
+ allqueue(REDRAWOOPS, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+ allqueue(REDRAWBUTSOBJECT, 0);
+}
+
+static void restrictbutton_bone_cb(void *poin, void *poin2)
+{
+ allqueue(REDRAWOOPS, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+}
+
static void namebutton_cb(void *tep, void *oldnamep)
{
SpaceOops *soops= curarea->spacedata.first;
@@ -3631,7 +3654,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, SpaceOops *soops, ListBas
uiBut *bt;
TreeElement *te;
TreeStoreElem *tselem;
- Object *ob;
+ Object *ob = NULL;
for(te= lb->first; te; te= te->next) {
tselem= TREESTORE(te);
@@ -3639,7 +3662,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, SpaceOops *soops, ListBas
/* objects have toggle-able restriction flags */
if(tselem->type==0 && te->idcode==ID_OB) {
ob = (Object *)tselem->id;
-
+
uiBlockSetEmboss(block, UI_EMBOSSN);
bt= uiDefIconButBitS(block, ICONTOG, OB_RESTRICT_VIEW, REDRAWALL, ICON_RESTRICT_VIEW_OFF,
(int)soops->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, te->ys, 17, OL_H-1, &(ob->restrictflag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
@@ -3685,6 +3708,40 @@ static void outliner_draw_restrictbuts(uiBlock *block, SpaceOops *soops, ListBas
uiBlockSetEmboss(block, UI_EMBOSS);
}
+ else if(tselem->type==TSE_MODIFIER) {
+ ModifierData *md= (ModifierData *)te->directdata;
+ ob = (Object *)tselem->id;
+
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, REDRAWALL, ICON_RESTRICT_VIEW_OFF,
+ (int)soops->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility 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);
+ uiButSetFlag(bt, UI_NO_HILITE);
+ }
+ else if(tselem->type==TSE_POSE_CHANNEL) {
+ bPoseChannel *pchan= (bPoseChannel *)te->directdata;
+ Bone *bone = pchan->bone;
+
+ 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, NULL, NULL);
+ uiButSetFlag(bt, UI_NO_HILITE);
+ }
+ else if(tselem->type==TSE_EBONE) {
+ EditBone *ebone= (EditBone *)te->directdata;
+
+ 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, NULL, NULL);
+ uiButSetFlag(bt, UI_NO_HILITE);
+ }
}
if((tselem->flag & TSE_CLOSED)==0) outliner_draw_restrictbuts(block, soops, &te->subtree);
diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c
index cc08bf53a72..b054b435002 100644
--- a/source/blender/src/poseobject.c
+++ b/source/blender/src/poseobject.c
@@ -180,27 +180,26 @@ bPoseChannel *get_active_posechannel (Object *ob)
return NULL;
}
-/* if a selected or active bone is protected, throw error and return 1 */
+/* if a selected or active bone is protected, throw error (oonly if warn==1) and return 1 */
/* only_selected==1 : the active bone is allowed to be protected */
-static int pose_has_protected_selected(Object *ob, int only_selected)
+static short pose_has_protected_selected(Object *ob, short only_selected, short warn)
{
-
/* check protection */
- if(ob->proxy) {
+ if (ob->proxy) {
bPoseChannel *pchan;
bArmature *arm= ob->data;
- for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if(pchan->bone && (pchan->bone->layer & arm->layer)) {
- if(pchan->bone->layer & arm->layer_protected) {
- if(only_selected && (pchan->bone->flag & BONE_ACTIVE));
- else if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED))
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone && (pchan->bone->layer & arm->layer)) {
+ if (pchan->bone->layer & arm->layer_protected) {
+ if (only_selected && (pchan->bone->flag & BONE_ACTIVE));
+ else if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED))
break;
}
}
}
- if(pchan) {
- error("Cannot change Proxy protected bones");
+ if (pchan) {
+ if (warn) error("Cannot change Proxy protected bones");
return 1;
}
}
@@ -540,7 +539,7 @@ void pose_clear_IK(void)
if(!ob && !ob->pose) return;
if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
- if(pose_has_protected_selected(ob, 0))
+ if(pose_has_protected_selected(ob, 0, 1))
return;
if(okee("Remove IK constraint(s)")==0) return;
@@ -581,7 +580,7 @@ void pose_clear_constraints(void)
if(!ob && !ob->pose) return;
if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
- if(pose_has_protected_selected(ob, 0))
+ if(pose_has_protected_selected(ob, 0, 1))
return;
if(okee("Remove Constraints")==0) return;
@@ -612,38 +611,49 @@ void pose_copy_menu(void)
Object *ob= OBACT;
bArmature *arm= ob->data;
bPoseChannel *pchan, *pchanact;
- short nr;
+ short nr=0;
int i=0;
/* paranoia checks */
- if(!ob && !ob->pose) return;
- if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
+ if (ELEM(NULL, ob, ob->pose)) return;
+ if ((ob==G.obedit) || (ob->flag & OB_POSEMODE)==0) return;
/* find active */
- for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if(pchan->bone->flag & BONE_ACTIVE) break;
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (pchan->bone->flag & BONE_ACTIVE)
+ break;
}
- if(pchan==NULL) return;
-
- if(pose_has_protected_selected(ob, 1))
- return;
-
+ if (pchan==NULL) return;
pchanact= pchan;
- i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
- if (i<25)
- nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8");
- else
- nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8");
+ /* if proxy-protected bones selected, some things (such as locks + displays) shouldn't be changable,
+ * but for constraints (just add local constraints)
+ */
+ if (pose_has_protected_selected(ob, 1, 0)) {
+ i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
+ if (i < 25)
+ nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5");
+ else
+ nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4");
+ }
+ else {
+ i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
+ if (i < 25)
+ nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8");
+ else
+ nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8");
+ }
- if(nr==-1) return;
- if(nr!=5) {
- for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if( (arm->layer & pchan->bone->layer) &&
- (pchan->bone->flag & BONE_SELECTED) &&
- (pchan!=pchanact)
- ) {
+ if (nr <= 0)
+ return;
+
+ if (nr != 5) {
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ( (arm->layer & pchan->bone->layer) &&
+ (pchan->bone->flag & BONE_SELECTED) &&
+ (pchan != pchanact) )
+ {
switch (nr) {
case 1: /* Local Location */
VECCOPY(pchan->loc, pchanact->loc);
@@ -656,13 +666,26 @@ void pose_copy_menu(void)
break;
case 4: /* All Constraints */
{
- free_constraints(&pchan->constraints);
- copy_constraints(&pchan->constraints, &pchanact->constraints);
- pchan->constflag = pchanact->constflag;
+ ListBase tmp_constraints = {NULL, NULL};
- if (ob->pose) {
- ob->pose->flag |= POSE_RECALC;
+ /* copy constraints to tmpbase and apply 'local' tags before
+ * appending to list of constraints for this channel
+ */
+ copy_constraints(&tmp_constraints, &pchanact->constraints);
+ if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
+ bConstraint *con;
+
+ /* add proxy-local tags */
+ for (con= tmp_constraints.first; con; con= con->next)
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
}
+ addlisttolist(&pchan->constraints, &tmp_constraints);
+
+ /* update flags (need to add here, not just copy) */
+ pchan->constflag |= pchanact->constflag;
+
+ if (ob->pose)
+ ob->pose->flag |= POSE_RECALC;
}
break;
case 6: /* Transform Locks */
@@ -703,12 +726,13 @@ void pose_copy_menu(void)
}
}
}
- } else { /* constraints, optional */
+ }
+ else { /* constraints, optional (note: max we can have is 24 constraints) */
bConstraint *con, *con_back;
int const_toggle[24];
- ListBase const_copy={0, 0};
+ ListBase const_copy = {NULL, NULL};
- duplicatelist (&const_copy, &(pchanact->constraints));
+ duplicatelist(&const_copy, &(pchanact->constraints));
/* build the puplist of constraints */
for (con = pchanact->constraints.first, i=0; con; con=con->next, i++){
@@ -723,32 +747,46 @@ void pose_copy_menu(void)
/* now build a new listbase from the options selected */
for (i=0, con=const_copy.first; con; i++) {
+ /* if not selected, free/remove it from the list */
if (!const_toggle[i]) {
con_back= con->next;
BLI_freelinkN(&const_copy, con);
con= con_back;
- } else {
+ }
+ else
con= con->next;
- }
}
/* Copy the temo listbase to the selected posebones */
- for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if( (arm->layer & pchan->bone->layer) &&
- (pchan->bone->flag & BONE_SELECTED) &&
- (pchan!=pchanact)
- ) {
- free_constraints(&pchan->constraints);
- copy_constraints(&pchan->constraints, &const_copy);
- pchan->constflag = pchanact->constflag;
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ( (arm->layer & pchan->bone->layer) &&
+ (pchan->bone->flag & BONE_SELECTED) &&
+ (pchan!=pchanact) )
+ {
+ ListBase tmp_constraints = {NULL, NULL};
+
+ /* copy constraints to tmpbase and apply 'local' tags before
+ * appending to list of constraints for this channel
+ */
+ copy_constraints(&tmp_constraints, &const_copy);
+ if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
+ bConstraint *con;
+
+ /* add proxy-local tags */
+ for (con= tmp_constraints.first; con; con= con->next)
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+ }
+ addlisttolist(&pchan->constraints, &tmp_constraints);
+
+ /* update flags (need to add here, not just copy) */
+ pchan->constflag |= pchanact->constflag;
}
}
BLI_freelistN(&const_copy);
update_pose_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */
- if (ob->pose) {
+ if (ob->pose)
ob->pose->flag |= POSE_RECALC;
- }
}
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); // and all its relations
@@ -808,7 +846,7 @@ void paste_posebuf (int flip)
/*
// disabled until protected bones in proxies follow the rules everywhere else!
- if(pose_has_protected_selected(ob, 1))
+ if(pose_has_protected_selected(ob, 1, 1))
return;
*/
@@ -1249,7 +1287,7 @@ void pose_flip_names(void)
if(!ob && !ob->pose) return;
if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
- if(pose_has_protected_selected(ob, 0))
+ if(pose_has_protected_selected(ob, 0, 1))
return;
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
@@ -1282,7 +1320,7 @@ void pose_autoside_names(short axis)
if (ELEM(NULL, ob, ob->pose)) return;
if (ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
- if (pose_has_protected_selected(ob, 0))
+ if (pose_has_protected_selected(ob, 0, 1))
return;
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
@@ -1415,7 +1453,7 @@ void pose_movetolayer(void)
/* pose-channel layers */
bPoseChannel *pchan;
- if (pose_has_protected_selected(ob, 0))
+ if (pose_has_protected_selected(ob, 0, 1))
return;
for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c
index 9426548dc38..7e2ffc3ba63 100644
--- a/source/blender/src/sequence.c
+++ b/source/blender/src/sequence.c
@@ -1473,8 +1473,8 @@ static void input_preprocess(Sequence * seq, TStripElem* se, int cfra)
dy = sy;
if (seq->flag & SEQ_USE_TRANSFORM) {
- dx = seqrectx;
- dy = seqrecty;
+ dx = G.scene->r.xsch;
+ dy = G.scene->r.ysch;
}
if (c.top + c.bottom >= se->ibuf->y ||
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index 92efb477095..b4702788e0c 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -1205,9 +1205,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
return; /* return if event was processed (swallowed) by handler(s) */
}
- if(gpencil_do_paint(sa)) return;
+ if(gpencil_do_paint(sa, L_MOUSE)) return;
if(BIF_do_manipulator(sa)) return;
}
+ else if(event==RIGHTMOUSE) {
+ if(gpencil_do_paint(sa, R_MOUSE)) return;
+ }
/* swap mouse buttons based on user preference */
if (U.flag & USER_LMOUSESELECT) {
@@ -2711,6 +2714,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case DELKEY:
if(G.qual==0 || G.qual==LR_SHIFTKEY)
delete_context_selected();
+ if(G.qual==LR_ALTKEY)
+ gpencil_delete_menu();
break;
case YKEY:
if((G.qual==0) && (G.obedit)) {
@@ -4823,8 +4828,11 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0;
/* grease-pencil defaults to leftmouse */
- if(event==LEFTMOUSE) {
- if(gpencil_do_paint(sa)) return;
+ if (event == LEFTMOUSE) {
+ if(gpencil_do_paint(sa, L_MOUSE)) return;
+ }
+ else if (event == RIGHTMOUSE) {
+ if(gpencil_do_paint(sa, R_MOUSE)) return;
}
/* swap mouse buttons based on user preference */
@@ -5099,6 +5107,10 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if((G.qual==0))
del_seq();
}
+ else if(G.qual==LR_ALTKEY) {
+ if(sseq->mainb)
+ gpencil_delete_menu();
+ }
break;
case PAD1: case PAD2: case PAD4: case PAD8:
seq_viewzoom(event, (G.qual & LR_SHIFTKEY)==0);
@@ -5107,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);
+ }
}
diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c
index 706b079432c..8f83434e528 100644
--- a/source/blender/src/transform_conversions.c
+++ b/source/blender/src/transform_conversions.c
@@ -1089,6 +1089,8 @@ static void createTransArmatureVerts(TransInfo *t)
VECCOPY (td->center, td->iloc);
td->loc= ebo->tail;
td->flag= TD_SELECTED;
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
@@ -1104,6 +1106,8 @@ static void createTransArmatureVerts(TransInfo *t)
VECCOPY (td->center, td->iloc);
td->loc= ebo->head;
td->flag= TD_SELECTED;
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c
index 050360887b4..709879f142b 100644
--- a/source/blender/src/transform_manipulator.c
+++ b/source/blender/src/transform_manipulator.c
@@ -170,6 +170,13 @@ static void stats_pose(View3D *v3d, bPoseChannel *pchan)
}
}
+/* for editmode*/
+static void stats_editbone(View3D *v3d, EditBone *ebo)
+{
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ protectflag_to_drawflags(OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE, &v3d->twdrawflag);
+}
+
/* only counts the parent selection, and tags transform flag */
/* bad call... should re-use method from transform_conversion once */
static void count_bone_select(TransInfo *t, bArmature *arm, ListBase *lb, int do_it)
@@ -258,6 +265,9 @@ int calc_manipulator_stats(ScrArea *sa)
calc_tw_center(ebo->head);
totsel++;
}
+ if (ebo->flag & BONE_SELECTED) {
+ stats_editbone(v3d, ebo);
+ }
}
}
}
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 9589f1e3e94..e17b0f66977 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -618,8 +618,23 @@ int main(int argc, char **argv)
if (G.scene) {
if (a < argc) {
int frame= MIN2(MAXFRAME, MAX2(1, atoi(argv[a])));
+ int slink_flag= 0;
Render *re= RE_NewRender(G.scene->id.name);
+
+ if (G.f & G_DOSCRIPTLINKS) {
+ BPY_do_all_scripts(SCRIPT_RENDER);
+ /* avoid FRAMECHANGED slink event
+ * (should only be triggered in anims): */
+ G.f &= ~G_DOSCRIPTLINKS;
+ slink_flag= 1;
+ }
+
RE_BlenderAnim(re, G.scene, frame, frame);
+
+ if (slink_flag) {
+ G.f |= G_DOSCRIPTLINKS;
+ BPY_do_all_scripts(SCRIPT_POSTRENDER);
+ }
}
} else {
printf("\nError: no blend loaded. cannot use '-f'.\n");
@@ -628,7 +643,14 @@ int main(int argc, char **argv)
case 'a':
if (G.scene) {
Render *re= RE_NewRender(G.scene->id.name);
+
+ if (G.f & G_DOSCRIPTLINKS)
+ BPY_do_all_scripts(SCRIPT_RENDER);
+
RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra);
+
+ if (G.f & G_DOSCRIPTLINKS)
+ BPY_do_all_scripts(SCRIPT_POSTRENDER);
} else {
printf("\nError: no blend loaded. cannot use '-a'.\n");
}
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 <config.h>
-#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_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 1f1ac6da119..f44318120e8 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,16 @@ 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->transp != TF_CLIP)) {
+ material->ras_mode |= ALPHA;
+ material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0;
+ }
// get uv sets
if(validmat)
@@ -711,132 +712,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<MFace*>(mesh->mface);
- MTFace* tface = static_cast<MTFace*>(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<MFace*>(mesh->mface);
- MTFace* tface = static_cast<MTFace*>(mesh->mtface);
+
+ // 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<MTFace*>(dm->getFaceDataArray(dm, CD_MTFACE));
+ MCol *mcol = static_cast<MCol*>(dm->getFaceDataArray(dm, CD_MCOL));
+ float (*tangent)[3] = NULL;
+ int totface = dm->getNumFaces(dm);
const char *tfaceName = "";
- MCol* mmcol = mesh->mcol;
- MT_assert(mface || mesh->totface == 0);
+ 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; lay<MAX_MTFACE; lay++)
- {
+ for (int lay=0; lay<MAX_MTFACE; lay++) {
layers[lay].face = 0;
layers[lay].name = "";
}
-
int validLayers = 0;
- for (int i=0; i<mesh->fdata.totlayer; i++)
+ for (int i=0; i<dm->faceData.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 +767,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;f<mesh->totface;f++,mface++)
+ meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert);
+
+ for (int f=0;f<totface;f++,mface++)
{
-
+ Material* ma = 0;
bool collider = true;
-
- // only add valid polygons
- if (mface->v3)
- {
- 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);
-
- 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;
+ 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];
+
+ if (mface->v4)
+ 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;
-
+ {
+ bool polyvisible = true;
+ RAS_IPolyMaterial* polymat = NULL;
+ BL_Material *bl_mat = NULL;
+
+ if(converter->GetMaterials()) {
+ /* do Blender Multitexture and Blender GLSL materials */
+ unsigned int rgb[4];
+ MT_Point2 uv[4];
+
+ /* first is the BL_Material */
+ bl_mat = ConvertMaterial(ma, tface, tfaceName, mface, mcol,
+ lightlayer, blenderobj, layers, converter->GetGLSLMaterials());
+
+ bl_mat->material_index = (int)mface->mat_nr;
+
+ polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0);
+ collider = ((bl_mat->ras_mode & COLLIDER)!=0);
+
+ /* 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];
+
+ 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];
+
+ /* 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 : "" ) : "";
- {
- Material* ma = 0;
- 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);
-
- 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;
-
- polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0);
- collider = ((bl_mat->ras_mode & COLLIDER)!=0);
+ char transp=0;
+ short mode=0, tile=0;
+ int tilexrep=4,tileyrep = 4;
+
+ if (bima) {
+ tilexrep = bima->xrep;
+ tileyrep = bima->yrep;
+ }
+
+ /* 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;
- polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj );
+ polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE));
- 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->GetConversionUV2(uv);
- uv20 = uv[0]; uv21 = uv[1];
- uv22 = uv[2]; uv23 = uv[3];
-
- if(tangent){
- tan0 = tangent[mface->v1];
- tan1 = tangent[mface->v2];
- tan2 = tangent[mface->v3];
- if (mface->v4)
- tan3 = tangent[mface->v4];
- }
+ uv0 = MT_Point2(tface->uv[0]);
+ uv1 = MT_Point2(tface->uv[1]);
+ uv2 = MT_Point2(tface->uv[2]);
+
+ 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;
}
- else
- {
- ma = give_current_material(blenderobj, 1);
- 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;
+ /* 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]);
- if (bima)
- {
- tilexrep = bima->xrep;
- tileyrep = bima->yrep;
-
- }
+ if (mface->v4)
+ rgb3 = KX_Mcol2uint_new(mcol[3]);
+ }
+ else {
+ /* no vertex colors, take from material, otherwise white */
+ unsigned int color = 0xFFFFFFFFL;
- if (mesh->mtface && tface)
+ if (ma)
{
- // 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));
+ union
+ {
+ unsigned char cp[4];
+ unsigned int integer;
+ } col_converter;
- uv0 = MT_Point2(tface->uv[0]);
- uv1 = MT_Point2(tface->uv[1]);
- uv2 = MT_Point2(tface->uv[2]);
-
- if (mface->v4)
- uv3 = MT_Point2(tface->uv[3]);
- }
- else
- {
- // no texfaces, set COLLSION true and everything else FALSE
+ 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);
- mode = default_face_mode;
- transp = TF_SOLID;
- tile = 0;
+ color = col_converter.integer;
}
- 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;
+ rgb0 = KX_rgbaint2uint_new(color);
+ rgb1 = KX_rgbaint2uint_new(color);
+ rgb2 = KX_rgbaint2uint_new(color);
+
+ if (mface->v4)
+ rgb3 = KX_rgbaint2uint_new(color);
+ }
+
+ bool istriangle = (mface->v4==0);
- 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;
- }
+ // 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);
- rgb0 = KX_rgbaint2uint_new(color);
- rgb1 = KX_rgbaint2uint_new(color);
- rgb2 = KX_rgbaint2uint_new(color);
-
- if (mface->v4)
- rgb3 = KX_rgbaint2uint_new(color);
- }
-
- 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 (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);
+ 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;
+ }
+ }
- } 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);
}
-
- // 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();
+ } 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;
}
-
- int nverts = mface->v4?4:3;
- int vtxarray = meshobj->FindVertexArray(nverts,polymat);
- RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray);
+ 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;
+ 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
+ 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));
+ 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())
+ 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)
{
- 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);
- }
+ 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);
}
+
+// poly->SetVisibleWireframeEdges(mface->edcode);
+ poly->SetCollider(collider);
}
+
if (tface)
tface++;
- if (mmcol)
- mmcol+=4;
+ if (mcol)
+ mcol+=4;
for (int lay=0; lay<MAX_MTFACE; lay++)
{
@@ -1127,11 +1048,10 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
(*mit)->GetPolyMaterial()->OnConstruction();
}
- if(tangent)
- delete [] tangent;
-
if (layers)
delete []layers;
+
+ dm->release(dm);
return meshobj;
}
@@ -1819,7 +1739,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,
@@ -1937,7 +1857,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
if (converter->addInitFromFrame)
if (!isInActiveLayer)
addobj=false;
-
+
if (gameobj&&addobj)
{
MT_Point3 posPrev;
@@ -1989,10 +1909,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->NodeUpdateGS(0,true);
BL_ConvertIpos(blenderobject,gameobj,converter);
- // TODO: expand to multiple ipos per mesh
- Material *mat = give_current_material(blenderobject, 1);
- if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter);
-
+ BL_ConvertMaterialIpos(blenderobject, gameobj, converter);
+
sumolist->Add(gameobj->AddRef());
BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer);
@@ -2029,8 +1947,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
// needed for python scripting
logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj);
- // needed for dynamic object morphing
- logicmgr->RegisterGameObj(gameobj, blenderobject);
+ // needed for group duplication
+ logicmgr->RegisterGameObj(blenderobject, gameobj);
for (int i = 0; i < gameobj->GetMeshCount(); i++)
logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject);
@@ -2052,8 +1970,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->NodeUpdateGS(0,true);
gameobj->Bucketize();
- if (gameobj->IsDupliGroup())
- grouplist.insert(blenderobject->dup_group);
}
else
{
@@ -2061,6 +1977,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
//at the end of this function if it is not a root object
inactivelist->Add(gameobj->AddRef());
}
+ if (gameobj->IsDupliGroup())
+ grouplist.insert(blenderobject->dup_group);
if (converter->addInitFromFrame){
gameobj->NodeSetLocalPosition(posPrev);
gameobj->NodeSetLocalOrientation(angor);
@@ -2111,7 +2029,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
blenderscene);
// this code is copied from above except that
- // object from groups are never is active layer
+ // object from groups are never in active layer
bool isInActiveLayer = false;
bool addobj=true;
@@ -2171,9 +2089,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->NodeUpdateGS(0,true);
BL_ConvertIpos(blenderobject,gameobj,converter);
- // TODO: expand to multiple ipos per mesh
- Material *mat = give_current_material(blenderobject, 1);
- if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter);
+ BL_ConvertMaterialIpos(blenderobject,gameobj, converter);
sumolist->Add(gameobj->AddRef());
@@ -2211,8 +2127,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
// needed for python scripting
logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj);
- // needed for dynamic object morphing
- logicmgr->RegisterGameObj(gameobj, blenderobject);
+ // needed for group duplication
+ logicmgr->RegisterGameObj(blenderobject, gameobj);
for (int i = 0; i < gameobj->GetMeshCount(); i++)
logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject);
@@ -2262,7 +2178,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)
@@ -2524,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);
+ // set the init state to all objects
+ gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state);
}
- // apply the initial state to controllers
- for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
+ // apply the initial state to controllers, only on the active objects as this registers the sensors
+ for ( i=0;i<objectlist->GetCount();i++)
{
- KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i));
- struct Object* blenderobj = converter->FindBlenderObject(gameobj);
- gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state);
+ KX_GameObject* gameobj = static_cast<KX_GameObject*>(objectlist->GetValue(i));
gameobj->ResetState();
}
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
index 7196b393ed4..242d648b062 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
@@ -442,15 +442,15 @@ PyMethodDef BL_ShapeActionActuator::Methods[] = {
{"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
{"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc},
- {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_VARARGS, GetAction_doc},
- {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_VARARGS, GetStart_doc},
- {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_VARARGS, GetEnd_doc},
- {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_VARARGS, GetBlendin_doc},
- {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_VARARGS, GetPriority_doc},
- {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_VARARGS, GetFrame_doc},
- {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
- {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_VARARGS, GetType_doc},
- {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_VARARGS, SetType_doc},
+ {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_NOARGS, GetAction_doc},
+ {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_NOARGS, GetStart_doc},
+ {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_NOARGS, GetEnd_doc},
+ {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_NOARGS, GetBlendin_doc},
+ {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_NOARGS, GetPriority_doc},
+ {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_NOARGS, GetFrame_doc},
+ {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc},
+ {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_NOARGS, GetType_doc},
+ {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_NOARGS, SetType_doc},
{NULL,NULL} //Sentinel
};
@@ -463,9 +463,7 @@ char BL_ShapeActionActuator::GetAction_doc[] =
"getAction()\n"
"\tReturns a string containing the name of the current action.\n";
-PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self) {
PyObject *result;
if (m_action){
@@ -484,9 +482,7 @@ char BL_ShapeActionActuator::GetProperty_doc[] =
"getProperty()\n"
"\tReturns the name of the property to be used in FromProp mode.\n";
-PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self) {
PyObject *result;
result = Py_BuildValue("s", (const char *)m_propname);
@@ -499,9 +495,7 @@ char BL_ShapeActionActuator::GetFrame_doc[] =
"getFrame()\n"
"\tReturns the current frame number.\n";
-PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self) {
PyObject *result;
result = Py_BuildValue("f", m_localtime);
@@ -514,9 +508,7 @@ char BL_ShapeActionActuator::GetEnd_doc[] =
"getEnd()\n"
"\tReturns the last frame of the action.\n";
-PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self) {
PyObject *result;
result = Py_BuildValue("f", m_endframe);
@@ -529,9 +521,7 @@ char BL_ShapeActionActuator::GetStart_doc[] =
"getStart()\n"
"\tReturns the starting frame of the action.\n";
-PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self) {
PyObject *result;
result = Py_BuildValue("f", m_startframe);
@@ -545,9 +535,7 @@ char BL_ShapeActionActuator::GetBlendin_doc[] =
"\tReturns the number of interpolation animation frames to be\n"
"\tgenerated when this actuator is triggered.\n";
-PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self) {
PyObject *result;
result = Py_BuildValue("f", m_blendin);
@@ -561,9 +549,7 @@ char BL_ShapeActionActuator::GetPriority_doc[] =
"\tReturns the priority for this actuator. Actuators with lower\n"
"\tPriority numbers will override actuators with higher numbers.\n";
-PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self) {
PyObject *result;
result = Py_BuildValue("i", m_priority);
@@ -605,6 +591,7 @@ PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self,
}
}
else {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -627,6 +614,7 @@ PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self,
m_startframe = start;
}
else {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -649,6 +637,7 @@ PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self,
m_endframe = end;
}
else {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -672,6 +661,7 @@ PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self,
m_blendin = blendin;
}
else {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -700,6 +690,7 @@ PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self,
m_blendframe = m_blendin;
}
else {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -724,6 +715,7 @@ PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self,
m_priority = priority;
}
else {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -750,6 +742,7 @@ PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self,
m_localtime=m_endframe;
}
else {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -773,6 +766,7 @@ PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self,
m_propname = string;
}
else {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -784,9 +778,7 @@ PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self,
char BL_ShapeActionActuator::GetType_doc[] =
"getType()\n"
"\tReturns the operation mode of the actuator.\n";
-PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) {
return Py_BuildValue("h", m_playtype);
}
@@ -801,6 +793,7 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* self,
short typeArg;
if (!PyArg_ParseTuple(args, "h", &typeArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h
index 434a62a1233..a9b9ad8fa86 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.h
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.h
@@ -87,15 +87,15 @@ public:
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendtime);
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetChannel);
- KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetAction);
- KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetBlendin);
- KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetPriority);
- KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetStart);
- KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetEnd);
- KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetFrame);
- KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetProperty);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetAction);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetBlendin);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetPriority);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetStart);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetEnd);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetFrame);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetProperty);
// KX_PYMETHOD(BL_ActionActuator,GetChannel);
- KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetType);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType);
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType);
virtual PyObject* _getattr(const STR_String& attr);
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 8739fb109fd..53ac730d203 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -628,6 +628,8 @@ void BL_ConvertActuators(char* maggiename,
/* convert settings... degrees in the ui become radians */
/* internally */
if (conact->type == ACT_CONST_TYPE_ORI) {
+ min = (MT_2_PI * conact->minloc[0])/360.0;
+ max = (MT_2_PI * conact->maxloc[0])/360.0;
switch (conact->mode) {
case ACT_CONST_DIRPX:
locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX;
@@ -656,18 +658,18 @@ void BL_ConvertActuators(char* maggiename,
min = conact->minloc[2];
max = conact->maxloc[2];
break;
- case ACT_CONST_DIRMX:
- locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMX;
+ case ACT_CONST_DIRNX:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNX;
min = conact->minloc[0];
max = conact->maxloc[0];
break;
- case ACT_CONST_DIRMY:
- locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMY;
+ case ACT_CONST_DIRNY:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNY;
min = conact->minloc[1];
max = conact->maxloc[1];
break;
- case ACT_CONST_DIRMZ:
- locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMZ;
+ case ACT_CONST_DIRNZ:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNZ;
min = conact->minloc[2];
max = conact->maxloc[2];
break;
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;i<sens->totlinks;i++)
diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp
index 75ca59d01e7..7410beecaf4 100644
--- a/source/gameengine/Converter/KX_IpoConvert.cpp
+++ b/source/gameengine/Converter/KX_IpoConvert.cpp
@@ -36,6 +36,7 @@
#pragma warning (disable:4786)
#endif
+#include "BKE_material.h" /* give_current_material */
#include "KX_GameObject.h"
#include "KX_IpoConvert.h"
@@ -68,6 +69,8 @@
#include "SG_Node.h"
+#include "STR_HashedString.h"
+
static BL_InterpolatorList *GetIpoList(struct Ipo *for_ipo, KX_BlenderSceneConverter *converter) {
BL_InterpolatorList *ipoList= converter->FindInterpolatorList(for_ipo);
@@ -560,16 +563,15 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co
}
}
-
-void BL_ConvertMaterialIpos(
- Material* blendermaterial,
+static void ConvertMaterialIpos(
+ Material* blendermaterial,
+ dword matname_hash,
KX_GameObject* gameobj,
KX_BlenderSceneConverter *converter
)
{
if (blendermaterial->ipo) {
-
- KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController();
+ KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
@@ -596,7 +598,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_COL_R);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -610,7 +612,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_COL_G);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -624,7 +626,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_COL_B);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -638,7 +640,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_ALPHA);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -653,7 +655,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_SPEC_R );
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -667,7 +669,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_SPEC_G);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -681,7 +683,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_SPEC_B);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -696,7 +698,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_HARD);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -710,7 +712,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_SPEC);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -725,7 +727,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_REF);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -739,7 +741,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_EMIT);
if (ipo) {
if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController();
+ ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@@ -752,3 +754,28 @@ void BL_ConvertMaterialIpos(
}
}
+void BL_ConvertMaterialIpos(
+ struct Object* blenderobject,
+ KX_GameObject* gameobj,
+ KX_BlenderSceneConverter *converter
+ )
+{
+ if (blenderobject->totcol==1)
+ {
+ Material *mat = give_current_material(blenderobject, 1);
+ // if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL
+ // --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor
+ // because this yields a better performance as not all the vertex colors need to be edited
+ if(mat) ConvertMaterialIpos(mat, NULL, gameobj, converter);
+ }
+ else
+ {
+ for (int material_index=1; material_index <= blenderobject->totcol; material_index++)
+ {
+ Material *mat = give_current_material(blenderobject, material_index);
+ STR_HashedString matname = mat->id.name;
+ if(mat) ConvertMaterialIpos(mat, matname.hash(), gameobj, converter);
+ }
+ }
+}
+
diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h
index afcb1b22821..4ec9bd31062 100644
--- a/source/gameengine/Converter/KX_IpoConvert.h
+++ b/source/gameengine/Converter/KX_IpoConvert.h
@@ -46,7 +46,7 @@ void BL_ConvertCameraIpos(struct Camera* blendercamera,
class KX_GameObject* cameraobj,
class KX_BlenderSceneConverter *converter);
-void BL_ConvertMaterialIpos(struct Material* blendermaterial,
+void BL_ConvertMaterialIpos(struct Object* blenderobject,
class KX_GameObject* materialobj,
class KX_BlenderSceneConverter *converter);
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<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++)
+ for (set<SCA_ISensor*>::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<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++)
+ for (set<SCA_ISensor*>::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_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
index e1c8ef87dd1..099cb8eebd0 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
@@ -149,7 +149,7 @@ PyParentObject SCA_ActuatorSensor::Parents[] = {
};
PyMethodDef SCA_ActuatorSensor::Methods[] = {
- {"getActuator", (PyCFunction) SCA_ActuatorSensor::sPyGetActuator, METH_VARARGS, GetActuator_doc},
+ {"getActuator", (PyCFunction) SCA_ActuatorSensor::sPyGetActuator, METH_NOARGS, GetActuator_doc},
{"setActuator", (PyCFunction) SCA_ActuatorSensor::sPySetActuator, METH_VARARGS, SetActuator_doc},
{NULL,NULL} //Sentinel
};
@@ -162,7 +162,7 @@ PyObject* SCA_ActuatorSensor::_getattr(const STR_String& attr) {
char SCA_ActuatorSensor::GetActuator_doc[] =
"getActuator()\n"
"\tReturn the Actuator with which the sensor operates.\n";
-PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self)
{
return PyString_FromString(m_checkactname);
}
@@ -180,6 +180,7 @@ PyObject* SCA_ActuatorSensor::PySetActuator(PyObject* self, PyObject* args, PyOb
char *actNameArg = NULL;
if (!PyArg_ParseTuple(args, "s", &actNameArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h
index 6086c5bfce0..a71145f6852 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h
+++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h
@@ -66,7 +66,7 @@ public:
/* 3. setProperty */
KX_PYMETHOD_DOC(SCA_ActuatorSensor,SetActuator);
/* 4. getProperty */
- KX_PYMETHOD_DOC(SCA_ActuatorSensor,GetActuator);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ActuatorSensor,GetActuator);
};
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<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+ for (set<class SCA_ISensor*>::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<SCA_ISensor*>::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 <vector>
+#include <set>
#include <algorithm>
class SCA_EventManager
{
protected:
- std::vector <class SCA_ISensor*> m_sensors;
+ // use a set to speed-up insertion/removal
+ std::set <class SCA_ISensor*> 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)
+ {
+ // 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)
{
- (*contit)->ApplyState(m_state);
+ 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 68341b57435..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();
}
}
@@ -168,23 +170,23 @@ PyMethodDef SCA_ISensor::Methods[] = {
{"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive,
METH_VARARGS, IsPositive_doc},
{"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode,
- METH_VARARGS, GetUsePosPulseMode_doc},
+ METH_NOARGS, GetUsePosPulseMode_doc},
{"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode,
METH_VARARGS, SetUsePosPulseMode_doc},
{"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency,
- METH_VARARGS, GetFrequency_doc},
+ METH_NOARGS, GetFrequency_doc},
{"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency,
METH_VARARGS, SetFrequency_doc},
{"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode,
- METH_VARARGS, GetUseNegPulseMode_doc},
+ METH_NOARGS, GetUseNegPulseMode_doc},
{"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode,
METH_VARARGS, SetUseNegPulseMode_doc},
{"getInvert", (PyCFunction) SCA_ISensor::sPyGetInvert,
- METH_VARARGS, GetInvert_doc},
+ METH_NOARGS, GetInvert_doc},
{"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert,
METH_VARARGS, SetInvert_doc},
{"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel,
- METH_VARARGS, GetLevel_doc},
+ METH_NOARGS, GetLevel_doc},
{"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel,
METH_VARARGS, SetLevel_doc},
{NULL,NULL} //Sentinel
@@ -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)
{
@@ -259,7 +266,7 @@ PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kw
char SCA_ISensor::GetUsePosPulseMode_doc[] =
"getUsePosPulseMode()\n"
"\tReturns whether positive pulse mode is active.\n";
-PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self)
{
return BoolToPyArg(m_pos_pulsemode);
}
@@ -286,7 +293,7 @@ PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyOb
char SCA_ISensor::GetFrequency_doc[] =
"getFrequency()\n"
"\tReturns the frequency of the updates in pulse mode.\n" ;
-PyObject* SCA_ISensor::PyGetFrequency(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PyGetFrequency(PyObject* self)
{
return PyInt_FromLong(m_pulse_frequency);
}
@@ -321,7 +328,7 @@ PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject*
char SCA_ISensor::GetInvert_doc[] =
"getInvert()\n"
"\tReturns whether or not pulses from this sensor are inverted.\n" ;
-PyObject* SCA_ISensor::PyGetInvert(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PyGetInvert(PyObject* self)
{
return BoolToPyArg(m_invert);
}
@@ -342,11 +349,10 @@ char SCA_ISensor::GetLevel_doc[] =
"getLevel()\n"
"\tReturns whether this sensor is a level detector or a edge detector.\n"
"\tIt makes a difference only in case of logic state transition (state actuator).\n"
-"\tA level detector will immediately generate a pulse if the condition for the\n"
-"\tdetector is met when entering the state. A edge detector will wait for an off-on\n"
-"\ttransition to occur.\n"
-"\tOnly some sensors implement this feature: keyboard.\n";
-PyObject* SCA_ISensor::PyGetLevel(PyObject* self, PyObject* args, PyObject* kwds)
+"\tA level detector will immediately generate a pulse, negative or positive\n"
+"\tdepending on the sensor condition, as soon as the state is activated.\n"
+"\tA edge detector will wait for a state change before generating a pulse.\n";
+PyObject* SCA_ISensor::PyGetLevel(PyObject* self)
{
return BoolToPyArg(m_level);
}
@@ -366,7 +372,7 @@ PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds
char SCA_ISensor::GetUseNegPulseMode_doc[] =
"getUseNegPulseMode()\n"
"\tReturns whether negative pulse mode is active.\n";
-PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self)
{
return BoolToPyArg(m_neg_pulsemode);
}
diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h
index 4ce49e71507..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,22 +131,22 @@ public:
void ClrLink()
{ m_links = 0; }
void IncLink()
- { m_links++; }
+ { if (!m_links++) RegisterToManager(); }
void DecLink();
bool IsNoLink() const
{ return !m_links; }
/* Python functions: */
KX_PYMETHOD_DOC(SCA_ISensor,IsPositive);
- KX_PYMETHOD_DOC(SCA_ISensor,GetUsePosPulseMode);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode);
KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode);
- KX_PYMETHOD_DOC(SCA_ISensor,GetFrequency);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency);
KX_PYMETHOD_DOC(SCA_ISensor,SetFrequency);
- KX_PYMETHOD_DOC(SCA_ISensor,GetUseNegPulseMode);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUseNegPulseMode);
KX_PYMETHOD_DOC(SCA_ISensor,SetUseNegPulseMode);
- KX_PYMETHOD_DOC(SCA_ISensor,GetInvert);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetInvert);
KX_PYMETHOD_DOC(SCA_ISensor,SetInvert);
- KX_PYMETHOD_DOC(SCA_ISensor,GetLevel);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetLevel);
KX_PYMETHOD_DOC(SCA_ISensor,SetLevel);
};
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<SCA_ISensor*>::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<m_sensors.size();i++)
+ set<SCA_ISensor*>::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 f50161cbecb..91e66aea359 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.cpp
+++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp
@@ -127,12 +127,17 @@ void SCA_LogicManager::RegisterGameMeshName(const STR_String& gamemeshname, void
-void SCA_LogicManager::RegisterGameObj(CValue* gameobj, void* blendobj)
+void SCA_LogicManager::RegisterGameObj(void* blendobj, CValue* gameobj)
{
- m_map_gameobj_to_blendobj.insert(CHashedPtr(gameobj), blendobj);
+ m_map_blendobj_to_gameobj.insert(CHashedPtr(blendobj), gameobj);
}
-
+void SCA_LogicManager::UnregisterGameObj(void* blendobj, CValue* gameobj)
+{
+ void **obp = m_map_blendobj_to_gameobj[CHashedPtr(blendobj)];
+ if (obp && (CValue*)(*obp) == gameobj)
+ m_map_blendobj_to_gameobj.remove(CHashedPtr(blendobj));
+}
CValue* SCA_LogicManager::GetGameObjectByName(const STR_String& gameobjname)
{
@@ -146,10 +151,10 @@ CValue* SCA_LogicManager::GetGameObjectByName(const STR_String& gameobjname)
}
-void* SCA_LogicManager::FindBlendObjByGameObj(CValue* gameobject)
+CValue* SCA_LogicManager::FindGameObjByBlendObj(void* blendobj)
{
- void **obp= m_map_gameobj_to_blendobj[CHashedPtr(gameobject)];
- return obp?*obp:NULL;
+ void **obp= m_map_blendobj_to_gameobj[CHashedPtr(blendobj)];
+ return obp?(CValue*)(*obp):NULL;
}
@@ -171,12 +176,7 @@ void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor)
(*c)->UnlinkSensor(sensor);
}
m_sensorcontrollermapje.erase(sensor);
-
- for (vector<SCA_EventManager*>::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_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h
index 39d8b865977..e0d3d506702 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.h
+++ b/source/gameengine/GameLogic/SCA_LogicManager.h
@@ -109,7 +109,7 @@ class SCA_LogicManager
GEN_Map<STR_HashedString,void*> m_mapStringToActions;
GEN_Map<STR_HashedString,void*> m_map_gamemeshname_to_blendobj;
- GEN_Map<CHashedPtr,void*> m_map_gameobj_to_blendobj;
+ GEN_Map<CHashedPtr,void*> m_map_blendobj_to_gameobj;
vector<SmartActuatorPtr> m_removedActuators;
public:
@@ -152,8 +152,9 @@ public:
void RegisterGameMeshName(const STR_String& gamemeshname, void* blendobj);
void* FindBlendObjByGameMeshName(const STR_String& gamemeshname);
- void RegisterGameObj(CValue* gameobj, void* blendobj);
- void* FindBlendObjByGameObj(CValue* gameobj);
+ void RegisterGameObj(void* blendobj, CValue* gameobj);
+ void UnregisterGameObj(void* blendobj, CValue* gameobj);
+ CValue* FindGameObjByBlendObj(void* blendobj);
};
#endif //__KX_LOGICMANAGER
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<SCA_ISensor*>::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<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++)
+ for (set<SCA_ISensor*>::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<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+ for (set<class SCA_ISensor*>::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/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;
+
+ for (sce= (Scene*)G.main->scene.first; sce; sce= (Scene*)sce->id.next)
+ if (scenename == (sce->id.name+2))
+ return sce;
-const bool BL_BlenderShader::Ok()const
+ 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];
+
+ VerifyShader();
- if(!mGPUMat || !mBound)
+ 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; i<MAXTEX; i++) {
if(GLEW_ARB_multitexture)
glActiveTextureARB(GL_TEXTURE0_ARB+i);
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<class SCA_ISensor*>::iterator it;
+ set<class SCA_ISensor*>::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_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 0f445a9f32e..a67e5b26667 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -38,6 +38,7 @@ extern "C" {
// ------------------------------------
#define spit(x) std::cout << x << std::endl;
+BL_Shader *KX_BlenderMaterial::mLastShader = NULL;
BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL;
//static PyObject *gTextureDict = 0;
@@ -58,7 +59,8 @@ KX_BlenderMaterial::KX_BlenderMaterial(
data->tilexrep[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<KX_BlenderMaterial*>(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<KX_BlenderMaterial*>(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_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
index c7b2a671f78..539eaec4a7b 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
@@ -135,7 +135,7 @@ void KX_BulletPhysicsController::getOrientation(MT_Quaternion& orn)
}
void KX_BulletPhysicsController::setOrientation(const MT_Matrix3x3& orn)
{
- btMatrix3x3 btmat(orn[0][0], orn[0][1], orn[1][2], orn[1][0], orn[1][1], orn[1][2], orn[2][0], orn[2][1], orn[2][2]);
+ btMatrix3x3 btmat(orn[0][0], orn[0][1], orn[0][2], orn[1][0], orn[1][1], orn[1][2], orn[2][0], orn[2][1], orn[2][2]);
CcdPhysicsController::setWorldOrientation(btmat);
}
void KX_BulletPhysicsController::setPosition(const MT_Point3& pos)
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
index e0b2efb3a25..2401d69d3a3 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -88,11 +88,17 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj,
} else {
m_refDirection /= len;
}
+ m_minimumBound = cos(minBound);
+ m_maximumBound = cos(maxBound);
+ m_minimumSine = sin(minBound);
+ m_maximumSine = sin(maxBound);
}
break;
default:
m_minimumBound = minBound;
m_maximumBound = maxBound;
+ m_minimumSine = 0.f;
+ m_maximumSine = 0.f;
break;
}
@@ -153,9 +159,9 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
KX_GameObject *obj = (KX_GameObject*) GetParent();
MT_Point3 position = obj->NodeGetWorldPosition();
MT_Point3 newposition;
- MT_Vector3 direction;
+ MT_Vector3 direction, refDirection;
MT_Matrix3x3 rotation = obj->NodeGetWorldOrientation();
- MT_Scalar filter, newdistance;
+ MT_Scalar filter, newdistance, cosangle;
int axis, sign;
if (m_posDampTime) {
@@ -185,11 +191,45 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
axis = 2;
break;
}
+ if ((m_maximumBound < (1.0f-FLT_EPSILON)) || (m_minimumBound < (1.0f-FLT_EPSILON))) {
+ // reference direction needs to be evaluated
+ // 1. get the cosine between current direction and target
+ cosangle = direction.dot(m_refDirection);
+ if (cosangle >= (m_maximumBound-FLT_EPSILON) && cosangle <= (m_minimumBound+FLT_EPSILON)) {
+ // no change to do
+ result = true;
+ goto CHECK_TIME;
+ }
+ // 2. define a new reference direction
+ // compute local axis with reference direction as X and
+ // Y in direction X refDirection plane
+ MT_Vector3 zaxis = m_refDirection.cross(direction);
+ if (MT_fuzzyZero2(zaxis.length2())) {
+ // direction and refDirection are identical,
+ // choose any other direction to define plane
+ if (direction[0] < 0.9999)
+ zaxis = m_refDirection.cross(MT_Vector3(1.0,0.0,0.0));
+ else
+ zaxis = m_refDirection.cross(MT_Vector3(0.0,1.0,0.0));
+ }
+ MT_Vector3 yaxis = zaxis.cross(m_refDirection);
+ yaxis.normalize();
+ if (cosangle > m_minimumBound) {
+ // angle is too close to reference direction,
+ // choose a new reference that is exactly at minimum angle
+ refDirection = m_minimumBound * m_refDirection + m_minimumSine * yaxis;
+ } else {
+ // angle is too large, choose new reference direction at maximum angle
+ refDirection = m_maximumBound * m_refDirection + m_maximumSine * yaxis;
+ }
+ } else {
+ refDirection = m_refDirection;
+ }
if (m_posDampTime) {
// apply damping on the direction
- direction = filter*direction + (1.0-filter)*m_refDirection;
+ direction = filter*direction + (1.0-filter)*refDirection;
} else {
- direction = m_refDirection;
+ direction = refDirection;
}
obj->AlignAxisToVect(direction, axis);
result = true;
@@ -197,9 +237,9 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
case KX_ACT_CONSTRAINT_DIRPX:
case KX_ACT_CONSTRAINT_DIRPY:
case KX_ACT_CONSTRAINT_DIRPZ:
- case KX_ACT_CONSTRAINT_DIRMX:
- case KX_ACT_CONSTRAINT_DIRMY:
- case KX_ACT_CONSTRAINT_DIRMZ:
+ case KX_ACT_CONSTRAINT_DIRNX:
+ case KX_ACT_CONSTRAINT_DIRNY:
+ case KX_ACT_CONSTRAINT_DIRNZ:
switch (m_locrot) {
case KX_ACT_CONSTRAINT_DIRPX:
direction[0] = rotation[0][0];
@@ -222,21 +262,21 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
axis = 2;
sign = 1;
break;
- case KX_ACT_CONSTRAINT_DIRMX:
+ case KX_ACT_CONSTRAINT_DIRNX:
direction[0] = -rotation[0][0];
direction[1] = -rotation[1][0];
direction[2] = -rotation[2][0];
axis = 0;
sign = 0;
break;
- case KX_ACT_CONSTRAINT_DIRMY:
+ case KX_ACT_CONSTRAINT_DIRNY:
direction[0] = -rotation[0][1];
direction[1] = -rotation[1][1];
direction[2] = -rotation[2][1];
axis = 1;
sign = 0;
break;
- case KX_ACT_CONSTRAINT_DIRMZ:
+ case KX_ACT_CONSTRAINT_DIRNZ:
direction[0] = -rotation[0][2];
direction[1] = -rotation[1][2];
direction[2] = -rotation[2][2];
@@ -397,27 +437,27 @@ PyParentObject KX_ConstraintActuator::Parents[] = {
PyMethodDef KX_ConstraintActuator::Methods[] = {
{"setDamp", (PyCFunction) KX_ConstraintActuator::sPySetDamp, METH_VARARGS, SetDamp_doc},
- {"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_VARARGS, GetDamp_doc},
+ {"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_NOARGS, GetDamp_doc},
{"setRotDamp", (PyCFunction) KX_ConstraintActuator::sPySetRotDamp, METH_VARARGS, SetRotDamp_doc},
- {"getRotDamp", (PyCFunction) KX_ConstraintActuator::sPyGetRotDamp, METH_VARARGS, GetRotDamp_doc},
+ {"getRotDamp", (PyCFunction) KX_ConstraintActuator::sPyGetRotDamp, METH_NOARGS, GetRotDamp_doc},
{"setDirection", (PyCFunction) KX_ConstraintActuator::sPySetDirection, METH_VARARGS, SetDirection_doc},
- {"getDirection", (PyCFunction) KX_ConstraintActuator::sPyGetDirection, METH_VARARGS, GetDirection_doc},
+ {"getDirection", (PyCFunction) KX_ConstraintActuator::sPyGetDirection, METH_NOARGS, GetDirection_doc},
{"setOption", (PyCFunction) KX_ConstraintActuator::sPySetOption, METH_VARARGS, SetOption_doc},
- {"getOption", (PyCFunction) KX_ConstraintActuator::sPyGetOption, METH_VARARGS, GetOption_doc},
+ {"getOption", (PyCFunction) KX_ConstraintActuator::sPyGetOption, METH_NOARGS, GetOption_doc},
{"setTime", (PyCFunction) KX_ConstraintActuator::sPySetTime, METH_VARARGS, SetTime_doc},
- {"getTime", (PyCFunction) KX_ConstraintActuator::sPyGetTime, METH_VARARGS, GetTime_doc},
+ {"getTime", (PyCFunction) KX_ConstraintActuator::sPyGetTime, METH_NOARGS, GetTime_doc},
{"setProperty", (PyCFunction) KX_ConstraintActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
- {"getProperty", (PyCFunction) KX_ConstraintActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
+ {"getProperty", (PyCFunction) KX_ConstraintActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc},
{"setMin", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, SetMin_doc},
- {"getMin", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_VARARGS, GetMin_doc},
+ {"getMin", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_NOARGS, GetMin_doc},
{"setDistance", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, SetDistance_doc},
- {"getDistance", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_VARARGS, GetDistance_doc},
+ {"getDistance", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_NOARGS, GetDistance_doc},
{"setMax", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, SetMax_doc},
- {"getMax", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_VARARGS, GetMax_doc},
+ {"getMax", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, GetMax_doc},
{"setRayLength", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, SetRayLength_doc},
- {"getRayLength", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_VARARGS, GetRayLength_doc},
+ {"getRayLength", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, GetRayLength_doc},
{"setLimit", (PyCFunction) KX_ConstraintActuator::sPySetLimit, METH_VARARGS, SetLimit_doc},
- {"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_VARARGS, GetLimit_doc},
+ {"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_NOARGS, GetLimit_doc},
{NULL,NULL} //Sentinel
};
@@ -436,6 +476,7 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self,
PyObject* kwds) {
int dampArg;
if(!PyArg_ParseTuple(args, "i", &dampArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -448,9 +489,7 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self,
char KX_ConstraintActuator::GetDamp_doc[] =
"getDamp()\n"
"\tReturns the damping parameter.\n";
-PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self,
- PyObject* args,
- PyObject* kwds){
+PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self){
return PyInt_FromLong(m_posDampTime);
}
@@ -465,6 +504,7 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self,
PyObject* kwds) {
int dampArg;
if(!PyArg_ParseTuple(args, "i", &dampArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -477,9 +517,7 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self,
char KX_ConstraintActuator::GetRotDamp_doc[] =
"getRotDamp()\n"
"\tReturns the damping time for application of the constraint.\n";
-PyObject* KX_ConstraintActuator::PyGetRotDamp(PyObject* self,
- PyObject* args,
- PyObject* kwds){
+PyObject* KX_ConstraintActuator::PyGetRotDamp(PyObject* self){
return PyInt_FromLong(m_rotDampTime);
}
@@ -496,6 +534,7 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self,
MT_Vector3 dir;
if(!PyArg_ParseTuple(args, "(fff)", &x, &y, &z)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
dir[0] = x;
@@ -514,9 +553,7 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self,
char KX_ConstraintActuator::GetDirection_doc[] =
"getDirection()\n"
"\tReturns the reference direction of the orientation constraint as a 3-tuple.\n";
-PyObject* KX_ConstraintActuator::PyGetDirection(PyObject* self,
- PyObject* args,
- PyObject* kwds){
+PyObject* KX_ConstraintActuator::PyGetDirection(PyObject* self){
PyObject *retVal = PyList_New(3);
PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_refDirection[0]));
@@ -540,6 +577,7 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self,
PyObject* kwds) {
int option;
if(!PyArg_ParseTuple(args, "i", &option)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -551,9 +589,7 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self,
char KX_ConstraintActuator::GetOption_doc[] =
"getOption()\n"
"\tReturns the option parameter.\n";
-PyObject* KX_ConstraintActuator::PyGetOption(PyObject* self,
- PyObject* args,
- PyObject* kwds){
+PyObject* KX_ConstraintActuator::PyGetOption(PyObject* self){
return PyInt_FromLong(m_option);
}
@@ -569,6 +605,7 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self,
PyObject* kwds) {
int t;
if(!PyArg_ParseTuple(args, "i", &t)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -582,9 +619,7 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self,
char KX_ConstraintActuator::GetTime_doc[] =
"getTime()\n"
"\tReturns the time parameter.\n";
-PyObject* KX_ConstraintActuator::PyGetTime(PyObject* self,
- PyObject* args,
- PyObject* kwds){
+PyObject* KX_ConstraintActuator::PyGetTime(PyObject* self){
return PyInt_FromLong(m_activeTime);
}
@@ -599,6 +634,7 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self,
PyObject* kwds) {
char *property;
if (!PyArg_ParseTuple(args, "s", &property)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
if (property == NULL) {
@@ -614,9 +650,7 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self,
char KX_ConstraintActuator::GetProperty_doc[] =
"getProperty()\n"
"\tReturns the property parameter.\n";
-PyObject* KX_ConstraintActuator::PyGetProperty(PyObject* self,
- PyObject* args,
- PyObject* kwds){
+PyObject* KX_ConstraintActuator::PyGetProperty(PyObject* self){
return PyString_FromString(m_property);
}
@@ -636,6 +670,7 @@ PyObject* KX_ConstraintActuator::PySetMin(PyObject* self,
PyObject* kwds) {
float minArg;
if(!PyArg_ParseTuple(args, "f", &minArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -661,9 +696,7 @@ char KX_ConstraintActuator::GetMin_doc[] =
"getMin()\n"
"\tReturns the lower value of the interval to which the value\n"
"\tis clipped.\n";
-PyObject* KX_ConstraintActuator::PyGetMin(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PyGetMin(PyObject* self) {
return PyFloat_FromDouble(m_minimumBound);
}
@@ -683,6 +716,7 @@ PyObject* KX_ConstraintActuator::PySetMax(PyObject* self,
PyObject* kwds){
float maxArg;
if(!PyArg_ParseTuple(args, "f", &maxArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -708,9 +742,7 @@ char KX_ConstraintActuator::GetMax_doc[] =
"getMax()\n"
"\tReturns the upper value of the interval to which the value\n"
"\tis clipped.\n";
-PyObject* KX_ConstraintActuator::PyGetMax(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PyGetMax(PyObject* self) {
return PyFloat_FromDouble(m_maximumBound);
}
@@ -738,6 +770,7 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self,
PyObject* kwds) {
int locrotArg;
if(!PyArg_ParseTuple(args, "i", &locrotArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -749,9 +782,7 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self,
char KX_ConstraintActuator::GetLimit_doc[] =
"getLimit()\n"
"\tReturns the type of constraint.\n";
-PyObject* KX_ConstraintActuator::PyGetLimit(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_ConstraintActuator::PyGetLimit(PyObject* self) {
return PyInt_FromLong(m_locrot);
}
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h
index 5a1d4d23217..d9f39124cac 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.h
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h
@@ -48,6 +48,10 @@ protected:
float m_minimumBound;
// max (float)
float m_maximumBound;
+ // sinus of minimum angle
+ float m_minimumSine;
+ // sinus of maximum angle
+ float m_maximumSine;
// reference direction
MT_Vector3 m_refDirection;
// locrotxyz choice (pick one): only one choice allowed at a time!
@@ -80,9 +84,9 @@ protected:
KX_ACT_CONSTRAINT_DIRPX,
KX_ACT_CONSTRAINT_DIRPY,
KX_ACT_CONSTRAINT_DIRPZ,
- KX_ACT_CONSTRAINT_DIRMX,
- KX_ACT_CONSTRAINT_DIRMY,
- KX_ACT_CONSTRAINT_DIRMZ,
+ KX_ACT_CONSTRAINT_DIRNX,
+ KX_ACT_CONSTRAINT_DIRNY,
+ KX_ACT_CONSTRAINT_DIRNZ,
KX_ACT_CONSTRAINT_ORIX,
KX_ACT_CONSTRAINT_ORIY,
KX_ACT_CONSTRAINT_ORIZ,
@@ -127,27 +131,27 @@ protected:
virtual PyObject* _getattr(const STR_String& attr);
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDamp);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetDamp);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDamp);
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetRotDamp);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetRotDamp);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetRotDamp);
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDirection);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetDirection);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDirection);
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetOption);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetOption);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetOption);
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetTime);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetTime);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetTime);
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetProperty);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetProperty);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetProperty);
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMin);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetMin);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMin);
static char SetDistance_doc[];
static char GetDistance_doc[];
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMax);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetMax);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMax);
static char SetRayLength_doc[];
static char GetRayLength_doc[];
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetLimit);
- KX_PYMETHOD_DOC(KX_ConstraintActuator,GetLimit);
+ KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetLimit);
};
#endif //__KX_CONSTRAINTACTUATOR
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index d40fa1e2446..02d1ad1b12b 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
@@ -277,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;
}
@@ -442,6 +441,7 @@ void KX_GameObject::UpdateIPO(float curframetime,
// IPO update
void
KX_GameObject::UpdateMaterialData(
+ dword matname_hash,
MT_Vector4 rgba,
MT_Vector3 specrgb,
MT_Scalar hard,
@@ -453,16 +453,35 @@ 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)
{
- SetObjectColor(rgba);
KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly);
- m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
+
+ if (matname_hash == NULL)
+ {
+ 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)
+ if(!(poly->GetFlag() & RAS_BLENDERGLSL))
+ SetObjectColor(rgba);
+ }
+ else
+ {
+ if (matname_hash == poly->GetMaterialNameHash())
+ {
+ m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
+ m_meshes[mesh]->SetVertexColor(poly,rgba);
+
+ // no break here, because one blender material can be split into several game engine materials
+ // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
+ // if here was a break then would miss some vertices if material was split
+ }
+ }
}
}
}
@@ -1306,18 +1325,18 @@ PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
}
-static void walk_children(SG_Node* node, PyObject *list, bool recursive)
+static void walk_children(SG_Node* node, CListValue* list, bool recursive)
{
NodeList& children = node->GetSGChildren();
for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
{
SG_Node* childnode = (*childit);
- KX_GameObject* childobj = (KX_GameObject*)childnode->GetSGClientObject();
+ CValue* childobj = (CValue*)childnode->GetSGClientObject();
if (childobj != NULL) // This is a GameObject
{
// add to the list
- PyList_Append(list, (PyObject *)childobj);
+ list->Add(childobj->AddRef());
}
// if the childobj is NULL then this may be an inverse parent link
@@ -1330,14 +1349,14 @@ static void walk_children(SG_Node* node, PyObject *list, bool recursive)
PyObject* KX_GameObject::PyGetChildren(PyObject* self)
{
- PyObject * list = PyList_New(0);
+ CListValue* list = new CListValue();
walk_children(m_pSGNode, list, 0);
return list;
}
PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
{
- PyObject * list = PyList_New(0);
+ CListValue* list = new CListValue();
walk_children(m_pSGNode, list, 1);
return list;
}
@@ -1470,6 +1489,7 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self,
if (PyVecTo(pyvect, vect))
{
AlignAxisToVect(vect,axis,fac);
+ NodeUpdateGS(0.f,true);
Py_RETURN_NONE;
}
}
@@ -1567,8 +1587,10 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
float dist = 0.0f;
char *propName = NULL;
- if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName))
+ if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
+ }
if (!PyVecTo(pyarg, toPoint))
{
@@ -1615,11 +1637,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
}
KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
-"rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or None if no hit\n"
+ "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or (None,None,None) tuple if no hit\n"
" prop = property name that object must have; can be omitted => detect any object\n"
" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
" from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
-" Can None or omitted => start from self object center\n"
+" Can be None or omitted => start from self object center\n"
" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
"Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n")
{
@@ -1631,8 +1653,10 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
char *propName = NULL;
KX_GameObject *other;
- if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName))
+ if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
+ }
if (!PyVecTo(pyto, toPoint))
{
@@ -1690,16 +1714,14 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
if (m_pHitObject)
{
PyObject* returnValue = PyTuple_New(3);
- if (!returnValue)
+ if (!returnValue) {
+ PyErr_SetString(PyExc_TypeError, "PyTuple_New() failed");
return NULL;
+ }
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("(O,(fff),(fff))",
- // m_pHitObject->AddRef(), // trick: KX_GameObject are not true Python object, they use a difference reference count system
- // resultPoint[0], resultPoint[1], resultPoint[2],
- // resultNormal[0], resultNormal[1], resultNormal[2]);
}
return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
//Py_RETURN_NONE;
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 6051cf850b5..1d36798b12f 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -521,6 +521,7 @@ public:
*/
void
UpdateMaterialData(
+ dword matname_hash,
MT_Vector4 rgba,
MT_Vector3 specrgb,
MT_Scalar hard,
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
index b7103f49aee..af3add8a323 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.cpp
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -430,27 +430,27 @@ PyMethodDef KX_IpoActuator::Methods[] = {
{"setStart", (PyCFunction) KX_IpoActuator::sPySetStart,
METH_VARARGS, SetStart_doc},
{"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart,
- METH_VARARGS, GetStart_doc},
+ METH_NOARGS, GetStart_doc},
{"setEnd", (PyCFunction) KX_IpoActuator::sPySetEnd,
METH_VARARGS, SetEnd_doc},
{"getEnd", (PyCFunction) KX_IpoActuator::sPyGetEnd,
- METH_VARARGS, GetEnd_doc},
+ METH_NOARGS, GetEnd_doc},
{"setIpoAsForce", (PyCFunction) KX_IpoActuator::sPySetIpoAsForce,
METH_VARARGS, SetIpoAsForce_doc},
{"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce,
- METH_VARARGS, GetIpoAsForce_doc},
+ METH_NOARGS, GetIpoAsForce_doc},
{"setIpoAdd", (PyCFunction) KX_IpoActuator::sPySetIpoAdd,
METH_VARARGS, SetIpoAdd_doc},
{"getIpoAdd", (PyCFunction) KX_IpoActuator::sPyGetIpoAdd,
- METH_VARARGS, GetIpoAdd_doc},
+ METH_NOARGS, GetIpoAdd_doc},
{"setType", (PyCFunction) KX_IpoActuator::sPySetType,
METH_VARARGS, SetType_doc},
{"getType", (PyCFunction) KX_IpoActuator::sPyGetType,
- METH_VARARGS, GetType_doc},
+ METH_NOARGS, GetType_doc},
{"setForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPySetForceIpoActsLocal,
METH_VARARGS, SetForceIpoActsLocal_doc},
{"getForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPyGetForceIpoActsLocal,
- METH_VARARGS, GetForceIpoActsLocal_doc},
+ METH_NOARGS, GetForceIpoActsLocal_doc},
{NULL,NULL} //Sentinel
};
@@ -480,6 +480,7 @@ PyObject* KX_IpoActuator::PySet(PyObject* self,
int startFrame, stopFrame;
if(!PyArg_ParseTuple(args, "siii", &mode, &startFrame,
&stopFrame, &forceToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
modenum = string2mode(mode);
@@ -515,6 +516,7 @@ PyObject* KX_IpoActuator::PySetProperty(PyObject* self,
/* args: property */
char *propertyName;
if(!PyArg_ParseTuple(args, "s", &propertyName)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -533,6 +535,7 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self,
PyObject* kwds) {
float startArg;
if(!PyArg_ParseTuple(args, "f", &startArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -544,9 +547,7 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self,
char KX_IpoActuator::GetStart_doc[] =
"getStart()\n"
"\tReturns the frame from which the ipo starts playing.\n";
-PyObject* KX_IpoActuator::PyGetStart(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_IpoActuator::PyGetStart(PyObject* self) {
return PyFloat_FromDouble(m_startframe);
}
@@ -560,6 +561,7 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self,
PyObject* kwds) {
float endArg;
if(!PyArg_ParseTuple(args, "f", &endArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -571,9 +573,7 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self,
char KX_IpoActuator::GetEnd_doc[] =
"getEnd()\n"
"\tReturns the frame at which the ipo stops playing.\n";
-PyObject* KX_IpoActuator::PyGetEnd(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_IpoActuator::PyGetEnd(PyObject* self) {
return PyFloat_FromDouble(m_endframe);
}
@@ -588,6 +588,7 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self,
int boolArg;
if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -601,9 +602,7 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self,
char KX_IpoActuator::GetIpoAsForce_doc[] =
"getIpoAsForce()\n"
"\tReturns whether to interpret the ipo as a force rather than a displacement.\n";
-PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self) {
return BoolToPyArg(m_ipo_as_force);
}
@@ -618,6 +617,7 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self,
int boolArg;
if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -631,9 +631,7 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self,
char KX_IpoActuator::GetIpoAdd_doc[] =
"getIpoAsAdd()\n"
"\tReturns whether to interpret the ipo as additive rather than absolute.\n";
-PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self) {
return BoolToPyArg(m_ipo_add);
}
@@ -648,6 +646,7 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self,
int typeArg;
if (!PyArg_ParseTuple(args, "i", &typeArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -662,9 +661,7 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self,
char KX_IpoActuator::GetType_doc[] =
"getType()\n"
"\tReturns the operation mode of the actuator.\n";
-PyObject* KX_IpoActuator::PyGetType(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_IpoActuator::PyGetType(PyObject* self) {
return PyInt_FromLong(m_type);
}
@@ -681,6 +678,7 @@ PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self,
int boolArg;
if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
@@ -693,9 +691,7 @@ char KX_IpoActuator::GetForceIpoActsLocal_doc[] =
"getForceIpoActsLocal()\n"
"\tReturn whether to apply the force in the object's local\n"
"\tcoordinates rather than the world global coordinates.\n";
-PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self) {
return BoolToPyArg(m_ipo_local);
}
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h
index ae554fb0fce..d6f52f8d59d 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.h
+++ b/source/gameengine/Ketsji/KX_IpoActuator.h
@@ -143,17 +143,17 @@ public:
KX_PYMETHOD_DOC(KX_IpoActuator,SetProperty);
/* KX_PYMETHOD_DOC(KX_IpoActuator,SetKey2Key); */
KX_PYMETHOD_DOC(KX_IpoActuator,SetStart);
- KX_PYMETHOD_DOC(KX_IpoActuator,GetStart);
+ KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetStart);
KX_PYMETHOD_DOC(KX_IpoActuator,SetEnd);
- KX_PYMETHOD_DOC(KX_IpoActuator,GetEnd);
+ KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetEnd);
KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAsForce);
- KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAsForce);
+ KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetIpoAsForce);
KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAdd);
- KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAdd);
+ KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetIpoAdd);
KX_PYMETHOD_DOC(KX_IpoActuator,SetType);
- KX_PYMETHOD_DOC(KX_IpoActuator,GetType);
+ KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetType);
KX_PYMETHOD_DOC(KX_IpoActuator,SetForceIpoActsLocal);
- KX_PYMETHOD_DOC(KX_IpoActuator,GetForceIpoActsLocal);
+ KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetForceIpoActsLocal);
};
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_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
index c0757a32b9c..2ce5d469380 100644
--- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
+++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
@@ -37,6 +37,7 @@ bool KX_MaterialIpoController::Update(double currentTime)
//kxgameobj->SetObjectColor(m_rgba);
kxgameobj->UpdateMaterialData(
+ m_matname_hash,
m_rgba,
m_specrgb,
m_hard,
diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.h b/source/gameengine/Ketsji/KX_MaterialIpoController.h
index e76ddeefb04..4d2e258bf94 100644
--- a/source/gameengine/Ketsji/KX_MaterialIpoController.h
+++ b/source/gameengine/Ketsji/KX_MaterialIpoController.h
@@ -7,6 +7,8 @@
#include "SG_Spatial.h"
#include "KX_IInterpolator.h"
+#include "STR_String.h" //typedef dword
+
class KX_MaterialIpoController : public SG_Controller
{
public:
@@ -23,10 +25,12 @@ private:
bool m_modified;
double m_ipotime;
+ dword m_matname_hash;
public:
- KX_MaterialIpoController() :
+ KX_MaterialIpoController(dword matname_hash) :
m_modified(true),
- m_ipotime(0.0)
+ m_ipotime(0.0),
+ m_matname_hash(matname_hash)
{}
virtual ~KX_MaterialIpoController();
virtual SG_Controller* GetReplica(class SG_Node* destnode);
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_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
index 9ac0b4d4703..5cd4d089c14 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -304,27 +304,27 @@ PyParentObject KX_ObjectActuator::Parents[] = {
};
PyMethodDef KX_ObjectActuator::Methods[] = {
- {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_VARARGS},
+ {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_NOARGS},
{"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
- {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_VARARGS},
+ {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS},
{"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
- {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_VARARGS},
+ {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_NOARGS},
{"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
- {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_VARARGS},
+ {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_NOARGS},
{"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
- {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_VARARGS},
+ {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_NOARGS},
{"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
- {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_VARARGS},
+ {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_NOARGS},
{"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
{"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS},
- {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_VARARGS},
+ {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_NOARGS},
{"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS},
- {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_VARARGS},
+ {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_NOARGS},
{"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS},
- {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_VARARGS},
+ {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_NOARGS},
{"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS},
- {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_VARARGS},
- {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_VARARGS},
+ {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_NOARGS},
+ {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS},
{"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS},
@@ -340,9 +340,7 @@ PyObject* KX_ObjectActuator::_getattr(const STR_String& attr) {
/* Removed! */
/* 2. getForce */
-PyObject* KX_ObjectActuator::PyGetForce(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_ObjectActuator::PyGetForce(PyObject* self)
{
PyObject *retVal = PyList_New(4);
@@ -362,6 +360,7 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self,
int bToggle = 0;
if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
&vecArg[2], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_force.setValue(vecArg);
@@ -371,9 +370,7 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self,
}
/* 4. getTorque */
-PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self)
{
PyObject *retVal = PyList_New(4);
@@ -393,6 +390,7 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self,
int bToggle = 0;
if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
&vecArg[2], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_torque.setValue(vecArg);
@@ -402,9 +400,7 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self,
}
/* 6. getDLoc */
-PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self)
{
PyObject *retVal = PyList_New(4);
@@ -424,6 +420,7 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self,
int bToggle = 0;
if(!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
&vecArg[2], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_dloc.setValue(vecArg);
@@ -433,9 +430,7 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self,
}
/* 8. getDRot */
-PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self)
{
PyObject *retVal = PyList_New(4);
@@ -455,6 +450,7 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self,
int bToggle = 0;
if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
&vecArg[2], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_drot.setValue(vecArg);
@@ -464,9 +460,7 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self,
}
/* 10. getLinearVelocity */
-PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self) {
PyObject *retVal = PyList_New(4);
PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
@@ -485,6 +479,7 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self,
int bToggle = 0;
if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
&vecArg[2], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_linear_velocity.setValue(vecArg);
@@ -495,9 +490,7 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self,
/* 12. getAngularVelocity */
-PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self) {
PyObject *retVal = PyList_New(4);
PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
@@ -515,6 +508,7 @@ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self,
int bToggle = 0;
if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1],
&vecArg[2], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_angular_velocity.setValue(vecArg);
@@ -529,6 +523,7 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* self,
PyObject* kwds) {
int damping = 0;
if (!PyArg_ParseTuple(args, "i", &damping) || damping < 0 || damping > 1000) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_damping = damping;
@@ -536,15 +531,11 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* self,
}
/* 13. getVelocityDamping */
-PyObject* KX_ObjectActuator::PyGetDamping(PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* KX_ObjectActuator::PyGetDamping(PyObject* self) {
return Py_BuildValue("i",m_damping);
}
/* 6. getForceLimitX */
-PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self)
{
PyObject *retVal = PyList_New(3);
@@ -562,6 +553,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self,
float vecArg[2];
int bToggle = 0;
if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_drot[0] = vecArg[0];
@@ -571,9 +563,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self,
}
/* 6. getForceLimitY */
-PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self)
{
PyObject *retVal = PyList_New(3);
@@ -591,6 +581,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self,
float vecArg[2];
int bToggle = 0;
if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_drot[1] = vecArg[0];
@@ -600,9 +591,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self,
}
/* 6. getForceLimitZ */
-PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self)
{
PyObject *retVal = PyList_New(3);
@@ -620,6 +609,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self,
float vecArg[2];
int bToggle = 0;
if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_drot[2] = vecArg[0];
@@ -629,9 +619,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self,
}
/* 4. getPID */
-PyObject* KX_ObjectActuator::PyGetPID(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_ObjectActuator::PyGetPID(PyObject* self)
{
PyObject *retVal = PyList_New(3);
@@ -648,6 +636,7 @@ PyObject* KX_ObjectActuator::PySetPID(PyObject* self,
{
float vecArg[3];
if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) {
+ PyErr_SetString(PyExc_TypeError, "Invalid arguments");
return NULL;
}
m_torque.setValue(vecArg);
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h
index bb74756551f..aa686f41233 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.h
@@ -155,27 +155,27 @@ public:
virtual PyObject* _getattr(const STR_String& attr);
- KX_PYMETHOD(KX_ObjectActuator,GetForce);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce);
KX_PYMETHOD(KX_ObjectActuator,SetForce);
- KX_PYMETHOD(KX_ObjectActuator,GetTorque);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetTorque);
KX_PYMETHOD(KX_ObjectActuator,SetTorque);
- KX_PYMETHOD(KX_ObjectActuator,GetDLoc);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDLoc);
KX_PYMETHOD(KX_ObjectActuator,SetDLoc);
- KX_PYMETHOD(KX_ObjectActuator,GetDRot);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDRot);
KX_PYMETHOD(KX_ObjectActuator,SetDRot);
- KX_PYMETHOD(KX_ObjectActuator,GetLinearVelocity);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetLinearVelocity);
KX_PYMETHOD(KX_ObjectActuator,SetLinearVelocity);
- KX_PYMETHOD(KX_ObjectActuator,GetAngularVelocity);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetAngularVelocity);
KX_PYMETHOD(KX_ObjectActuator,SetAngularVelocity);
KX_PYMETHOD(KX_ObjectActuator,SetDamping);
- KX_PYMETHOD(KX_ObjectActuator,GetDamping);
- KX_PYMETHOD(KX_ObjectActuator,GetForceLimitX);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDamping);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitX);
KX_PYMETHOD(KX_ObjectActuator,SetForceLimitX);
- KX_PYMETHOD(KX_ObjectActuator,GetForceLimitY);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitY);
KX_PYMETHOD(KX_ObjectActuator,SetForceLimitY);
- KX_PYMETHOD(KX_ObjectActuator,GetForceLimitZ);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitZ);
KX_PYMETHOD(KX_ObjectActuator,SetForceLimitZ);
- KX_PYMETHOD(KX_ObjectActuator,GetPID);
+ KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetPID);
KX_PYMETHOD(KX_ObjectActuator,SetPID);
};
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_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h
index e1715c9275f..4e383e9b3d4 100644
--- a/source/gameengine/Ketsji/KX_PyMath.h
+++ b/source/gameengine/Ketsji/KX_PyMath.h
@@ -84,7 +84,10 @@ bool PyMatTo(PyObject* pymat, T& mat)
}
} else
noerror = false;
-
+
+ if (noerror==false)
+ PyErr_SetString(PyExc_TypeError, "could not be converted to a matrix (sequence of sequences)");
+
return noerror;
}
@@ -97,9 +100,13 @@ bool PyVecTo(PyObject* pyval, T& vec)
if (PySequence_Check(pyval))
{
unsigned int numitems = PySequence_Size(pyval);
- if (numitems != Size(vec))
+ if (numitems != Size(vec)) {
+ char err[128];
+ sprintf(err, "error setting vector, %d args, should be %d", numitems, Size(vec));
+ PyErr_SetString(PyExc_AttributeError, err);
return false;
-
+ }
+
for (unsigned int x = 0; x < numitems; x++)
{
PyObject *item = PySequence_GetItem(pyval, x); /* new ref */
@@ -107,7 +114,17 @@ bool PyVecTo(PyObject* pyval, T& vec)
Py_DECREF(item);
}
+ if (PyErr_Occurred()) {
+ PyErr_SetString(PyExc_AttributeError, "one or more of the items in the sequence was not a float");
+ return false;
+ }
+
return true;
+ } else
+ {
+ char err[128];
+ sprintf(err, "not a sequence type, expected a sequence of numbers size %d", Size(vec));
+ PyErr_SetString(PyExc_AttributeError, err);
}
return false;
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 61ed8b6a8e4..b66c3e42606 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -756,6 +756,15 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTX);
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTY);
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTZ);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRPX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRPX);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRPY);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRPY);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRNX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNX);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNY);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNY);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIY);
+ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIZ);
/* 4. Ipo actuator, simple part */
KX_MACRO_addTypesToDict(d, KX_IPOACT_PLAY, KX_IpoActuator::KX_ACT_IPO_PLAY);
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<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++)
+ for (set<class SCA_ISensor*>::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_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index c374b9d6fd1..2828663c63d 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"
@@ -92,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;
}
@@ -116,13 +120,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;
@@ -650,14 +654,14 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
if (blgroupobj == blenderobj)
// this check is also in group_duplilist()
continue;
- gameobj = m_sceneConverter->FindGameObject(blenderobj);
+ gameobj = (KX_GameObject*)m_logicmgr->FindGameObjByBlendObj(blenderobj);
if (gameobj == NULL)
{
// this object has not been converted!!!
// 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;
@@ -669,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
@@ -860,6 +868,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
replica->GetSGNode()->UpdateWorldData(0);
replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
+ // check if there are objects with dupligroup in the hierarchy
+ vector<KX_GameObject*> duplilist;
+ for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
+ {
+ if ((*git)->IsDupliGroup())
+ {
+ // separate list as m_logicHierarchicalGameObjects is also used by DupliGroupRecurse()
+ duplilist.push_back(*git);
+ }
+ }
+ for (git = duplilist.begin();!(git==duplilist.end());++git)
+ {
+ DupliGroupRecurse(*git, 0);
+ }
// don't release replica here because we are returning it, not done with it...
return replica;
}
@@ -906,6 +928,12 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
int ret;
KX_GameObject* newobj = (KX_GameObject*) gameobj;
+ // keep the blender->game object association up to date
+ // note that all the replicas of an object will have the same
+ // blender object, that's why we need to check the game object
+ // as only the deletion of the original object must be recorded
+ m_logicmgr->UnregisterGameObj(newobj->GetBlenderObject(), gameobj);
+
//todo: look at this
//GetPhysicsEnvironment()->RemovePhysicsController(gameobj->getPhysicsController());
@@ -964,6 +992,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);
@@ -1220,14 +1249,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;m<nummeshes;m++)
- {
- // this adds the vertices to the display list
- (gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode());
- }
+ (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode());
}
gameobj->MarkVisible(visible);
}
@@ -1284,12 +1309,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;m<nummeshes;m++)
{
// this adds the vertices to the display list
- (gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode());
+ (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode());
}
// Visibility/ non-visibility are marked
// elsewhere now.
@@ -1402,7 +1426,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);
}
@@ -1412,10 +1436,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/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<KX_TouchSensor*>(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<KX_TouchSensor*>(sensor);
+ m_sensors.erase(touchsensor);
+
+ touchsensor->UnregisterSumo(this);
+}
+
void KX_TouchEventManager::EndFrame()
{
- vector<SCA_ISensor*>::iterator it;
+ set<SCA_ISensor*>::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<SCA_ISensor*>::iterator it;
+ set<SCA_ISensor*>::iterator it;
for (it = m_sensors.begin();!(it==m_sensors.end());++it)
static_cast<KX_TouchSensor*>(*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<SCA_ISensor*>::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/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index c580aa4d4e5..f5b463abf02 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -146,19 +146,19 @@ void compatible_eulFast(float *eul, float *oldrot)
{
float dx, dy, dz;
- /* verschillen van ong 360 graden corrigeren */
+ /* angular difference of 360 degrees */
dx= eul[0] - oldrot[0];
dy= eul[1] - oldrot[1];
dz= eul[2] - oldrot[2];
- if( fabs(dx) > 5.1) {
+ if( fabs(dx) > MT_PI) {
if(dx > 0.0) eul[0] -= MT_2_PI; else eul[0]+= MT_2_PI;
}
- if( fabs(dy) > 5.1) {
+ if( fabs(dy) > MT_PI) {
if(dy > 0.0) eul[1] -= MT_2_PI; else eul[1]+= MT_2_PI;
}
- if( fabs(dz) > 5.1 ) {
+ if( fabs(dz) > MT_PI ) {
if(dz > 0.0) eul[2] -= MT_2_PI; else eul[2]+= MT_2_PI;
}
}
@@ -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<GEN_HashedPtr, void*> *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();
+ }
}
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<CcdPhysicsController*>::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<CcdPhysicsController*>::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<CcdPhysicsController*>::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<CcdPhysicsController*>::iterator it;
+ int i;
- int i,numCtrl = GetNumControllers();
- for (i=0;i<numCtrl;i++)
+ for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
{
- CcdPhysicsController* ctrl = GetPhysicsController(i);
- ctrl->SynchronizeMotionStates(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;i<numCtrl;i++)
+ for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
{
- CcdPhysicsController* ctrl = GetPhysicsController(i);
- ctrl->SynchronizeMotionStates(timeStep);
+ (*it)->SynchronizeMotionStates(timeStep);
}
for (i=0;i<m_wrapperVehicles.size();i++)
@@ -852,20 +826,6 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
}
-int CcdPhysicsEnvironment::GetNumControllers()
-{
- return m_controllers.size();
-}
-
-
-CcdPhysicsController* CcdPhysicsEnvironment::GetPhysicsController( int index)
-{
- return m_controllers[index];
-}
-
-
-
-
void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float value0,float value1)
{
btTypedConstraint* typedConstraint = getConstraintById(constraintId);
@@ -905,12 +865,14 @@ void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl)
{
CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl;
- std::vector<CcdPhysicsController*>::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<CcdPhysicsController*>::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<CcdPhysicsController*>(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<CcdPhysicsController*>(obj0->getUserPointer());
CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer());
- std::vector<CcdPhysicsController*>::iterator i =
- std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl0);
+ std::set<CcdPhysicsController*>::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 <vector>
+#include <set>
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<CcdPhysicsController*> m_controllers;
+ std::set<CcdPhysicsController*> m_controllers;
- std::vector<CcdPhysicsController*> m_triggerControllers;
+ std::set<CcdPhysicsController*> 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;
diff --git a/source/gameengine/PyDoc/BL_ShapeActionActuator.py b/source/gameengine/PyDoc/BL_ShapeActionActuator.py
new file mode 100644
index 00000000000..63cce253fa4
--- /dev/null
+++ b/source/gameengine/PyDoc/BL_ShapeActionActuator.py
@@ -0,0 +1,158 @@
+# $Id$
+# Documentation for BL_ShapeActionActuator
+from SCA_IActuator import *
+
+class BL_ShapeActionActuator(SCA_IActuator):
+ """
+ ShapeAction Actuators apply an shape action to an mesh object.
+ """
+ def setAction(action, reset = True):
+ """
+ Sets the current action.
+
+ @param action: The name of the action to set as the current action.
+ @type action: string
+ @param reset: Optional parameter indicating whether to reset the
+ blend timer or not. A value of 1 indicates that the
+ timer should be reset. A value of 0 will leave it
+ unchanged. If reset is not specified, the timer will
+ be reset.
+ """
+
+ def setStart(start):
+ """
+ Specifies the starting frame of the animation.
+
+ @param start: the starting frame of the animation
+ @type start: float
+ """
+
+ def setEnd(end):
+ """
+ Specifies the ending frame of the animation.
+
+ @param end: the ending frame of the animation
+ @type end: float
+ """
+ def setBlendin(blendin):
+ """
+ Specifies the number of frames of animation to generate
+ when making transitions between actions.
+
+ @param blendin: the number of frames in transition.
+ @type blendin: float
+ """
+
+ def setPriority(priority):
+ """
+ Sets the priority of this actuator.
+
+ @param priority: Specifies the new priority. Actuators will lower
+ priority numbers will override actuators with higher
+ numbers.
+ @type priority: integer
+ """
+ def setFrame(frame):
+ """
+ Sets the current frame for the animation.
+
+ @param frame: Specifies the new current frame for the animation
+ @type frame: float
+ """
+
+ def setProperty(prop):
+ """
+ Sets the property to be used in FromProp playback mode.
+
+ @param prop: the name of the property to use.
+ @type prop: string.
+ """
+
+ def setBlendtime(blendtime):
+ """
+ Sets the internal frame timer.
+
+ Allows the script to directly modify the internal timer
+ used when generating transitions between actions.
+
+ @param blendtime: The new time. This parameter must be in the range from 0.0 to 1.0.
+ @type blendtime: float
+ """
+
+ def setType(mode):
+ """
+ Sets the operation mode of the actuator
+
+ @param mode: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND
+ @type mode: integer
+ """
+
+ def setContinue(cont):
+ """
+ Set the actions continue option True or False. see getContinue.
+
+ @param cont: The continue option.
+ @type cont: bool
+ """
+
+ def getType():
+ """
+ Returns the operation mode of the actuator
+
+ @rtype: integer
+ @return: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND
+ """
+
+ def getContinue():
+ """
+ When True, the action will always play from where last left off, otherwise negative events to this actuator will reset it to its start frame.
+
+ @rtype: bool
+ """
+
+ def getAction():
+ """
+ getAction() returns the name of the action associated with this actuator.
+
+ @rtype: string
+ """
+
+ def getStart():
+ """
+ Returns the starting frame of the action.
+
+ @rtype: float
+ """
+ def getEnd():
+ """
+ Returns the last frame of the action.
+
+ @rtype: float
+ """
+ def getBlendin():
+ """
+ Returns the number of interpolation animation frames to be generated when this actuator is triggered.
+
+ @rtype: float
+ """
+ def getPriority():
+ """
+ Returns the priority for this actuator. Actuators with lower Priority numbers will
+ override actuators with higher numbers.
+
+ @rtype: integer
+ """
+ def getFrame():
+ """
+ Returns the current frame number.
+
+ @rtype: float
+ """
+ def getProperty():
+ """
+ Returns the name of the property to be used in FromProp mode.
+
+ @rtype: string
+ """
+
+
diff --git a/source/gameengine/PyDoc/KX_ActuatorSensor.py b/source/gameengine/PyDoc/KX_ActuatorSensor.py
new file mode 100644
index 00000000000..f9aef86f7f0
--- /dev/null
+++ b/source/gameengine/PyDoc/KX_ActuatorSensor.py
@@ -0,0 +1,24 @@
+# $Id$
+# Documentation for KX_ActuatorSensor
+from SCA_IActuator import *
+
+class KX_ActuatorSensor(SCA_ISensor):
+ """
+ Actuator sensor detect change in actuator state of the parent object.
+ It generates a positive pulse if the corresponding actuator is activated
+ and a negative pulse if the actuator is deactivated.
+ """
+ def getActuator():
+ """
+ Return the Actuator with which the sensor operates.
+
+ @rtype: string
+ """
+ def setActuator(name):
+ """
+ Sets the Actuator with which to operate. If there is no Actuator
+ of this name, the function has no effect.
+
+ @param name: actuator name
+ @type name: string
+ """
diff --git a/source/gameengine/PyDoc/KX_ConstraintActuator.py b/source/gameengine/PyDoc/KX_ConstraintActuator.py
index 9630690e572..b1c6f3c0f4e 100644
--- a/source/gameengine/PyDoc/KX_ConstraintActuator.py
+++ b/source/gameengine/PyDoc/KX_ConstraintActuator.py
@@ -4,7 +4,7 @@ from SCA_IActuator import *
class KX_ConstraintActuator(SCA_IActuator):
"""
- A constraint actuator limits the position or orientation of an object.
+ A constraint actuator limits the position, rotation, distance or orientation of an object.
"""
def setDamp(time):
"""
@@ -24,7 +24,7 @@ class KX_ConstraintActuator(SCA_IActuator):
"""
Sets the lower bound of the constraint.
- For rotational constraints, lower is specified in degrees.
+ For rotational and orientation constraints, lower is specified in degrees.
@type lower: float
"""
@@ -32,7 +32,7 @@ class KX_ConstraintActuator(SCA_IActuator):
"""
Gets the lower bound of the constraint.
- For rotational constraints, the lower bound is returned in radians.
+ For rotational and orientation constraints, the lower bound is returned in radians.
@rtype: float
"""
@@ -40,7 +40,7 @@ class KX_ConstraintActuator(SCA_IActuator):
"""
Sets the upper bound of the constraint.
- For rotational constraints, upper is specified in degrees.
+ For rotational and orientation constraints, upper is specified in degrees.
@type upper: float
"""
@@ -48,7 +48,7 @@ class KX_ConstraintActuator(SCA_IActuator):
"""
Gets the upper bound of the constraint.
- For rotational constraints, the upper bound is returned in radians.
+ For rotational and orientation constraints, the upper bound is returned in radians.
@rtype: float
"""
@@ -60,6 +60,9 @@ class KX_ConstraintActuator(SCA_IActuator):
@param limit: Position constraints: KX_CONSTRAINTACT_LOCX, KX_CONSTRAINTACT_LOCY, KX_CONSTRAINTACT_LOCZ,
Rotation constraints: KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY or KX_CONSTRAINTACT_ROTZ
+ Distance contraints: KX_ACT_CONSTRAINT_DIRPX, KX_ACT_CONSTRAINT_DIRPY, KX_ACT_CONSTRAINT_DIRPZ,
+ KX_ACT_CONSTRAINT_DIRNX, KX_ACT_CONSTRAINT_DIRNY, KX_ACT_CONSTRAINT_DIRNZ,
+ Orientation constraints: KX_ACT_CONSTRAINT_ORIX, KX_ACT_CONSTRAINT_ORIY, KX_ACT_CONSTRAINT_ORIZ
"""
def getLimit():
"""
@@ -68,5 +71,110 @@ class KX_ConstraintActuator(SCA_IActuator):
See module L{GameLogic} for valid constraints.
@return: Position constraints: KX_CONSTRAINTACT_LOCX, KX_CONSTRAINTACT_LOCY, KX_CONSTRAINTACT_LOCZ,
- Rotation constraints: KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY or KX_CONSTRAINTACT_ROTZ
+ Rotation constraints: KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY, KX_CONSTRAINTACT_ROTZ,
+ Distance contraints: KX_ACT_CONSTRAINT_DIRPX, KX_ACT_CONSTRAINT_DIRPY, KX_ACT_CONSTRAINT_DIRPZ,
+ KX_ACT_CONSTRAINT_DIRNX, KX_ACT_CONSTRAINT_DIRNY, KX_ACT_CONSTRAINT_DIRNZ,
+ Orientation constraints: KX_ACT_CONSTRAINT_ORIX, KX_ACT_CONSTRAINT_ORIY, KX_ACT_CONSTRAINT_ORIZ
"""
+ def setRotDamp(duration):
+ """
+ Sets the time constant of the orientation constraint.
+
+ @param duration: If the duration is negative, it is set to 0.
+ @type duration: integer
+ """
+ def getRotDamp():
+ """
+ Returns the damping time for application of the constraint.
+
+ @rtype: integer
+ """
+ def setDirection(vector):
+ """
+ Sets the reference direction in world coordinate for the orientation constraint
+
+ @type vector: 3-tuple
+ """
+ def getDirection():
+ """
+ Returns the reference direction of the orientation constraint in world coordinate.
+
+ @rtype: 3-tuple
+ """
+ def setOption(option):
+ """
+ Sets several options of the distance constraint.
+
+ @type option: integer
+ @param option: Binary combination of the following values:
+ 64 : Activate alignment to surface
+ 128 : Detect material rather than property
+ 256 : No deactivation if ray does not hit target
+ 512 : Activate distance control
+ """
+ def getOption():
+ """
+ Returns the option parameter.
+
+ @rtype: integer
+ """
+ def setTime(duration):
+ """
+ Sets the activation time of the actuator.
+
+ @type duration: integer
+ @param duration: The actuator disables itself after this many frame.
+ If set to 0 or negative, the actuator is not limited in time.
+ """
+ def getTime():
+ """
+ Returns the time parameter.
+
+ @rtype: integer
+ """
+ def setProperty(property):
+ """
+ Sets the name of the property or material for the ray detection of the distance constraint.
+
+ @type property: string
+ @param property: If empty, the ray will detect any collisioning object.
+ """
+ def getProperty():
+ """
+ Returns the property parameter.
+
+ @rtype: string
+ """
+ def setDistance(distance):
+ """
+ Sets the target distance in distance constraint.
+
+ @type distance: float
+ """
+ def getDistance():
+ """
+ Returns the distance parameter.
+
+ @rtype: float
+ """
+ def setRayLength(length):
+ """
+ Sets the maximum ray length of the distance constraint.
+
+ @type length: float
+ """
+ def getRayLength():
+ """
+ Returns the length of the ray
+
+ @rtype: float
+ """
+
+
+
+
+
+
+
+
+
diff --git a/source/gameengine/PyDoc/KX_IpoActuator.py b/source/gameengine/PyDoc/KX_IpoActuator.py
index da8d05ddd5e..1cdab829385 100644
--- a/source/gameengine/PyDoc/KX_IpoActuator.py
+++ b/source/gameengine/PyDoc/KX_IpoActuator.py
@@ -6,7 +6,7 @@ class KX_IpoActuator(SCA_IActuator):
"""
IPO actuator activates an animation.
"""
- def set(mode, startframe, endframe, force):
+ def set(mode, startframe, endframe, mode):
"""
Sets the properties of the actuator.
@@ -16,8 +16,8 @@ class KX_IpoActuator(SCA_IActuator):
@type startframe: integer
@param endframe: last frame to use
@type endframe: integer
- @param force: interpret this ipo as a force
- @type force: boolean (KX_TRUE, KX_FALSE)
+ @param mode: special mode
+ @type mode: integer (0=normal, 1=interpret location as force, 2=additive)
"""
def setProperty(property):
"""
@@ -62,6 +62,19 @@ class KX_IpoActuator(SCA_IActuator):
@rtype: boolean
"""
+ def setIpoAdd(add):
+ """
+ Set whether to interpret the ipo as additive rather than absolute.
+
+ @type add: boolean
+ @param add: KX_TRUE or KX_FALSE
+ """
+ def getIpoAdd():
+ """
+ Returns whether to interpret the ipo as additive rather than absolute.
+
+ @rtype: boolean
+ """
def setType(mode):
"""
Sets the operation mode of the actuator.
diff --git a/source/gameengine/PyDoc/KX_ObjectActuator.py b/source/gameengine/PyDoc/KX_ObjectActuator.py
index 532c18eea5c..db577d21e6f 100644
--- a/source/gameengine/PyDoc/KX_ObjectActuator.py
+++ b/source/gameengine/PyDoc/KX_ObjectActuator.py
@@ -6,6 +6,7 @@ class KX_ObjectActuator(SCA_IActuator):
"""
The object actuator ("Motion Actuator") applies force, torque, displacement, angular displacement,
velocity, or angular velocity to an object.
+ Servo control allows to regulate force to achieve a certain speed target.
"""
def getForce():
"""
@@ -107,15 +108,17 @@ class KX_ObjectActuator(SCA_IActuator):
def getLinearVelocity():
"""
Returns the linear velocity applied by the actuator.
+ For the servo control actuator, this is the target speed.
@rtype: list [vx, vy, vz, local]
@return: A four item list, containing the vector velocity, and whether
the velocity is applied in local coordinates (True) or world
- coordinates (False)
+ coordinates (False)
"""
def setLinearVelocity(vx, vy, vz, local):
"""
Sets the linear velocity applied by the actuator.
+ For the servo control actuator, sets the target speed.
@type vx: float
@param vx: the x component of the velocity vector.
@@ -124,8 +127,8 @@ class KX_ObjectActuator(SCA_IActuator):
@type vz: float
@param vz: the z component of the velocity vector.
@type local: boolean
- @param local: - False: the velocity vector is applied in world coordinates.
- - True: the velocity vector is applied in local coordinates.
+ @param local: - False: the velocity vector is in world coordinates.
+ - True: the velocity vector is in local coordinates.
"""
def getAngularVelocity():
"""
@@ -150,5 +153,100 @@ class KX_ObjectActuator(SCA_IActuator):
@param local: - False: the velocity vector is applied in world coordinates.
- True: the velocity vector is applied in local coordinates.
"""
+ def getDamping():
+ """
+ Returns the damping parameter of the servo controller.
+
+ @rtype: integer
+ @return: the time constant of the servo controller in frame unit.
+ """
+ def setDamping(damp):
+ """
+ Sets the damping parameter of the servo controller.
+
+ @type damp: integer
+ @param damp: the damping parameter in frame unit.
+ """
+ def getForceLimitX():
+ """
+ Returns the min/max force limit along the X axis used by the servo controller.
+
+ @rtype: list [min, max, enabled]
+ @return: A three item list, containing the min and max limits of the force as float
+ and whether the limits are active(true) or inactive(true)
+ """
+ def setForceLimitX(min, max, enable):
+ """
+ Sets the min/max force limit along the X axis and activates or deactivates the limits in the servo controller.
+
+ @type min: float
+ @param min: the minimum value of the force along the X axis.
+ @type max: float
+ @param max: the maximum value of the force along the X axis.
+ @type enable: boolean
+ @param enable: - True: the force will be limited to the min/max
+ - False: the force will not be limited
+ """
+ def getForceLimitY():
+ """
+ Returns the min/max force limit along the Y axis used by the servo controller.
+
+ @rtype: list [min, max, enabled]
+ @return: A three item list, containing the min and max limits of the force as float
+ and whether the limits are active(true) or inactive(true)
+ """
+ def setForceLimitY(min, max, enable):
+ """
+ Sets the min/max force limit along the Y axis and activates or deactivates the limits in the servo controller.
+
+ @type min: float
+ @param min: the minimum value of the force along the Y axis.
+ @type max: float
+ @param max: the maximum value of the force along the Y axis.
+ @type enable: boolean
+ @param enable: - True: the force will be limited to the min/max
+ - False: the force will not be limited
+ """
+ def getForceLimitZ():
+ """
+ Returns the min/max force limit along the Z axis used by the servo controller.
+
+ @rtype: list [min, max, enabled]
+ @return: A three item list, containing the min and max limits of the force as float
+ and whether the limits are active(true) or inactive(true)
+ """
+ def setForceLimitZ(min, max, enable):
+ """
+ Sets the min/max force limit along the Z axis and activates or deactivates the limits in the servo controller.
+
+ @type min: float
+ @param min: the minimum value of the force along the Z axis.
+ @type max: float
+ @param max: the maximum value of the force along the Z axis.
+ @type enable: boolean
+ @param enable: - True: the force will be limited to the min/max
+ - False: the force will not be limited
+ """
+ def getPID():
+ """
+ Returns the PID coefficient of the servo controller.
+
+ @rtype: list [P, I, D]
+ @return: A three item list, containing the PID coefficient as floats:
+ P : proportional coefficient
+ I : Integral coefficient
+ D : Derivate coefficient
+ """
+ def setPID(P, I, D):
+ """
+ Sets the PID coefficients of the servo controller.
+
+ @type P: flat
+ @param P: proportional coefficient
+ @type I: float
+ @param I: Integral coefficient
+ @type D: float
+ @param D: Derivate coefficient
+ """
diff --git a/source/gameengine/PyDoc/KX_StateActuator.py b/source/gameengine/PyDoc/KX_StateActuator.py
new file mode 100644
index 00000000000..fb6ae5a3621
--- /dev/null
+++ b/source/gameengine/PyDoc/KX_StateActuator.py
@@ -0,0 +1,26 @@
+# $Id$
+# Documentation for KX_StateActuator
+from SCA_IActuator import *
+
+class KX_StateActuator(SCA_IActuator):
+ """
+ State actuator changes the state mask of parent object.
+ """
+ def setOperation(op):
+ """
+ Set the type of bit operation to be applied on object state mask.
+ Use setMask() to specify the bits that will be modified.
+
+ @param op: bit operation (0=Copy, 1=Add, 2=Substract, 3=Invert)
+ @type op: integer
+ """
+ def setMask(mask):
+ """
+ Set the value that defines the bits that will be modified by the operation.
+ The bits that are 1 in the value will be updated in the object state,
+ the bits that are 0 are will be left unmodified expect for the Copy operation
+ which copies the value to the object state.
+
+ @param mask: bits that will be modified
+ @type mask: integer
+ """
diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py
index b96d8c8c075..0ebc2debb31 100644
--- a/source/gameengine/PyDoc/SCA_ISensor.py
+++ b/source/gameengine/PyDoc/SCA_ISensor.py
@@ -59,4 +59,22 @@ class SCA_ISensor(SCA_ILogicBrick):
@type invert: boolean
@param invert: true if activates on negative events; false if activates on positive events.
"""
+ def getLevel():
+ """
+ Returns whether this sensor is a level detector or a edge detector.
+ It makes a difference only in case of logic state transition (state actuator).
+ A level detector will immediately generate a pulse, negative or positive
+ depending on the sensor condition, as soon as the state is activated.
+ A edge detector will wait for a state change before generating a pulse.
+
+ @rtype: boolean
+ @return: true if sensor is level sensitive, false if it is edge sensitive
+ """
+ def setLevel(level):
+ """
+ Set whether to detect level or edge transition when entering a state.
+
+ @param level: Detect level instead of edge? (KX_TRUE, KX_FALSE)
+ @type level: boolean
+ """
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_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),
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
index cb10ba6bf37..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
@@ -139,6 +143,11 @@ const STR_String& RAS_IPolyMaterial::GetMaterialName() const
return m_materialname;
}
+dword RAS_IPolyMaterial::GetMaterialNameHash() const
+{
+ return m_materialname.hash();
+}
+
const STR_String& RAS_IPolyMaterial::GetTextureName() const
{
return m_texturename;
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
index d2d1dba99d9..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,12 +134,13 @@ 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;
int GetDrawingMode() const;
const STR_String& GetMaterialName() const;
+ dword GetMaterialNameHash() const;
const STR_String& GetTextureName() const;
const unsigned int GetFlag() 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->IsAlpha());
+}
+
+bool RAS_MaterialBucket::IsZSort() const
{
- return (m_material->IsTransparant());
+ 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 4420f16c56d..af5228e4c35 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 <algorithm>
+
STR_String RAS_MeshObject::s_emptyname = "";
@@ -201,28 +203,35 @@ void RAS_MeshObject::DebugColor(unsigned int abgr)
m_debugcolor = abgr;
}
-
+void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba)
+{
+ const vecVertexArray & vertexvec = GetVertexCache(mat);
+
+ for (vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it)
+ {
+ KX_VertexArray::iterator vit;
+ for (vit=(*it)->begin(); vit != (*it)->end(); vit++)
+ {
+ vit->SetRGBA(rgba);
+ }
+ }
+}
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;
+
+ if (!mat->UsesTriangles())
ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]);
- }
}
-
void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx,
int numverts,
int edgecode,
@@ -409,7 +418,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);
}
@@ -434,7 +442,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);
}
@@ -453,7 +460,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);
}
@@ -572,31 +578,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; i<nvert; i++) {
+ m_index[i] = indexarray[offset+i];
+ center += vertexarray[m_index[i]].getLocalXYZ();
}
- m_z /= m_poly->VertexCount();
+
+ /* 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<nvert; i++)
+ indexarray[offset+i] = m_index[i];
}
};
@@ -616,100 +627,100 @@ struct RAS_MeshObject::fronttoback
}
};
-
void RAS_MeshObject::SortPolygons(const MT_Transform &transform)
{
+ // Limitations: sorting is quite simple, and handles many
+ // cases wrong, partially due to polygons being sorted per
+ // bucket.
+ //
+ // a) mixed triangles/quads are sorted wrong
+ // b) mixed materials are sorted wrong
+ // c) more than 65k faces are sorted wrong
+ // d) intersecting objects are sorted wrong
+ // e) intersecting polygons are sorted wrong
+ //
+ // a) can be solved by making all faces either triangles or quads
+ // if they need to be z-sorted. c) could be solved by allowing
+ // larger buckets, b) and d) cannot be solved easily if we want
+ // to avoid excessive state changes while drawing. e) would
+ // require splitting polygons.
+
if (!m_zsort)
return;
-
+
// Extract camera Z plane...
const MT_Vector3 pnorm(transform.getBasis()[2]);
- const MT_Scalar pval = transform.getOrigin()[2];
-
- unsigned int numpolys = m_Polygons.size();
- std::multiset<polygonSlot, backtofront> alphapolyset;
- std::multiset<polygonSlot, fronttoback> 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<KX_IndexArray*> *indexcache = &GetArrayOptimizer((*it)->GetPolyMaterial())->m_IndexArrayCache1;
- for (vector<KX_IndexArray*>::iterator iit = indexcache->begin(); iit != indexcache->end(); ++iit)
- (*iit)->clear();
- }
+ if(!(*it)->IsZSort())
+ continue;
- std::multiset<polygonSlot, fronttoback>::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<polygonSlot, backtofront>::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<indexarrays.size(); i++) {
+ KX_IndexArray& indexarray = *indexarrays[i];
+ KX_VertexArray& vertexarray = *vertexarrays[i];
+
+ unsigned int totpoly = indexarray.size()/nvert;
+ vector<polygonSlot> slots(totpoly);
+
+ /* get indices and z into temporary array */
+ for(j=0; j<totpoly; j++)
+ slots[j].get(vertexarray, indexarray, j*nvert, nvert, pnorm);
+
+ /* sort (stable_sort might be better, if flickering happens?) */
+ std::sort(slots.begin(), slots.end(), backtofront());
+
+ /* get indices from temporary array again */
+ for(j=0; j<totpoly; j++)
+ slots[j].set(indexarray, j*nvert, nvert);
+ }
+ }
}
-void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawingmode)
+void RAS_MeshObject::SchedulePolygons(int drawingmode)
{
-// int nummaterials = m_materials.size();
- int i;
-
if (m_bModified)
{
- for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it)
- {
- RAS_MaterialBucket* bucket = *it;
+ int i, numpolys = m_Polygons.size();
- bucket->SchedulePolygons(drawingmode);
- if (bucket->GetPolyMaterial()->IsZSort())
+ for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it)
+ 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;i<numpolys;i++)
{
RAS_Polygon* poly = m_Polygons[i];
if (poly->IsVisible())
- 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;i<numpolys;i++)
{
- for (i=0;i<numpolys;i++)
- {
- RAS_Polygon* poly = m_Polygons[i];
- if (poly->IsVisible())
- {
- 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 0d06748f91f..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};
@@ -189,16 +201,14 @@ public:
);
void DebugColor(unsigned int abgr);
+ void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba);
/**
* Sorts the polygons by their transformed z values.
*/
void SortPolygons(const MT_Transform &transform);
- void SchedulePolygons(
- const MT_Transform &transform,
- int drawingmode
- );
+ void SchedulePolygons(int drawingmode);
void ClearArrayData();
@@ -215,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,