Merging r59136 through r59152 from trunk into soc-2013-depsgraph_mt
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 15 Aug 2013 08:23:16 +0000 (08:23 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 15 Aug 2013 08:23:16 +0000 (08:23 +0000)
39 files changed:
doc/python_api/rst/bge.logic.rst
doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
intern/audaspace/OpenAL/AUD_OpenALDevice.h
intern/audaspace/Python/AUD_PyAPI.cpp
intern/audaspace/intern/AUD_IHandle.h
intern/audaspace/intern/AUD_SoftwareDevice.cpp
intern/audaspace/intern/AUD_SoftwareDevice.h
intern/audaspace/intern/AUD_Space.h
intern/cycles/kernel/kernel_shader.h
intern/guardedalloc/intern/mallocn.c
release/scripts/modules/bpy_extras/image_utils.py
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/space_logic/logic_window.c
source/blender/editors/space_outliner/outliner_edit.c
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesrna/intern/rna_ID.c
source/blender/makesrna/intern/rna_actuator.c
source/blender/makesrna/intern/rna_curve.c
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_ActionActuator.h
source/gameengine/Converter/BL_ArmatureObject.cpp
source/gameengine/Converter/BL_ArmatureObject.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Ketsji/BL_Action.cpp
source/gameengine/Ketsji/BL_Action.h
source/gameengine/Ketsji/BL_ActionManager.cpp
source/gameengine/Ketsji/BL_ActionManager.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_SoundActuator.cpp

index c7915ee5279d60f5a0d42f096513c571f6d6ca5d..3a79d32d91799bcb2f231e44277d5263fa61bc37 100644 (file)
@@ -1114,6 +1114,19 @@ See :class:`bge.types.KX_GameObject.playAction`
    
    :value: 2
 
+.. _gameobject-playaction-blend:
+
+.. data:: KX_ACTION_BLEND_BLEND
+
+   Blend layers using linear interpolation
+
+   :value: 0
+
+.. data:: KX_ACTION_BLEND_ADD
+
+   Adds the layers together
+
+   :value: 1
 
 -------------
 Mouse Buttons
index a9c91735f917bd6a10e3ab4a7a9c955abc459968..3be148556ef36e97231b7f5d855ecb664aa7afab 100644 (file)
@@ -776,7 +776,7 @@ base class --- :class:`SCA_IObject`
       Return the value matching key, or the default value if its not found.
       :return: The key value or a default.
 
-   .. method:: playAction(name, start_frame, end_frame, layer=0, priority=0, blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0)
+   .. method:: playAction(name, start_frame, end_frame, layer=0, priority=0, blendin=0, play_mode=KX_ACTION_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0, blend_mode=KX_ACTION_BLEND_BLEND)
 
       Plays an action.
       
@@ -794,12 +794,14 @@ base class --- :class:`SCA_IObject`
       :type blendin: float
       :arg play_mode: the play mode
       :type play_mode: one of :ref:`these constants <gameobject-playaction-mode>`
-      :arg layer_weight: how much of the previous layer to use for blending (0 = add)
+      :arg layer_weight: how much of the previous layer to use for blending
       :type layer_weight: float
       :arg ipo_flags: flags for the old IPO behaviors (force, etc)
       :type ipo_flags: int bitfield
       :arg speed: the playback speed of the action as a factor (1.0 = normal speed, 2.0 = 2x speed, etc)
       :type speed: float
+         :arg blend_mode: how to blend this layer with previous layers
+         :type blend_mode: one of :ref:`these constants <gameobject-playaction-blend>`
 
    .. method:: stopAction(layer=0)
       
index 371e0007bd31303e1768768a34e29d429beb3b77..676a86e88fe21f7128b58dd04425abf9ec8ae29f 100644 (file)
@@ -67,6 +67,35 @@ static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
 static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
                                                                          "filled with data.";
 
+bool AUD_OpenALDevice::AUD_OpenALHandle::pause(bool keep)
+{
+       if(m_status)
+       {
+               AUD_MutexLock lock(*m_device);
+
+               if(m_status == AUD_STATUS_PLAYING)
+               {
+                       for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
+                       {
+                               if(it->get() == this)
+                               {
+                                       boost::shared_ptr<AUD_OpenALHandle> This = *it;
+
+                                       m_device->m_playingSounds.erase(it);
+                                       m_device->m_pausedSounds.push_back(This);
+
+                                       alSourcePause(m_source);
+
+                                       m_status = keep ? AUD_STATUS_STOPPED : AUD_STATUS_PAUSED;
+
+                                       return true;
+                               }
+                       }
+               }
+       }
+
+       return false;}
+
 AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr<AUD_IReader> reader, bool keep) :
        m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0),
        m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING),
@@ -124,32 +153,7 @@ AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, A
 
 bool AUD_OpenALDevice::AUD_OpenALHandle::pause()
 {
-       if(m_status)
-       {
-               AUD_MutexLock lock(*m_device);
-
-               if(m_status == AUD_STATUS_PLAYING)
-               {
-                       for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
-                       {
-                               if(it->get() == this)
-                               {
-                                       boost::shared_ptr<AUD_OpenALHandle> This = *it;
-
-                                       m_device->m_playingSounds.erase(it);
-                                       m_device->m_pausedSounds.push_back(This);
-
-                                       alSourcePause(m_source);
-
-                                       m_status = AUD_STATUS_PAUSED;
-
-                                       return true;
-                               }
-                       }
-               }
-       }
-
-       return false;
+       return pause(false);
 }
 
 bool AUD_OpenALDevice::AUD_OpenALHandle::resume()
@@ -302,6 +306,9 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
                }
        }
 
+       if(m_status == AUD_STATUS_STOPPED)
+               m_status = AUD_STATUS_PAUSED;
+
        return true;
 }
 
@@ -409,7 +416,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count)
 {
        if(!m_status)
                return false;
+
+       if(m_status == AUD_STATUS_STOPPED && (count > m_loopcount || count < 0))
+               m_status = AUD_STATUS_PAUSED;
+
        m_loopcount = count;
+
        return true;
 }
 
@@ -987,7 +999,7 @@ void AUD_OpenALDevice::updateStreams()
                        }
 
                        for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
-                               (*it)->pause();
+                               (*it)->pause(true);
 
                        for(it = stopSounds.begin(); it != stopSounds.end(); it++)
                                (*it)->stop();
index d2a4be227bafd5d365bb669f4082432a57bf1cb8..f0e478249671dd2eb9ec7a2cd64a33d0cb4d3cf1 100644 (file)
@@ -96,6 +96,8 @@ private:
                /// Own device.
                AUD_OpenALDevice* m_device;
 
+               bool pause(bool keep);
+
        public:
 
                /**
index 9beba2eb0a0d6eea9085646496c25b34693e826e..b00289b3fae80de4e98a6e3e53922c72eea3df8e 100644 (file)
@@ -2908,6 +2908,7 @@ PyInit_aud(void)
        PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
        PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
        PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
+       PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_STOPPED);
        // distance model constants
        PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
        PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
index 9dcb743693e58eb295cf01aeb52cba8d16a649e1..c80fb4027b80528c6127eebc5d3f0cc858c42aa1 100644 (file)
@@ -113,6 +113,8 @@ public:
         *.         invalid
         *        - AUD_STATUS_PLAYING if the sound is currently played back.
         *        - AUD_STATUS_PAUSED if the sound is currently paused.
+        *        - AUD_STATUS_STOPPED if the sound finished playing and is still
+        *          kept in the device.
         * \see AUD_Status
         */
        virtual AUD_Status getStatus()=0;
index a7e5b25664bfc4bc78f1d9a32a11cf60ed858874..7bf59cd6f31a1beb261e7e39630c7da40868859e 100644 (file)
@@ -57,6 +57,37 @@ typedef enum
 /********************** AUD_SoftwareHandle Handle Code ************************/
 /******************************************************************************/
 
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause(bool keep)
+{
+       if(m_status)
+       {
+               AUD_MutexLock lock(*m_device);
+
+               if(m_status == AUD_STATUS_PLAYING)
+               {
+                       for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
+                       {
+                               if(it->get() == this)
+                               {
+                                       boost::shared_ptr<AUD_SoftwareHandle> This = *it;
+
+                                       m_device->m_playingSounds.erase(it);
+                                       m_device->m_pausedSounds.push_back(This);
+
+                                       if(m_device->m_playingSounds.empty())
+                                               m_device->playing(m_device->m_playback = false);
+
+                                       m_status = keep ? AUD_STATUS_STOPPED : AUD_STATUS_PAUSED;
+
+                                       return true;
+                               }
+                       }
+               }
+       }
+
+       return false;
+}
+
 AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_PitchReader> pitch, boost::shared_ptr<AUD_ResampleReader> resampler, boost::shared_ptr<AUD_ChannelMapperReader> mapper, bool keep) :
        m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_loopcount(0),
        m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
@@ -225,33 +256,7 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::setSpecs(AUD_Specs specs)
 
 bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause()
 {
-       if(m_status)
-       {
-               AUD_MutexLock lock(*m_device);
-
-               if(m_status == AUD_STATUS_PLAYING)
-               {
-                       for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
-                       {
-                               if(it->get() == this)
-                               {
-                                       boost::shared_ptr<AUD_SoftwareHandle> This = *it;
-
-                                       m_device->m_playingSounds.erase(it);
-                                       m_device->m_pausedSounds.push_back(This);
-
-                                       if(m_device->m_playingSounds.empty())
-                                               m_device->playing(m_device->m_playback = false);
-
-                                       m_status = AUD_STATUS_PAUSED;
-
-                                       return true;
-                               }
-                       }
-               }
-       }
-
-       return false;
+       return pause(false);
 }
 
 bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume()
@@ -360,6 +365,9 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position)
 
        m_reader->seek((int)(position * m_reader->getSpecs().rate));
 
+       if(m_status == AUD_STATUS_STOPPED)
+               m_status = AUD_STATUS_PAUSED;
+
        return true;
 }
 
@@ -429,7 +437,12 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setLoopCount(int count)
 {
        if(!m_status)
                return false;
+
+       if(m_status == AUD_STATUS_STOPPED && (count > m_loopcount || count < 0))
+               m_status = AUD_STATUS_PAUSED;
+
        m_loopcount = count;
+
        return true;
 }
 
@@ -793,19 +806,14 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
                m_mixer->read(buffer, m_volume);
 
                // cleanup
-               while(!stopSounds.empty())
-               {
-                       sound = stopSounds.front();
-                       stopSounds.pop_front();
-                       sound->stop();
-               }
+               for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
+                       (*it)->pause(true);
 
-               while(!pauseSounds.empty())
-               {
-                       sound = pauseSounds.front();
-                       pauseSounds.pop_front();
-                       sound->pause();
-               }
+               for(it = stopSounds.begin(); it != stopSounds.end(); it++)
+                       (*it)->stop();
+
+               pauseSounds.clear();
+               stopSounds.clear();
        }
 }
 
index 8675a5ce2b890eeb7705a22833889245bc09b833..3c8c1e438a370aa24ea588cff81b5b70db722177 100644 (file)
@@ -139,6 +139,8 @@ protected:
                /// Own device.
                AUD_SoftwareDevice* m_device;
 
+               bool pause(bool keep);
+
        public:
 
                /**
index f42cb1ab018005776da11b235e983d269c7bb763..ec2c06900ace0a742dca0ba38d9dda73ce47ae67 100644 (file)
@@ -125,7 +125,8 @@ typedef enum
 {
        AUD_STATUS_INVALID = 0,                 /// Invalid handle. Maybe due to stopping.
        AUD_STATUS_PLAYING,                             /// Sound is playing.
-       AUD_STATUS_PAUSED                               /// Sound is being paused.
+       AUD_STATUS_PAUSED,                              /// Sound is being paused.
+       AUD_STATUS_STOPPED                              /// Sound is stopped but kept in the device.
 } AUD_Status;
 
 /// Error codes for exceptions (C++ library) or for return values (C API).
index d8ff662c505a0d80482958e1553a1be7b6ef3829..5dd12f98b9ce8a5be95af7fc554514e85fa996fc 100644 (file)
@@ -498,7 +498,7 @@ __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
 #ifdef __MULTI_CLOSURE__
        bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
 
-       return _shader_bsdf_multi_eval(kg, sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
+       _shader_bsdf_multi_eval(kg, sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
 #else
        const ShaderClosure *sc = &sd->closure;
 
@@ -720,7 +720,7 @@ __device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_facto
                        eval += sc->weight*ao_factor;
                        *N += sc->N*average(sc->weight);
                }
-               if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
+               else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
                        eval += sc->weight;
                        *N += sd->N*average(sc->weight);
                }
index 1d5ba91db9df3e0ee549efa6f9a3199e351dd2ce..520df7880554df5eab1d85115800ee897345c9f3 100644 (file)
@@ -1148,12 +1148,12 @@ void *MEM_dupallocN(const void *vmemh)
        return newp;
 }
 
-void *MEM_reallocN(void *vmemh, size_t len)
+void *MEM_reallocN_id(void *vmemh, size_t len, const char *UNUSED(str))
 {
        return realloc(vmemh, len);
 }
 
-void *MEM_recallocN(void *vmemh, size_t len)
+void *MEM_recallocN_id(void *vmemh, size_t len, const char *UNUSED(str))
 {
        void *newp = NULL;
 
index 551689c5a75c7708ceabfaa685867888887e045a..ff6d23badb6943972540944e71f7ce42ebc15bc3 100644 (file)
@@ -105,7 +105,15 @@ def load_image(imagepath,
             if relpath is not None:
                 # make relative
                 from bpy.path import relpath as relpath_fn
-                image.filepath_raw = relpath_fn(path, start=relpath)
+                # can't always find the relative path
+                # (between drive letters on windows)
+                try:
+                    filepath_rel = relpath_fn(path, start=relpath)
+                except ValueError:
+                    filepath_rel = None
+
+                if filepath_rel is not None:
+                    image.filepath_raw = filepath_rel
 
         return image
 
index 6e78cf681e136cf6e57ff2ceed2ad6f8a95327c5..1d48063e1439a8736130e2d797d8ec4e5269857d 100644 (file)
@@ -80,7 +80,8 @@ bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max
 bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
 bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
 void BKE_curve_translate(struct Curve *cu, float offset[3], int do_keys);
-void BKE_curve_delete_material_index(struct Curve *cu, int index);
+void BKE_curve_material_index_remove(struct Curve *cu, int index);
+void BKE_curve_material_index_clear(struct Curve *cu);
 
 ListBase *BKE_curve_nurbs_get(struct Curve *cu);
 
index 5d8406ba76f14771e4fae942a87ffed8f580406c..91c1715cca666b8c23a198b9a07a40f1efd54860 100644 (file)
@@ -50,7 +50,7 @@ void init_def_material(void);
 void BKE_material_free(struct Material *sc); 
 void BKE_material_free_ex(struct Material *ma, int do_id_user);
 void test_object_materials(struct Main *bmain, struct ID *id);
-void resize_object_material(struct Object *ob, const short totcol);
+void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
 void init_material(struct Material *ma);
 struct Material *BKE_material_add(struct Main *bmain, const char *name);
 struct Material *BKE_material_copy(struct Material *ma);
@@ -87,9 +87,10 @@ int object_add_material_slot(struct Object *ob);
 int object_remove_material_slot(struct Object *ob);
 
 /* rna api */
-void material_append_id(struct ID *id, struct Material *ma);
-struct Material *material_pop_id(struct ID *id, int index, bool remove_material_slot); /* index is an int because of RNA */
-
+void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user);
+void BKE_material_append_id(struct ID *id, struct Material *ma);
+struct Material *BKE_material_pop_id(struct ID *id, int index, bool update_data); /* index is an int because of RNA */
+void BKE_material_clear_id(struct ID *id, bool update_data);
 /* rendering */
 
 void init_render_material(struct Material *, int, float *);
index 1c88a5c45dd06706ba2d18b97da2a719adb7acd5..e582af77d61798112d7433b02d34818a98771499 100644 (file)
@@ -188,7 +188,8 @@ void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase,
 void BKE_mesh_from_nurbs(struct Object *ob);
 void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test);
 void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
-void BKE_mesh_delete_material_index(struct Mesh *me, short index);
+void BKE_mesh_material_index_remove(struct Mesh *me, short index);
+void BKE_mesh_material_index_clear(struct Mesh *me);
 void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
 void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
 void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
index d677a6b07e47452984c68d317479faf2f4fb9cc5..4b98723b1b430355b2d402dbcf3a26c430a342dc 100644 (file)
@@ -2412,12 +2412,23 @@ static void make_bevel_list_2D(BevList *bl)
        /* note: bevp->dir and bevp->quat are not needed for beveling but are
         * used when making a path from a 2D curve, therefor they need to be set - Campbell */
 
-       BevPoint *bevp2 = (BevPoint *)(bl + 1);
-       BevPoint *bevp1 = bevp2 + (bl->nr - 1);
-       BevPoint *bevp0 = bevp1 - 1;
+       BevPoint *bevp0, *bevp1, *bevp2;
        int nr;
 
-       nr = bl->nr;
+       if (bl->poly != -1) {
+               bevp2 = (BevPoint *)(bl + 1);
+               bevp1 = bevp2 + (bl->nr - 1);
+               bevp0 = bevp1 - 1;
+               nr = bl->nr;
+       }
+       else {
+               bevp0 = (BevPoint *)(bl + 1);
+               bevp1 = bevp0 + 1;
+               bevp2 = bevp1 + 1;
+
+               nr = bl->nr - 2;
+       }
+
        while (nr--) {
                const float x1 = bevp1->vec[0] - bevp0->vec[0];
                const float x2 = bevp1->vec[0] - bevp2->vec[0];
@@ -2439,15 +2450,23 @@ static void make_bevel_list_2D(BevList *bl)
 
        /* correct non-cyclic cases */
        if (bl->poly == -1) {
-               BevPoint *bevp = (BevPoint *)(bl + 1);
-               bevp1 = bevp + 1;
-               bevp->sina = bevp1->sina;
-               bevp->cosa = bevp1->cosa;
+               BevPoint *bevp;
+               float angle;
+
+               /* first */
+               bevp = (BevPoint *)(bl + 1);
+               angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0;
+               bevp->sina = sinf(angle);
+               bevp->cosa = cosf(angle);
+               vec_to_quat(bevp->quat, bevp->dir, 5, 1);
+
+               /* last */
                bevp = (BevPoint *)(bl + 1);
                bevp += (bl->nr - 1);
-               bevp1 = bevp - 1;
-               bevp->sina = bevp1->sina;
-               bevp->cosa = bevp1->cosa;
+               angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0;
+               bevp->sina = sinf(angle);
+               bevp->cosa = cosf(angle);
+               vec_to_quat(bevp->quat, bevp->dir, 5, 1);
        }
 }
 
@@ -3858,7 +3877,7 @@ void BKE_curve_translate(Curve *cu, float offset[3], int do_keys)
        }
 }
 
-void BKE_curve_delete_material_index(Curve *cu, int index)
+void BKE_curve_material_index_remove(Curve *cu, int index)
 {
        const int curvetype = BKE_curve_type_get(cu);
 
@@ -3877,8 +3896,32 @@ void BKE_curve_delete_material_index(Curve *cu, int index)
                for (nu = cu->nurb.first; nu; nu = nu->next) {
                        if (nu->mat_nr && nu->mat_nr >= index) {
                                nu->mat_nr--;
-                               if (curvetype == OB_CURVE)
+                               if (curvetype == OB_CURVE) {
                                        nu->charidx--;
+                               }
+                       }
+               }
+       }
+}
+
+void BKE_curve_material_index_clear(Curve *cu)
+{
+       const int curvetype = BKE_curve_type_get(cu);
+
+       if (curvetype == OB_FONT) {
+               struct CharInfo *info = cu->strinfo;
+               int i;
+               for (i = cu->len - 1; i >= 0; i--, info++) {
+                       info->mat_nr = 0;
+               }
+       }
+       else {
+               Nurb *nu;
+
+               for (nu = cu->nurb.first; nu; nu = nu->next) {
+                       nu->mat_nr = 0;
+                       if (curvetype == OB_CURVE) {
+                               nu->charidx = 0;
                        }
                }
        }
index cb6308b70618cd771be089f6996c7e0133edf19a..f3dc64a72796f1fdc6051a40db87c3f954107919 100644 (file)
@@ -537,17 +537,17 @@ short *give_totcolp_id(ID *id)
        return NULL;
 }
 
-static void data_delete_material_index_id(ID *id, short index)
+static void material_data_index_remove_id(ID *id, short index)
 {
        /* ensure we don't try get materials from non-obdata */
        BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
 
        switch (GS(id->name)) {
                case ID_ME:
-                       BKE_mesh_delete_material_index((Mesh *)id, index);
+                       BKE_mesh_material_index_remove((Mesh *)id, index);
                        break;
                case ID_CU:
-                       BKE_curve_delete_material_index((Curve *)id, index);
+                       BKE_curve_material_index_remove((Curve *)id, index);
                        break;
                case ID_MB:
                        /* meta-elems don't have materials atm */
@@ -555,7 +555,53 @@ static void data_delete_material_index_id(ID *id, short index)
        }
 }
 
-void material_append_id(ID *id, Material *ma)
+static void material_data_index_clear_id(ID *id)
+{
+       /* ensure we don't try get materials from non-obdata */
+       BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
+
+       switch (GS(id->name)) {
+               case ID_ME:
+                       BKE_mesh_material_index_clear((Mesh *)id);
+                       break;
+               case ID_CU:
+                       BKE_curve_material_index_clear((Curve *)id);
+                       break;
+               case ID_MB:
+                       /* meta-elems don't have materials atm */
+                       break;
+       }
+}
+
+void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user)
+{
+       Material ***matar = give_matarar_id(id);
+       short *totcolp = give_totcolp_id(id);
+
+       if (matar == NULL) {
+               return;
+       }
+
+       if (do_id_user && totcol < (*totcolp)) {
+               short i;
+               for (i = totcol; i < (*totcolp); i++) {
+                       id_us_min((ID *)(*matar)[i]);
+               }
+       }
+
+       if (totcol == 0) {
+               if (*totcolp) {
+                       MEM_freeN(*matar);
+                       *matar = NULL;
+               }
+       }
+       else {
+               *matar = MEM_recallocN(*matar, sizeof(void *) * totcol);
+       }
+       *totcolp = totcol;
+}
+
+void BKE_material_append_id(ID *id, Material *ma)
 {
        Material ***matar;
        if ((matar = give_matarar_id(id))) {
@@ -572,7 +618,7 @@ void material_append_id(ID *id, Material *ma)
        }
 }
 
-Material *material_pop_id(ID *id, int index_i, bool remove_material_slot)
+Material *BKE_material_pop_id(ID *id, int index_i, bool update_data)
 {
        short index = (short)index_i;
        Material *ret = NULL;
@@ -597,9 +643,9 @@ Material *material_pop_id(ID *id, int index_i, bool remove_material_slot)
                                test_object_materials(G.main, id);
                        }
 
-                       if (remove_material_slot) {
+                       if (update_data) {
                                /* decrease mat_nr index */
-                               data_delete_material_index_id(id, index);
+                               material_data_index_remove_id(id, index);
                        }
                }
        }
@@ -607,6 +653,24 @@ Material *material_pop_id(ID *id, int index_i, bool remove_material_slot)
        return ret;
 }
 
+void BKE_material_clear_id(struct ID *id, bool update_data)
+{
+       Material ***matar;
+       if ((matar = give_matarar_id(id))) {
+               short *totcol = give_totcolp_id(id);
+               *totcol = 0;
+               if (*matar) {
+                       MEM_freeN(*matar);
+                       *matar = NULL;
+               }
+
+               if (update_data) {
+                       /* decrease mat_nr index */
+                       material_data_index_clear_id(id);
+               }
+       }
+}
+
 Material *give_current_material(Object *ob, short act)
 {
        Material ***matarar, *ma;
@@ -672,11 +736,18 @@ Material *give_node_material(Material *ma)
        return NULL;
 }
 
-void resize_object_material(Object *ob, const short totcol)
+void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user)
 {
        Material **newmatar;
        char *newmatbits;
 
+       if (do_id_user && totcol < ob->totcol) {
+               short i;
+               for (i = totcol; i < ob->totcol; i++) {
+                       id_us_min((ID *)ob->mat[i]);
+               }
+       }
+
        if (totcol == 0) {
                if (ob->totcol) {
                        MEM_freeN(ob->mat);
@@ -697,6 +768,8 @@ void resize_object_material(Object *ob, const short totcol)
                ob->mat = newmatar;
                ob->matbits = newmatbits;
        }
+       /* XXX, why not realloc on shrink? - campbell */
+
        ob->totcol = totcol;
        if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
        if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
@@ -714,7 +787,7 @@ void test_object_materials(Main *bmain, ID *id)
 
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->data == id) {
-                       resize_object_material(ob, *totcol);
+                       BKE_material_resize_object(ob, *totcol, false);
                }
        }
 }
@@ -1217,7 +1290,7 @@ int object_remove_material_slot(Object *ob)
 
        /* check indices from mesh */
        if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
-               data_delete_material_index_id((ID *)ob->data, actcol - 1);
+               material_data_index_remove_id((ID *)ob->data, actcol - 1);
                if (ob->curve_cache) {
                        BKE_displist_free(&ob->curve_cache->disp);
                }
@@ -1695,7 +1768,7 @@ static short mesh_getmaterialnumber(Mesh *me, Material *ma)
 /* append material */
 static short mesh_addmaterial(Mesh *me, Material *ma)
 {
-       material_append_id(&me->id, NULL);
+       BKE_material_append_id(&me->id, NULL);
        me->mat[me->totcol - 1] = ma;
 
        id_us_plus(&ma->id);
@@ -1834,7 +1907,7 @@ static void convert_tfacematerial(Main *main, Material *ma)
                /* remove material from mesh */
                for (a = 0; a < me->totcol; ) {
                        if (me->mat[a] == ma) {
-                               material_pop_id(&me->id, a, true);
+                               BKE_material_pop_id(&me->id, a, true);
                        }
                        else {
                                a++;
index f1729b8e098c65ab8f94bdfbbeb83e17fbaa0fc1..3b6040a2917860696b53c726a402450108b4d7b4 100644 (file)
@@ -1866,20 +1866,37 @@ void BKE_mesh_to_curve(Scene *scene, Object *ob)
        }
 }
 
-void BKE_mesh_delete_material_index(Mesh *me, short index)
+void BKE_mesh_material_index_remove(Mesh *me, short index)
 {
+       MPoly *mp;
+       MFace *mf;
        int i;
 
-       for (i = 0; i < me->totpoly; i++) {
-               MPoly *mp = &((MPoly *) me->mpoly)[i];
-               if (mp->mat_nr && mp->mat_nr >= index)
+       for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
+               if (mp->mat_nr && mp->mat_nr >= index) {
                        mp->mat_nr--;
+               }
        }
-       
-       for (i = 0; i < me->totface; i++) {
-               MFace *mf = &((MFace *) me->mface)[i];
-               if (mf->mat_nr && mf->mat_nr >= index)
+
+       for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
+               if (mf->mat_nr && mf->mat_nr >= index) {
                        mf->mat_nr--;
+               }
+       }
+}
+
+void BKE_mesh_material_index_clear(Mesh *me)
+{
+       MPoly *mp;
+       MFace *mf;
+       int i;
+
+       for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
+               mp->mat_nr = 0;
+       }
+
+       for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
+               mf->mat_nr = 0;
        }
 }
 
index 2c642403c077827891442fa5c264cccabe817ca1..f9d6c55a1329282e27e6e87a9421a82d5cf4d399 100644 (file)
@@ -4341,7 +4341,7 @@ static void lib_link_object(FileData *fd, Main *main)
                                /* Only expand so as not to loose any object materials that might be set. */
                                if (totcol_data && (*totcol_data > ob->totcol)) {
                                        /* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */
-                                       resize_object_material(ob, *totcol_data);
+                                       BKE_material_resize_object(ob, *totcol_data, false);
                                }
                        }
                        
index 4610bb89ae4670b1b320ed4f20406070fc81fc89..38ce56b4bc7a6f7bbf6cbd9c3fbe06dbb0f7bf9e 100644 (file)
@@ -2399,7 +2399,7 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
        RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
 }
 
-static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
 {
        Base *base_new;
        Object *obedit = base_old->object;
@@ -2441,7 +2441,7 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh
        BM_mesh_free(bm_new);
        ((Mesh *)base_new->object->data)->edit_btmesh = NULL;
        
-       return true;
+       return base_new;
 }
 
 static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
@@ -2452,7 +2452,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM
        /* sel -> tag */
        BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, BM_ELEM_SELECT);
 
-       return mesh_separate_tagged(bmain, scene, base_old, bm_old);
+       return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
 }
 
 /* flush a hflag to from verts to edges/faces */
@@ -2492,6 +2492,63 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag)
        }
 }
 
+/**
+ * Sets an object to a single material. from one of its slots.
+ *
+ * \note This could be used for split-by-material for non mesh types.
+ * \note This could take material data from another object or args.
+ */
+static void mesh_separate_material_assign_mat_nr(Object *ob, const short mat_nr)
+{
+       ID *obdata = ob->data;
+
+       Material ***matarar;
+       short *totcolp;
+
+       totcolp = give_totcolp_id(obdata);
+       matarar = give_matarar_id(obdata);
+
+       if ((totcolp && matarar) == 0) {
+               BLI_assert(0);
+               return;
+       }
+
+       if (*totcolp) {
+               Material *ma_ob;
+               Material *ma_obdata;
+               char matbit;
+
+               if (mat_nr < ob->totcol) {
+                       ma_ob = ob->mat[mat_nr];
+                       matbit = ob->matbits[mat_nr];
+               }
+               else {
+                       ma_ob = NULL;
+                       matbit = 0;
+               }
+
+               if (mat_nr < *totcolp) {
+                        ma_obdata = (*matarar)[mat_nr];
+               }
+               else {
+                       ma_obdata = NULL;
+               }
+
+               BKE_material_clear_id(obdata, true);
+               BKE_material_resize_object(ob, 1, true);
+               BKE_material_resize_id(obdata, 1, true);
+
+               ob->mat[0] = ma_ob;
+               ob->matbits[0] = matbit;
+               (*matarar)[0] = ma_obdata;
+       }
+       else {
+               BKE_material_clear_id(obdata, true);
+               BKE_material_resize_object(ob, 0, true);
+               BKE_material_resize_id(obdata, 0, true);
+       }
+}
+
 static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
 {
        BMFace *f_cmp, *f;
@@ -2499,6 +2556,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
        bool result = false;
 
        while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
+               Base *base_new;
                const short mat_nr = f_cmp->mat_nr;
                int tot = 0;
 
@@ -2522,11 +2580,22 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
 
                /* leave the current object with some materials */
                if (tot == bm_old->totface) {
+                       mesh_separate_material_assign_mat_nr(base_old->object, mat_nr);
+
+                       /* since we're in editmode, must set faces here */
+                       BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
+                               f->mat_nr = 0;
+                       }
                        break;
                }
 
                /* Move selection into a separate object */
-               result |= mesh_separate_tagged(bmain, scene, base_old, bm_old);
+               base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old);
+               if (base_new) {
+                       mesh_separate_material_assign_mat_nr(base_new->object, mat_nr);
+               }
+
+               result |= (base_new != NULL);
        }
 
        return result;
@@ -2585,7 +2654,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
                bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
 
                /* Move selection into a separate object */
-               result |= mesh_separate_tagged(bmain, scene, base_old, bm_old);
+               result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
        }
 
        return result;
index 2957edd941b4a967207b26f55fff58666ae495a8..aed5699a9d7940e3be308dde471f93efa22f2b29 100644 (file)
@@ -1465,6 +1465,7 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
        row = uiLayoutRow(layout, FALSE);
        uiItemR(row, ptr, "layer", 0, NULL, ICON_NONE);
        uiItemR(row, ptr, "layer_weight", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "blend_mode", 0, "", ICON_NONE);
 
        uiItemPointerR(layout, ptr, "frame_property", &settings_ptr, "properties", NULL, ICON_NONE);
 
index ed4ecff88b9dde578399068b66db26d3e868269c..1e9b681197c1785897b63f882bf64a91c517ed0f 100644 (file)
@@ -1662,17 +1662,15 @@ static int outliner_parenting_poll(bContext *C)
 static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 {
        Main *bmain = CTX_data_main(C);
-       Scene *scene = NULL;
        Object *ob = NULL;
        SpaceOops *soops = CTX_wm_space_outliner(C);
-       TreeElement *te;
        char obname[MAX_ID_NAME];
 
        RNA_string_get(op->ptr, "dragged_obj", obname);
        ob = (Object *)BKE_libblock_find_name(ID_OB, obname);
 
        /* search forwards to find the object */
-       te = outliner_find_id(soops, &soops->tree, (ID *)ob);
+       outliner_find_id(soops, &soops->tree, (ID *)ob);
 
        ED_object_parent_clear(ob, RNA_enum_get(op->ptr, "type"));
 
index 1495ba1b1a5319c7b433da05cac032b833c24e4b..f4e2ff43fc51bc2bed7ea63e589afb6d7e413254 100644 (file)
@@ -59,7 +59,7 @@ typedef struct bActionActuator {
        short   layer;          /* Animation layer */
        short   end_reset;      /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */
        short   strideaxis;     /* Displacement axis */
-       short   pad;
+       short   blend_mode;             /* Layer blending mode */
        float   stridelength;   /* Displacement incurred by cycle */ // not in use
        float   layer_weight;   /* How much of the previous layer to use for blending. (<0 = disable, 0 = add mode) */
 } bActionActuator;
@@ -341,6 +341,10 @@ typedef struct bActuator {
 #define ACT_ACTION_FROM_PROP   6
 #define ACT_ACTION_MOTION              7
 
+/* actionactuator->blend_mode */
+#define ACT_ACTION_BLEND               0
+#define ACT_ACTION_ADD                 1
+
 /* ipoactuator->type */
 #define ACT_IPO_PLAY           0
 #define ACT_IPO_PINGPONG       1
index 76337da32614b4dd301dd1ee7764d051daec62ee..26febf217a6b5d30bef2fa86037ace18ea7eac10 100644 (file)
@@ -347,7 +347,7 @@ int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assig
 
 static void rna_IDMaterials_append_id(ID *id, Material *ma)
 {
-       material_append_id(id, ma);
+       BKE_material_append_id(id, ma);
 
        WM_main_add_notifier(NC_OBJECT | ND_DRAW, id);
        WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id);
@@ -367,7 +367,7 @@ static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i
                return NULL;
        }
 
-       ma = material_pop_id(id, index_i, remove_material_slot);
+       ma = BKE_material_pop_id(id, index_i, remove_material_slot);
 
        if (*totcol == totcol_orig) {
                BKE_report(reports, RPT_ERROR, "No material to removed");
@@ -381,6 +381,15 @@ static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i
        return ma;
 }
 
+static void rna_IDMaterials_clear_id(ID *id, int remove_material_slot)
+{
+       BKE_material_clear_id(id, remove_material_slot);
+
+       DAG_id_tag_update(id, OB_RECALC_DATA);
+       WM_main_add_notifier(NC_OBJECT | ND_DRAW, id);
+       WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id);
+}
+
 static void rna_Library_filepath_set(PointerRNA *ptr, const char *value)
 {
        Library *lib = (Library *)ptr->data;
@@ -499,6 +508,10 @@ static void rna_def_ID_materials(BlenderRNA *brna)
        RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned");
        parm = RNA_def_pointer(func, "material", "Material", "", "Material to remove");
        RNA_def_function_return(func, parm);
+
+       func = RNA_def_function(srna, "clear", "rna_IDMaterials_clear_id");
+       RNA_def_function_ui_description(func, "Remove all materials from the data block");
+       RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned");
 }
 
 static void rna_def_ID(BlenderRNA *brna)
index 134c5bcbee45d3ef35cbd4c19e314e759adddad8..990537142467e3018ee848deed06a0a8c5d421fa 100644 (file)
@@ -593,6 +593,12 @@ static void rna_def_action_actuator(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}
        };
 
+       static EnumPropertyItem prop_blend_items[] = {
+           {ACT_ACTION_BLEND, "BLEND", 0, "Blend", ""},
+           {ACT_ACTION_ADD, "ADD", 0, "Add", ""},
+           {0, NULL, 0, NULL, NULL}
+       };
+
        srna = RNA_def_struct(brna, "ActionActuator", "Actuator");
        RNA_def_struct_ui_text(srna, "Action Actuator", "Actuator to control the object movement");
        RNA_def_struct_sdna_from(srna, "bActionActuator", "data");
@@ -656,7 +662,7 @@ static void rna_def_action_actuator(BlenderRNA *brna)
        prop = RNA_def_property(srna, "layer_weight", PROP_FLOAT, PROP_NONE);
        RNA_def_property_range(prop, 0.0, 1.0);
        RNA_def_property_ui_text(prop, "Layer Weight",
-                                "How much of the previous layer to blend into this one (0 = add mode)");
+                                "How much of the previous layer to blend into this one");
        RNA_def_property_update(prop, NC_LOGIC, NULL);
 
        prop = RNA_def_property(srna, "frame_property", PROP_STRING, PROP_NONE);
@@ -691,6 +697,12 @@ static void rna_def_action_actuator(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Child", "Update Action on all children Objects as well");
        RNA_def_property_update(prop, NC_LOGIC, NULL);
 
+       prop = RNA_def_property(srna, "blend_mode", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "blend_mode");
+       RNA_def_property_enum_items(prop, prop_blend_items);
+       RNA_def_property_ui_text(prop, "Blend Mode", "Determines how this layer is blended with previous layers");
+       RNA_def_property_update(prop, NC_LOGIC, NULL);
+
 #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
        prop = RNA_def_property(srna, "stride_length", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "stridelength");
index 21bf2ec6719a09e3cab3f1a696f446fff37e1234..9773e7a340b6b4f3e6b212e4bac771bc04b4c938 100644 (file)
@@ -568,6 +568,10 @@ static Nurb *rna_Curve_spline_new(Curve *cu, int type)
        nu->resolu = nu->resolv = 12;
        nu->flag = CU_SMOOTH;
 
+       if ((cu->flag & CU_3D) == 0) {
+               nu->flag |= CU_2D;
+       }
+
        BLI_addtail(BKE_curve_nurbs_get(cu), nu);
 
        return nu;
index 90383021c908956f59f6c0cf6ec96e68a5fbf659..a28906254a1edbf5b3cf91fcaf81390c029be164 100644 (file)
@@ -66,6 +66,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
                                        float endtime,
                                        struct bAction *action,
                                        short   playtype,
+                                       short   blend_mode,
                                        short   blendin,
                                        short   priority,
                                        short   layer,
@@ -88,6 +89,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
        m_stridelength(stride),
        m_layer_weight(layer_weight),
        m_playtype(playtype),
+    m_blendmode(blend_mode),
        m_priority(priority),
        m_layer(layer),
        m_ipo_flags(ipo_flags),
@@ -187,6 +189,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
        bool bUseContinue = false;
        KX_GameObject *obj = (KX_GameObject*)GetParent();
        short playtype = BL_Action::ACT_MODE_PLAY;
+       short blendmode = (m_blendmode == ACT_ACTION_ADD) ? BL_Action::ACT_BLEND_ADD : BL_Action::ACT_BLEND_BLEND;
        float start = m_startframe;
        float end = m_endframe;
 
@@ -283,7 +286,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
                        ResetStartTime(curtime);
                }
 
-               if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags))
+               if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags, 1.f, blendmode))
                {
                        m_flag |= ACT_FLAG_ACTIVE;
                        if (bUseContinue)
@@ -328,7 +331,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
                                // Convert into a play action and play back to the beginning
                                end = start;
                                start = obj->GetActionFrame(m_layer);
-                               obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags);
+                               obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags, 1.f, blendmode);
 
                                m_flag |= ACT_FLAG_PLAY_END;
                                break;
index ce805c774effd462bd0b2e716538b20e7614b464..4579a21f5544beea91d695bc602559eb572920e2 100644 (file)
@@ -48,6 +48,7 @@ public:
                                                float endtime,
                                                struct bAction *action,
                                                short   playtype,
+                                               short   blend_mode,
                                                short   blendin,
                                                short   priority,
                                                short   layer,
@@ -129,6 +130,7 @@ protected:
        float   m_stridelength;
        float   m_layer_weight;
        short   m_playtype;
+       short   m_blendmode;
        short   m_priority;
        short   m_layer;
        short   m_ipo_flags;
index 55d9decb333ae87f651e0f1b33868356ac51b9ea..d8ddb33ddc4a391dd34d397e19d7b46eda127c3c 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "BL_ArmatureObject.h"
 #include "BL_ActionActuator.h"
+#include "BL_Action.h"
 #include "KX_BlenderSceneConverter.h"
 #include "MEM_guardedalloc.h"
 #include "BLI_blenlib.h"
@@ -50,7 +51,6 @@
 #include "DNA_armature_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
-#include "DNA_nla_types.h"
 #include "DNA_constraint_types.h"
 #include "KX_PythonSeq.h"
 #include "KX_PythonInit.h"
@@ -137,25 +137,22 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
 
 
 /* Only allowed for Poses with identical channels */
-void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
+void game_blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
 {
-       short mode= ACTSTRIPMODE_BLEND;
-       
        bPoseChannel *dchan;
        const bPoseChannel *schan;
        bConstraint *dcon, *scon;
        float dstweight;
        int i;
 
-       switch (mode) {
-       case ACTSTRIPMODE_BLEND:
-               dstweight = 1.0F - srcweight;
-               break;
-       case ACTSTRIPMODE_ADD:
-               dstweight = 1.0F;
-               break;
-       default :
-               dstweight = 1.0F;
+       if (mode == BL_Action::ACT_BLEND_BLEND)
+       {
+               dstweight = 1.0f - srcweight;
+       } else if (mode == BL_Action::ACT_BLEND_ADD)
+       {
+               dstweight = 1.0f;
+       } else {
+               dstweight = 1.0f;
        }
        
        schan= (bPoseChannel *)src->chanbase.first;
@@ -167,7 +164,7 @@ void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
                        
                        copy_qt_qt(dquat, dchan->quat);
                        copy_qt_qt(squat, schan->quat);
-                       if (mode==ACTSTRIPMODE_BLEND)
+                       if (mode==BL_Action::ACT_BLEND_BLEND)
                                interp_qt_qtqt(dchan->quat, dquat, squat, srcweight);
                        else {
                                mul_fac_qt_fl(squat, srcweight);
index 445b9af1b10d0781d0576efc7349708f264f58ab..81388355fc4f44fcbddb8f09fb26e47e8c5f45ea 100644 (file)
@@ -147,7 +147,7 @@ protected:
 };
 
 /* Pose function specific to the game engine */
-void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */
+void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode); /* was blend_poses */
 //void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
 void game_copy_pose(struct bPose **dst, struct bPose *src, int copy_con);
 void game_free_pose(struct bPose *pose);
index 5b528972e006d2a1b87d130e6f5bd48b0b9dfcea..279899833262fe9893061a23cb4de707c07ad918 100644 (file)
@@ -225,6 +225,7 @@ void BL_ConvertActuators(const char* maggiename,
                                            actact->end,
                                            actact->act,
                                            actact->type, // + 1, because Blender starts to count at zero,
+                                           actact->blend_mode,
                                            actact->blendin,
                                            actact->priority,
                                            actact->layer,
index 9d189a6170e8fe1132b8252adb08cb2f15ca34fc..6d9b22eed91d1a11ffe2a8c49f8e7a3b1dea4b6e 100644 (file)
@@ -65,7 +65,8 @@ BL_Action::BL_Action(class KX_GameObject* gameobj)
        m_blendstart(0.f),
        m_speed(0.f),
        m_priority(0),
-       m_playmode(0),
+       m_playmode(ACT_MODE_PLAY),
+       m_blendmode(ACT_BLEND_BLEND),
        m_ipo_flags(0),
        m_done(true),
        m_calc_localtime(true)
@@ -104,7 +105,8 @@ bool BL_Action::Play(const char* name,
                                        short play_mode,
                                        float layer_weight,
                                        short ipo_flags,
-                                       float playback_speed)
+                                       float playback_speed,
+                                       short blend_mode)
 {
 
        // Only start playing a new action if we're done, or if
@@ -229,6 +231,7 @@ bool BL_Action::Play(const char* name,
        m_endframe = end;
        m_blendin = blendin;
        m_playmode = play_mode;
+       m_blendmode = blend_mode;
        m_endtime = 0.f;
        m_blendframe = 0.f;
        m_blendstart = 0.f;
@@ -423,7 +426,7 @@ void BL_Action::Update(float curtime)
                        float weight = 1.f - (m_blendframe/m_blendin);
 
                        // Blend the poses
-                       game_blend_poses(m_pose, m_blendinpose, weight);
+                       game_blend_poses(m_pose, m_blendinpose, weight, ACT_BLEND_BLEND);
                }
 
 
@@ -431,7 +434,7 @@ void BL_Action::Update(float curtime)
                if (m_layer_weight >= 0)
                {
                        obj->GetMRDPose(&m_blendpose);
-                       game_blend_poses(m_pose, m_blendpose, m_layer_weight);
+                       game_blend_poses(m_pose, m_blendpose, m_layer_weight, m_blendmode);
                }
 
                obj->SetPose(m_pose);
index e4088633e61f58f2520600b07ddbed8f2ee383df..e9d099165175701ec286a26b60699517078ca47a 100644 (file)
@@ -34,7 +34,6 @@
 #include "MEM_guardedalloc.h"
 #endif
 
-
 class BL_Action
 {
 private:
@@ -64,6 +63,7 @@ private:
        short m_priority;
 
        short m_playmode;
+       short m_blendmode;
 
        short m_ipo_flags;
 
@@ -91,7 +91,8 @@ public:
                        short play_mode,
                        float layer_weight,
                        short ipo_flags,
-                       float playback_speed);
+                       float playback_speed,
+                       short blend_mode);
        /**
         * Stop playing the action
         */
@@ -114,7 +115,7 @@ public:
        void SetPlayMode(short play_mode);
        void SetTimes(float start, float end);
 
-       enum 
+       enum
        {
                ACT_MODE_PLAY = 0,
                ACT_MODE_LOOP,
@@ -122,6 +123,13 @@ public:
                ACT_MODE_MAX,
        };
 
+       enum
+       {
+               ACT_BLEND_BLEND=0,
+               ACT_BLEND_ADD=1,
+               ACT_BLEND_MAX,
+       };
+
        enum
        {
                ACT_IPOFLAG_FORCE = 1,
index e3402972ca6cad8399e3cb6c4d847275d71d7360..2e882ceba74552818403605687ddc2e2ef2d9c79 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 #include "BL_ActionManager.h"
+#include "BL_Action.h"
 
 BL_ActionManager::BL_ActionManager(class KX_GameObject *obj)
 {
@@ -72,12 +73,13 @@ bool BL_ActionManager::PlayAction(const char* name,
                                                                short play_mode,
                                                                float layer_weight,
                                                                short ipo_flags,
-                                                               float playback_speed)
+                                                               float playback_speed,
+                                                               short blend_mode)
 {
        // Disable layer blending on the first layer
        if (layer == 0) layer_weight = -1.f;
 
-       return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
+       return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
 }
 
 void BL_ActionManager::StopAction(short layer)
index 600e7b6621eb63769991dca3be2fc1c4928526cc..88aa241b6ce9498540afb81300b9ea0ca3198fc7 100644 (file)
 #ifndef __BL_ACTIONMANAGER_H__
 #define __BL_ACTIONMANAGER_H__
 
-#include "BL_Action.h"
-
 #define MAX_ACTION_LAYERS 8
 
+class BL_Action;
+
 /**
  * BL_ActionManager is responsible for handling a KX_GameObject's actions.
  */
@@ -52,7 +52,8 @@ public:
                                        short play_mode=0,
                                        float layer_weight=0.f,
                                        short ipo_flags=0,
-                                       float playback_speed=1.f);
+                                       float playback_speed=1.f,
+                                       short blend_mode=0);
        /**
         * Gets the current frame of an action
         */
index ec62ae63f0c5133a600fdbaf39a663818e17cf70..e0ec4983739794bf3cdbd98f92ee2babbb0ebdc8 100644 (file)
@@ -73,6 +73,7 @@ typedef unsigned long uint_ptr;
 #include "KX_ObstacleSimulation.h"
 
 #include "BL_ActionManager.h"
+#include "BL_Action.h"
 
 #include "PyObjectPlus.h" /* python stuff */
 
@@ -429,9 +430,10 @@ bool KX_GameObject::PlayAction(const char* name,
                                                                short play_mode,
                                                                float layer_weight,
                                                                short ipo_flags,
-                                                               float playback_speed)
+                                                               float playback_speed,
+                                                               short blend_mode)
 {
-       return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
+       return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
 }
 
 void KX_GameObject::StopAction(short layer)
@@ -3311,11 +3313,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
        short layer=0, priority=0;
        short ipo_flags=0;
        short play_mode=0;
+       short blend_mode=0;
 
-       static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", NULL};
+       static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", "blend_mode", NULL};
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhf:playAction", const_cast<char**>(kwlist),
-                                                                       &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed))
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhfh:playAction", const_cast<char**>(kwlist),
+                                                                       &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed, &blend_mode))
                return NULL;
 
        layer_check(layer, "playAction");
@@ -3323,7 +3326,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
        if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX)
        {
                printf("KX_GameObject.playAction(): given play_mode (%d) is out of range (0 - %d), setting to ACT_MODE_PLAY", play_mode, BL_Action::ACT_MODE_MAX-1);
-               play_mode = BL_Action::ACT_MODE_MAX;
+               play_mode = BL_Action::ACT_MODE_PLAY;
+       }
+
+       if (blend_mode < 0 || blend_mode > BL_Action::ACT_BLEND_MAX)
+       {
+               printf("KX_GameObject.playAction(): given blend_mode (%d) is out of range (0 - %d), setting to ACT_BLEND_BLEND", blend_mode, BL_Action::ACT_BLEND_MAX-1);
+               blend_mode = BL_Action::ACT_BLEND_BLEND;
        }
 
        if (layer_weight < 0.f || layer_weight > 1.f)
@@ -3332,7 +3341,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
                layer_weight = 0.f;
        }
 
-       PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed);
+       PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed, blend_mode);
 
        Py_RETURN_NONE;
 }
index 13a79cebefbe6ef506660ce695e7449f1916c721..5a3b9df74ee32168832da562f9a190df84ed9abd 100644 (file)
@@ -255,7 +255,8 @@ public:
                                        short play_mode=0,
                                        float layer_weight=0.f,
                                        short ipo_flags=0,
-                                       float playback_speed=1.f);
+                                       float playback_speed=1.f,
+                                       short blend_mode=0);
 
        /**
         * Gets the current frame of an action
index d8b4bf9e8bdb0f48bf827744afb1e139143a61f5..ae9cbbb2656ac4176c73dd6e7487206d2238d589 100644 (file)
@@ -1820,6 +1820,10 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
        KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_LOOP, BL_Action::ACT_MODE_LOOP);
        KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_PING_PONG, BL_Action::ACT_MODE_PING_PONG);
 
+       /* BL_Action blend modes */
+       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);
+
        // Check for errors
        if (PyErr_Occurred())
        {
index 5438ae5a97c7a67dcdaf4766d349ccb77095044f..3a4b1d82946acb78942091fb62869094c42cb69c 100644 (file)
@@ -109,7 +109,7 @@ void KX_SoundActuator::play()
 
        try
        {
-               m_handle = AUD_getDevice()->play(sound, 0);
+               m_handle = AUD_getDevice()->play(sound);
        }
        catch(AUD_Exception&)
        {