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:
authorAntony Riakiotakis <kalast@gmail.com>2014-07-10 01:09:10 +0400
committerAntony Riakiotakis <kalast@gmail.com>2014-07-10 01:09:10 +0400
commit4b5d02b7c4233d3e4129f4406aebe88dabf04d41 (patch)
tree9b7767b208e9d6c4ae746a028bd923a4e8ead3d8 /source/gameengine
parent53025e92604c8749332ad17d8b8b24f989923b0e (diff)
parent2788d5f38565695cd4beba6b062206d202d13f51 (diff)
Merge branch 'master' into soc-2013-paint
Conflicts: source/blender/blenkernel/BKE_blender.h source/blender/blenloader/intern/versioning_270.c source/blender/editors/sculpt_paint/paint_stroke.c source/blender/editors/transform/transform.h source/blender/makesdna/DNA_material_types.h
Diffstat (limited to 'source/gameengine')
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp4
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp45
-rw-r--r--source/gameengine/GameLogic/SCA_IActuator.h1
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp13
-rw-r--r--source/gameengine/GamePlayer/common/CMakeLists.txt2
-rw-r--r--source/gameengine/Ketsji/CMakeLists.txt2
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp34
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h4
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.cpp525
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.h127
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp15
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp1
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp17
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h2
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h2
16 files changed, 781 insertions, 15 deletions
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 0392280444d..e11bc84a0da 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -319,6 +319,10 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter)
}
}
}
+
+ // If we have constraints, make sure we get treated as an "animated" object
+ if (m_constraintNumber > 0)
+ GetActionManager();
}
BL_ArmatureConstraint* BL_ArmatureObject::GetConstraint(const char* posechannel, const char* constraintname)
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 7d5527d4cbb..45fc11b97d2 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -70,6 +70,7 @@
#include "KX_ParentActuator.h"
#include "KX_SCA_DynamicActuator.h"
#include "KX_SteeringActuator.h"
+#include "KX_MouseActuator.h"
#include "KX_Scene.h"
#include "KX_KetsjiEngine.h"
@@ -1094,6 +1095,50 @@ void BL_ConvertActuators(const char* maggiename,
baseact = tmpstact;
break;
}
+ case ACT_MOUSE:
+ {
+ bMouseActuator* mouAct = (bMouseActuator*) bact->data;
+ int mode = KX_MouseActuator::KX_ACT_MOUSE_NODEF;
+
+ switch (mouAct->type) {
+ case ACT_MOUSE_VISIBILITY:
+ {
+ mode = KX_MouseActuator::KX_ACT_MOUSE_VISIBILITY;
+ break;
+ }
+ case ACT_MOUSE_LOOK:
+ {
+ mode = KX_MouseActuator::KX_ACT_MOUSE_LOOK;
+ break;
+ }
+ }
+
+ bool visible = (mouAct->flag & ACT_MOUSE_VISIBLE) != 0;
+ bool use_axis[2] = {(mouAct->flag & ACT_MOUSE_USE_AXIS_X) != 0, (mouAct->flag & ACT_MOUSE_USE_AXIS_Y) != 0};
+ bool reset[2] = {(mouAct->flag & ACT_MOUSE_RESET_X) != 0, (mouAct->flag & ACT_MOUSE_RESET_Y) != 0};
+ bool local[2] = {(mouAct->flag & ACT_MOUSE_LOCAL_X) != 0, (mouAct->flag & ACT_MOUSE_LOCAL_Y) != 0};
+
+ SCA_MouseManager* eventmgr = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR);
+ if (eventmgr) {
+ KX_MouseActuator* tmpbaseact = new KX_MouseActuator(gameobj,
+ ketsjiEngine,
+ eventmgr,
+ mode,
+ visible,
+ use_axis,
+ mouAct->threshold,
+ reset,
+ mouAct->object_axis,
+ local,
+ mouAct->sensitivity,
+ mouAct->limit_x,
+ mouAct->limit_y);
+ baseact = tmpbaseact;
+ } else {
+ //cout << "\n Couldn't find mouse event manager..."; - should throw an error here...
+ }
+ break;
+ }
default:
; /* generate some error */
}
diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h
index aed49bc1822..8c22fb39c80 100644
--- a/source/gameengine/GameLogic/SCA_IActuator.h
+++ b/source/gameengine/GameLogic/SCA_IActuator.h
@@ -89,6 +89,7 @@ public:
KX_ACT_STATE,
KX_ACT_ARMATURE,
KX_ACT_STEERING,
+ KX_ACT_MOUSE,
};
SCA_IActuator(SCA_IObject* gameobj, KX_ACTUATOR_TYPE type);
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index 3a9e8ff0bbc..8c3ce38276e 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -263,7 +263,18 @@ PyAttributeDef SCA_PythonController::Attributes[] = {
void SCA_PythonController::ErrorPrint(const char *error_msg)
{
- printf("%s - object '%s', controller '%s':\n", error_msg, GetParent()->GetName().Ptr(), GetName().Ptr());
+ // If GetParent() is NULL, then most likely the object this controller
+ // was attached to is gone (e.g., removed by LibFree()). Also, GetName()
+ // can be a bad pointer if GetParent() is NULL, so better be safe and
+ // flag it as unavailable as well
+ const char *obj_name, *ctr_name;
+ if (GetParent()) {
+ obj_name = GetParent()->GetName().ReadPtr();
+ ctr_name = GetName().ReadPtr();
+ } else {
+ obj_name = ctr_name = "Unavailable";
+ }
+ printf("%s - object '%s', controller '%s':\n", error_msg, obj_name, ctr_name);
PyErr_Print();
/* Added in 2.48a, the last_traceback can reference Objects for example, increasing
diff --git a/source/gameengine/GamePlayer/common/CMakeLists.txt b/source/gameengine/GamePlayer/common/CMakeLists.txt
index 2fc4df86332..fd73b4efb53 100644
--- a/source/gameengine/GamePlayer/common/CMakeLists.txt
+++ b/source/gameengine/GamePlayer/common/CMakeLists.txt
@@ -55,7 +55,7 @@ set(INC_SYS
../../../../intern/moto/include
${GLEW_INCLUDE_PATH}
${PYTHON_INCLUDE_DIRS}
- ${PNG_INCLUDE_DIR}
+ ${PNG_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
)
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index 09ef1677d7c..03d1524b310 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -91,6 +91,7 @@ set(SRC
KX_MaterialIpoController.cpp
KX_MeshProxy.cpp
KX_MotionState.cpp
+ KX_MouseActuator.cpp
KX_MouseFocusSensor.cpp
KX_NavMeshObject.cpp
KX_NearSensor.cpp
@@ -169,6 +170,7 @@ set(SRC
KX_MaterialIpoController.h
KX_MeshProxy.h
KX_MotionState.h
+ KX_MouseActuator.h
KX_MouseFocusSensor.h
KX_NavMeshObject.h
KX_NearSensor.h
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 9e8e58e9dfd..f61d08e7f71 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -928,6 +928,27 @@ KX_GameObject::SetVisible(
}
}
+bool KX_GameObject::GetCulled()
+{
+ // If we're set to not cull, double-check with
+ // the mesh slots first. This is kind of nasty, but
+ // it allows us to get proper culling information.
+ if (!m_bCulled)
+ {
+ SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
+ for (mit.begin(); !mit.end(); ++mit)
+ {
+ if ((*mit)->m_bCulled)
+ {
+ m_bCulled = true;
+ break;
+ }
+ }
+ }
+
+ return m_bCulled;
+}
+
static void setOccluder_recursive(SG_Node* node, bool v)
{
NodeList& children = node->GetSGChildren();
@@ -2167,9 +2188,15 @@ int KX_GameObject::pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIB
return PY_SET_ATTR_FAIL;
}
- Py_XDECREF(self->m_collisionCallbacks);
+ if (self->m_collisionCallbacks == NULL) {
+ self->RegisterCollisionCallbacks();
+ } else {
+ Py_DECREF(self->m_collisionCallbacks);
+ }
+
Py_INCREF(value);
+
self->m_collisionCallbacks = value;
return PY_SET_ATTR_SUCCESS;
@@ -3007,19 +3034,20 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args)
{
PyObject *pyattach;
PyObject *pyimpulse;
+ int local = 0;
if (!m_pPhysicsController) {
PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
return NULL;
}
- if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse))
+ if (PyArg_ParseTuple(args, "OO|i:applyImpulse", &pyattach, &pyimpulse, &local))
{
MT_Point3 attach;
MT_Vector3 impulse;
if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
{
- m_pPhysicsController->ApplyImpulse(attach, impulse);
+ m_pPhysicsController->ApplyImpulse(attach, impulse, (local!=0));
Py_RETURN_NONE;
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 7450be4fdef..f7f40acb8f1 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -852,10 +852,10 @@ public:
/**
* Was this object culled?
*/
- inline bool
+ bool
GetCulled(
void
- ) { return m_bCulled; }
+ );
/**
* Set culled flag of this object
diff --git a/source/gameengine/Ketsji/KX_MouseActuator.cpp b/source/gameengine/Ketsji/KX_MouseActuator.cpp
new file mode 100644
index 00000000000..3d74bd7c98a
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp
@@ -0,0 +1,525 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Geoffrey Gollmer, Jorge Bernal
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "KX_MouseActuator.h"
+#include "KX_KetsjiEngine.h"
+#include "SCA_MouseManager.h"
+#include "SCA_IInputDevice.h"
+#include "RAS_ICanvas.h"
+#include "KX_GameObject.h"
+#include "MT_Vector3.h"
+#include "MT_Scalar.h"
+#include "MT_assert.h"
+#include "limits.h"
+
+#include "BLI_math.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+KX_MouseActuator::KX_MouseActuator(
+ SCA_IObject* gameobj,
+
+ KX_KetsjiEngine* ketsjiEngine,
+ SCA_MouseManager* eventmgr,
+ int acttype,
+ bool visible,
+ bool* use_axis,
+ float* threshold,
+ bool* reset,
+ int* object_axis,
+ bool* local,
+ float* sensitivity,
+ float* limit_x,
+ float* limit_y
+):
+ SCA_IActuator(gameobj, KX_ACT_MOUSE),
+ m_ketsji(ketsjiEngine),
+ m_eventmgr(eventmgr),
+ m_type(acttype),
+ m_visible(visible),
+ m_use_axis_x(use_axis[0]),
+ m_use_axis_y(use_axis[1]),
+ m_reset_x(reset[0]),
+ m_reset_y(reset[1]),
+ m_local_x(local[0]),
+ m_local_y(local[1])
+{
+ m_canvas = m_ketsji->GetCanvas();
+ m_oldposition[0] = m_oldposition[1] = -1.f;
+ m_limit_x[0] = limit_x[0];
+ m_limit_x[1] = limit_x[1];
+ m_limit_y[0] = limit_y[0];
+ m_limit_y[1] = limit_y[1];
+ m_threshold[0] = threshold[0];
+ m_threshold[1] = threshold[1];
+ m_object_axis[0] = object_axis[0];
+ m_object_axis[1] = object_axis[1];
+ m_sensitivity[0] = sensitivity[0];
+ m_sensitivity[1] = sensitivity[1];
+ m_angle[0] = 0.f;
+ m_angle[1] = 0.f;
+}
+
+KX_MouseActuator::~KX_MouseActuator()
+{
+}
+
+bool KX_MouseActuator::Update()
+{
+ bool result = false;
+
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+
+ KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent());
+
+ m_mouse = ((SCA_MouseManager *)m_eventmgr)->GetInputDevice();
+
+ switch (m_type) {
+ case KX_ACT_MOUSE_VISIBILITY:
+ {
+ if (m_visible) {
+ if (m_canvas) {
+ m_canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
+ }
+ }
+ else {
+ if (m_canvas) {
+ m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
+ }
+ }
+ break;
+ }
+ case KX_ACT_MOUSE_LOOK:
+ {
+ if (m_mouse) {
+
+ float position[2];
+ float movement[2];
+ MT_Vector3 rotation;
+ float setposition[2] = {0.0};
+
+ getMousePosition(position);
+
+ movement[0] = position[0];
+ movement[1] = position[1];
+
+ //preventing initial skipping.
+ if ((m_oldposition[0] <= -0.9) && (m_oldposition[1] <= -0.9)) {
+
+ if (m_reset_x) {
+ m_oldposition[0] = 0.5;
+ }
+ else {
+ m_oldposition[0] = position[0];
+ }
+
+ if (m_reset_y) {
+ m_oldposition[1] = 0.5;
+ }
+ else {
+ m_oldposition[1] = position[1];
+ }
+ setMousePosition(m_oldposition[0], m_oldposition[1]);
+ break;
+ }
+
+ //Calculating X axis.
+ if (m_use_axis_x) {
+
+ if (m_reset_x) {
+ setposition[0] = 0.5;
+ movement[0] -= 0.5;
+ }
+ else {
+ setposition[0] = position[0];
+ movement[0] -= m_oldposition[0];
+ }
+
+ movement[0] *= -1.0;
+
+ /* Don't apply the rotation when width resolution is odd (+ little movement) to
+ avoid undesired drifting or when we are under a certain threshold for mouse
+ movement */
+
+ if (!((m_canvas->GetWidth() % 2 != 0) && MT_abs(movement[0]) < 0.01) &&
+ ((movement[0] > (m_threshold[0] / 10.0)) ||
+ ((movement[0] * (-1.0)) > (m_threshold[0] / 10.0)))) {
+
+ movement[0] *= m_sensitivity[0];
+
+ if ((m_limit_x[0] != 0.0) && ((m_angle[0] + movement[0]) <= m_limit_x[0])) {
+ movement[0] = m_limit_x[0] - m_angle[0];
+ }
+
+ if ((m_limit_x[1] != 0.0) && ((m_angle[0] + movement[0]) >= m_limit_x[1])) {
+ movement[0] = m_limit_x[1] - m_angle[0];
+ }
+
+ m_angle[0] += movement[0];
+
+ switch (m_object_axis[0]) {
+ case KX_ACT_MOUSE_OBJECT_AXIS_X:
+ {
+ rotation = MT_Vector3(movement[0], 0.0, 0.0);
+ break;
+ }
+ case KX_ACT_MOUSE_OBJECT_AXIS_Y:
+ {
+ rotation = MT_Vector3(0.0, movement[0], 0.0);
+ break;
+ }
+ case KX_ACT_MOUSE_OBJECT_AXIS_Z:
+ {
+ rotation = MT_Vector3(0.0, 0.0, movement[0]);
+ break;
+ }
+ default:
+ break;
+ }
+ parent->ApplyRotation(rotation, m_local_x);
+ }
+ }
+
+ //Calculating Y axis.
+ if (m_use_axis_y) {
+
+ if (m_reset_y) {
+ setposition[1] = 0.5;
+ movement[1] -= 0.5;
+ }
+ else {
+ setposition[1] = position[1];
+ movement[1] -= m_oldposition[1];
+ }
+
+ movement[1] *= -1.0;
+
+ /* Don't apply the rotation when height resolution is odd (+ little movement) to
+ avoid undesired drifting or when we are under a certain threshold for mouse
+ movement */
+
+ if (!((m_canvas->GetHeight() % 2 != 0) && MT_abs(movement[1]) < 0.01) &&
+ ((movement[1] > (m_threshold[1] / 10.0)) ||
+ ((movement[1] * (-1.0)) > (m_threshold[1] / 10.0)))) {
+
+ movement[1] *= m_sensitivity[1];
+
+ if ((m_limit_y[0] != 0.0) && ((m_angle[1] + movement[1]) <= m_limit_y[0])) {
+ movement[1] = m_limit_y[0] - m_angle[1];
+ }
+
+ if ((m_limit_y[1] != 0.0) && ((m_angle[1] + movement[1]) >= m_limit_y[1])) {
+ movement[1] = m_limit_y[1] - m_angle[1];
+ }
+
+ m_angle[1] += movement[1];
+
+ switch (m_object_axis[1])
+ {
+ case KX_ACT_MOUSE_OBJECT_AXIS_X:
+ {
+ rotation = MT_Vector3(movement[1], 0.0, 0.0);
+ break;
+ }
+ case KX_ACT_MOUSE_OBJECT_AXIS_Y:
+ {
+ rotation = MT_Vector3(0.0, movement[1], 0.0);
+ break;
+ }
+ case KX_ACT_MOUSE_OBJECT_AXIS_Z:
+ {
+ rotation = MT_Vector3(0.0, 0.0, movement[1]);
+ break;
+ }
+ default:
+ break;
+ }
+ parent->ApplyRotation(rotation, m_local_y);
+ }
+ }
+
+ setMousePosition(setposition[0], setposition[1]);
+
+ m_oldposition[0] = position[0];
+ m_oldposition[1] = position[1];
+
+ }
+ else {
+ //printf("\nNo input device detected for mouse actuator\n");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return result;
+}
+
+bool KX_MouseActuator::isValid(KX_MouseActuator::KX_ACT_MOUSE_MODE mode)
+{
+ return ((mode > KX_ACT_MOUSE_NODEF) && (mode < KX_ACT_MOUSE_MAX));
+}
+
+
+CValue* KX_MouseActuator::GetReplica()
+{
+ KX_MouseActuator* replica = new KX_MouseActuator(*this);
+
+ replica->ProcessReplica();
+ return replica;
+}
+
+void KX_MouseActuator::ProcessReplica()
+{
+ SCA_IActuator::ProcessReplica();
+}
+
+void KX_MouseActuator::getMousePosition(float* pos)
+{
+ MT_assert(!m_mouse);
+ const SCA_InputEvent & xevent = m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEX);
+ const SCA_InputEvent & yevent = m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEY);
+
+ pos[0] = m_canvas->GetMouseNormalizedX(xevent.m_eventval);
+ pos[1] = m_canvas->GetMouseNormalizedY(yevent.m_eventval);
+}
+
+void KX_MouseActuator::setMousePosition(float fx, float fy)
+{
+ int x, y;
+
+ x = (int)(fx * m_canvas->GetWidth());
+ y = (int)(fy * m_canvas->GetHeight());
+
+ m_canvas->SetMousePosition(x, y);
+}
+
+#ifndef DISABLE_PYTHON
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject KX_MouseActuator::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "KX_MouseActuator",
+ sizeof(PyObjectPlus_Proxy),
+ 0,
+ py_base_dealloc,
+ 0,
+ 0,
+ 0,
+ 0,
+ py_base_repr,
+ 0,0,0,0,0,0,0,0,0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ 0,0,0,0,0,0,0,
+ Methods,
+ 0,
+ 0,
+ &SCA_IActuator::Type,
+ 0,0,0,0,0,0,
+ py_base_new
+};
+
+PyMethodDef KX_MouseActuator::Methods[] = {
+ {"reset", (PyCFunction) KX_MouseActuator::sPyReset, METH_NOARGS,"reset() : undo rotation caused by actuator\n"},
+ {NULL,NULL} //Sentinel
+};
+
+
+
+PyAttributeDef KX_MouseActuator::Attributes[] = {
+ KX_PYATTRIBUTE_BOOL_RW("visible", KX_MouseActuator, m_visible),
+ KX_PYATTRIBUTE_BOOL_RW("use_axis_x", KX_MouseActuator, m_use_axis_x),
+ KX_PYATTRIBUTE_BOOL_RW("use_axis_y", KX_MouseActuator, m_use_axis_y),
+ KX_PYATTRIBUTE_FLOAT_ARRAY_RW("threshold", 0.0, 0.5, KX_MouseActuator, m_threshold, 2),
+ KX_PYATTRIBUTE_BOOL_RW("reset_x", KX_MouseActuator, m_reset_x),
+ KX_PYATTRIBUTE_BOOL_RW("reset_y", KX_MouseActuator, m_reset_y),
+ KX_PYATTRIBUTE_INT_ARRAY_RW("object_axis", 0, 2, 1, KX_MouseActuator, m_object_axis, 2),
+ KX_PYATTRIBUTE_BOOL_RW("local_x", KX_MouseActuator, m_local_x),
+ KX_PYATTRIBUTE_BOOL_RW("local_y", KX_MouseActuator, m_local_y),
+ KX_PYATTRIBUTE_FLOAT_ARRAY_RW("sensitivity", -FLT_MAX, FLT_MAX, KX_MouseActuator, m_sensitivity, 2),
+ KX_PYATTRIBUTE_RW_FUNCTION("limit_x", KX_MouseActuator, pyattr_get_limit_x, pyattr_set_limit_x),
+ KX_PYATTRIBUTE_RW_FUNCTION("limit_y", KX_MouseActuator, pyattr_get_limit_y, pyattr_set_limit_y),
+ KX_PYATTRIBUTE_RW_FUNCTION("angle", KX_MouseActuator, pyattr_get_angle, pyattr_set_angle),
+ { NULL } //Sentinel
+};
+
+PyObject* KX_MouseActuator::pyattr_get_limit_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_MouseActuator* self= static_cast<KX_MouseActuator*>(self_v);
+ return Py_BuildValue("[f,f]", (self->m_limit_x[0] / M_PI * 180.0), (self->m_limit_x[1] / M_PI * 180.0));
+}
+
+int KX_MouseActuator::pyattr_set_limit_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ PyObject *item1, *item2;
+ KX_MouseActuator* self= static_cast<KX_MouseActuator*>(self_v);
+
+ if (!PyList_Check(value))
+ return PY_SET_ATTR_FAIL;
+
+ if (PyList_Size(value) != 2)
+ return PY_SET_ATTR_FAIL;
+
+ item1 = PyList_GetItem(value, 0);
+ item2 = PyList_GetItem(value, 1);
+
+ if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
+ return PY_SET_ATTR_FAIL;
+ }
+ else {
+ self->m_limit_x[0] = (PyFloat_AsDouble(item1) * M_PI / 180.0);
+ self->m_limit_x[1] = (PyFloat_AsDouble(item2) * M_PI / 180.0);
+ }
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* KX_MouseActuator::pyattr_get_limit_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_MouseActuator* self= static_cast<KX_MouseActuator*>(self_v);
+ return Py_BuildValue("[f,f]", (self->m_limit_y[0] / M_PI * 180.0), (self->m_limit_y[1] / M_PI * 180.0));
+}
+
+int KX_MouseActuator::pyattr_set_limit_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ PyObject *item1, *item2;
+ KX_MouseActuator* self= static_cast<KX_MouseActuator*>(self_v);
+
+ if (!PyList_Check(value))
+ return PY_SET_ATTR_FAIL;
+
+ if (PyList_Size(value) != 2)
+ return PY_SET_ATTR_FAIL;
+
+ item1 = PyList_GetItem(value, 0);
+ item2 = PyList_GetItem(value, 1);
+
+ if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
+ return PY_SET_ATTR_FAIL;
+ }
+ else {
+ self->m_limit_y[0] = (PyFloat_AsDouble(item1) * M_PI / 180.0);
+ self->m_limit_y[1] = (PyFloat_AsDouble(item2) * M_PI / 180.0);
+ }
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* KX_MouseActuator::pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_MouseActuator* self= static_cast<KX_MouseActuator*>(self_v);
+ return Py_BuildValue("[f,f]", (self->m_angle[0] / M_PI * 180.0), (self->m_angle[1] / M_PI * 180.0));
+}
+
+int KX_MouseActuator::pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ PyObject *item1, *item2;
+ KX_MouseActuator* self= static_cast<KX_MouseActuator*>(self_v);
+
+ if (!PyList_Check(value))
+ return PY_SET_ATTR_FAIL;
+
+ if (PyList_Size(value) != 2)
+ return PY_SET_ATTR_FAIL;
+
+ item1 = PyList_GetItem(value, 0);
+ item2 = PyList_GetItem(value, 1);
+
+ if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
+ return PY_SET_ATTR_FAIL;
+ }
+ else {
+ self->m_angle[0] = (PyFloat_AsDouble(item1) * M_PI / 180.0);
+ self->m_angle[1] = (PyFloat_AsDouble(item2) * M_PI / 180.0);
+ }
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* KX_MouseActuator::PyReset()
+{
+ MT_Vector3 rotation;
+ KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent());
+
+ switch (m_object_axis[0]) {
+ case KX_ACT_MOUSE_OBJECT_AXIS_X:
+ {
+ rotation = MT_Vector3(-1.0 * m_angle[0], 0.0, 0.0);
+ break;
+ }
+ case KX_ACT_MOUSE_OBJECT_AXIS_Y:
+ {
+ rotation = MT_Vector3(0.0, -1.0 * m_angle[0], 0.0);
+ break;
+ }
+ case KX_ACT_MOUSE_OBJECT_AXIS_Z:
+ {
+ rotation = MT_Vector3(0.0, 0.0, -1.0 * m_angle[0]);
+ break;
+ }
+ default:
+ break;
+ }
+ parent->ApplyRotation(rotation, m_local_x);
+
+ switch (m_object_axis[1]) {
+ case KX_ACT_MOUSE_OBJECT_AXIS_X:
+ {
+ rotation = MT_Vector3(-1.0 * m_angle[1], 0.0, 0.0);
+ break;
+ }
+ case KX_ACT_MOUSE_OBJECT_AXIS_Y:
+ {
+ rotation = MT_Vector3(0.0, -1.0 * m_angle[1], 0.0);
+ break;
+ }
+ case KX_ACT_MOUSE_OBJECT_AXIS_Z:
+ {
+ rotation = MT_Vector3(0.0, 0.0, -1.0 * m_angle[1]);
+ break;
+ }
+ default:
+ break;
+ }
+ parent->ApplyRotation(rotation, m_local_y);
+
+ m_angle[0] = 0.0;
+ m_angle[1] = 0.0;
+
+ Py_RETURN_NONE;
+}
+
+#endif
diff --git a/source/gameengine/Ketsji/KX_MouseActuator.h b/source/gameengine/Ketsji/KX_MouseActuator.h
new file mode 100644
index 00000000000..bf90bd21dac
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_MouseActuator.h
@@ -0,0 +1,127 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Geoffrey Gollmer, Jorge Bernal
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __KX_MOUSEACTUATOR
+#define __KX_MOUSEACTUATOR
+
+#include "SCA_IActuator.h"
+
+class KX_KetsjiEngine;
+class SCA_MouseManager;
+class SCA_IInputDevice;
+class RAS_ICanvas;
+
+class KX_MouseActuator : public SCA_IActuator
+{
+ Py_Header
+
+private:
+
+ KX_KetsjiEngine* m_ketsji;
+ SCA_MouseManager* m_eventmgr;
+ SCA_IInputDevice* m_mouse;
+ RAS_ICanvas* m_canvas;
+ int m_type;
+
+ bool m_visible;
+
+ bool m_use_axis_x; /* 0 for calculate axis, 1 for ignore axis */
+ bool m_use_axis_y;
+ float m_threshold[2];
+ bool m_reset_x; /* 0=reset, 1=free */
+ bool m_reset_y;
+ int m_object_axis[2]; /* 0=x, 1=y, 2=z */
+ bool m_local_x; /* 0=local, 1=global*/
+ bool m_local_y;
+ float m_sensitivity[2];
+ float m_limit_x[2];
+ float m_limit_y[2];
+
+ float m_oldposition[2];
+ float m_angle[2];
+
+public:
+
+ enum KX_ACT_MOUSE_OBJECT_AXIS {
+ KX_ACT_MOUSE_OBJECT_AXIS_X = 0,
+ KX_ACT_MOUSE_OBJECT_AXIS_Y,
+ KX_ACT_MOUSE_OBJECT_AXIS_Z
+ };
+
+ enum KX_ACT_MOUSE_MODE {
+ KX_ACT_MOUSE_NODEF = 0,
+ KX_ACT_MOUSE_VISIBILITY,
+ KX_ACT_MOUSE_LOOK,
+ KX_ACT_MOUSE_MAX
+ };
+
+ KX_MouseActuator(
+ SCA_IObject* gameobj,
+ KX_KetsjiEngine* ketsjiEngine,
+ SCA_MouseManager* eventmgr,
+ int acttype,
+ bool visible,
+ bool* use_axis,
+ float* threshold,
+ bool* reset,
+ int* object_axis,
+ bool* local,
+ float* sensitivity,
+ float* limit_x,
+ float* limit_y
+ );
+
+
+ ~KX_MouseActuator();
+
+ CValue* GetReplica();
+ virtual void ProcessReplica();
+
+ virtual bool Update();
+
+ /* check whether this value is valid */
+ bool isValid(KX_ACT_MOUSE_MODE mode);
+
+ virtual void getMousePosition(float*);
+ virtual void setMousePosition(float, float);
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ /* Methods */
+
+ KX_PYMETHOD_DOC_NOARGS(KX_MouseActuator,Reset);
+
+ /* Attributes */
+
+ static PyObject* pyattr_get_limit_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_limit_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
+ static PyObject* pyattr_get_limit_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_limit_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
+ static PyObject* pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+};
+
+#endif //__KX_MOUSEACTUATOR_DOC
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 913851bcc3f..56b7631e7f1 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -87,6 +87,7 @@ extern "C" {
#include "KX_SCA_DynamicActuator.h"
#include "KX_SteeringActuator.h"
#include "KX_NavMeshObject.h"
+#include "KX_MouseActuator.h"
#include "SCA_IInputDevice.h"
#include "SCA_PropertySensor.h"
@@ -1820,6 +1821,12 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
KX_MACRO_addTypesToDict(d, KX_ACTION_BLEND_BLEND, BL_Action::ACT_BLEND_BLEND);
KX_MACRO_addTypesToDict(d, KX_ACTION_BLEND_ADD, BL_Action::ACT_BLEND_ADD);
+ /* Mouse Actuator object axis*/
+ KX_MACRO_addTypesToDict(d, KX_ACT_MOUSE_OBJECT_AXIS_X, KX_MouseActuator::KX_ACT_MOUSE_OBJECT_AXIS_X);
+ KX_MACRO_addTypesToDict(d, KX_ACT_MOUSE_OBJECT_AXIS_Y, KX_MouseActuator::KX_ACT_MOUSE_OBJECT_AXIS_Y);
+ KX_MACRO_addTypesToDict(d, KX_ACT_MOUSE_OBJECT_AXIS_Z, KX_MouseActuator::KX_ACT_MOUSE_OBJECT_AXIS_Z);
+
+
// Check for errors
if (PyErr_Occurred())
{
@@ -1951,10 +1958,10 @@ void removeImportMain(struct Main *maggie)
// Copied from bpy_interface.c
static struct _inittab bge_internal_modules[] = {
- {(char *)"mathutils", PyInit_mathutils},
- {(char *)"bgl", BPyInit_bgl},
- {(char *)"blf", BPyInit_blf},
- {(char *)"aud", AUD_initPython},
+ {"mathutils", PyInit_mathutils},
+ {"bgl", BPyInit_bgl},
+ {"blf", BPyInit_blf},
+ {"aud", AUD_initPython},
{NULL, NULL}
};
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
index bacace9199a..7d38ce58eee 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
@@ -97,6 +97,7 @@
#include "SCA_RandomActuator.h"
#include "SCA_IController.h"
#include "KX_NavMeshObject.h"
+#include "KX_MouseActuator.h"
static void PyType_Attr_Set(PyGetSetDef *attr_getset, PyAttributeDef *attr)
{
@@ -227,6 +228,7 @@ void initPyTypes(void)
PyType_Ready_Attr(dict, KX_VehicleWrapper, init_getset);
PyType_Ready_Attr(dict, KX_VertexProxy, init_getset);
PyType_Ready_Attr(dict, KX_VisibilityActuator, init_getset);
+ PyType_Ready_Attr(dict, KX_MouseActuator, init_getset);
PyType_Ready_Attr(dict, PyObjectPlus, init_getset);
PyType_Ready_Attr(dict, SCA_2DFilterActuator, init_getset);
PyType_Ready_Attr(dict, SCA_ANDController, init_getset);
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 0dfdb3d5f3b..3d71327828e 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -1038,6 +1038,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
!(itc==controllers.end());itc++)
{
m_logicmgr->RemoveController(*itc);
+ (*itc)->ReParent(NULL);
}
SCA_ActuatorList& actuators = newobj->GetActuators();
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index c98cf212265..72c3b13e301 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -1309,8 +1309,9 @@ void CcdPhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool loc
}
}
}
-void CcdPhysicsController::ApplyImpulse(const MT_Point3& attach, const MT_Vector3& impulsein)
+void CcdPhysicsController::ApplyImpulse(const MT_Point3& attach, const MT_Vector3& impulsein, bool local)
{
+ btVector3 pos;
btVector3 impulse(impulsein.x(), impulsein.y(), impulsein.z());
if (m_object && impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON))
@@ -1323,7 +1324,19 @@ void CcdPhysicsController::ApplyImpulse(const MT_Point3& attach, const MT_Vecto
return;
}
- btVector3 pos(attach.x(), attach.y(), attach.z());
+ btTransform xform = m_object->getWorldTransform();
+
+ if (local)
+ {
+ pos = btVector3(attach.x(), attach.y(), attach.z());
+ impulse = xform.getBasis() * impulse;
+ }
+ else {
+ /* If the point of impulse application is not equal to the object position
+ * then an angular momentum is generated in the object*/
+ pos = btVector3(attach.x()-xform.getOrigin().x(), attach.y()-xform.getOrigin().y(), attach.z()-xform.getOrigin().z());
+ }
+
btRigidBody* body = GetRigidBody();
if (body)
body->applyImpulse(impulse,pos);
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 25a8f0306bd..4d0d96e07c6 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -565,7 +565,7 @@ protected:
virtual void SetMass(MT_Scalar newmass);
// physics methods
- virtual void ApplyImpulse(const MT_Point3& attach, const MT_Vector3& impulsein);
+ virtual void ApplyImpulse(const MT_Point3& attach, const MT_Vector3& impulsein, bool local);
virtual void ApplyTorque(const MT_Vector3& torque,bool local);
virtual void ApplyForce(const MT_Vector3& force,bool local);
virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local);
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index 2ffb115e3b2..f9975484fa7 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -82,7 +82,7 @@ class PHY_IPhysicsController : public PHY_IController
virtual void SetMass(MT_Scalar newmass)=0;
// physics methods
- virtual void ApplyImpulse(const MT_Point3& attach, const MT_Vector3& impulse)=0;
+ virtual void ApplyImpulse(const MT_Point3& attach, const MT_Vector3& impulse,bool local)=0;
virtual void ApplyTorque(const MT_Vector3& torque,bool local)=0;
virtual void ApplyForce(const MT_Vector3& force,bool local)=0;
virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local)=0;