diff --git a/extern/glew/make/msvc_7_0/glew_vc7.vcproj b/extern/glew/make/msvc_7_0/glew_vc7.vcproj new file mode 100644 index 00000000000..a8141587350 --- /dev/null +++ b/extern/glew/make/msvc_7_0/glew_vc7.vcproj @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extern/make/msvc_7_0/extern.sln b/extern/make/msvc_7_0/extern.sln index afc88ddda8e..e4bc550f503 100644 --- a/extern/make/msvc_7_0/extern.sln +++ b/extern/make/msvc_7_0/extern.sln @@ -8,6 +8,7 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "solid", "..\..\solid\make\msvc_7_0\solid.vcproj", "{D696C86B-0B53-4471-A50D-5B983A6FA4AD}" ProjectSection(ProjectDependencies) = postProject {6461F05D-4698-47AB-A8E8-1CA2ACC9948B} = {6461F05D-4698-47AB-A8E8-1CA2ACC9948B} + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A} = {BAC615B0-F1AF-418B-8D23-A10FD8870D6A} {0112CAD5-3584-412A-A2E5-1315A00437B4} = {0112CAD5-3584-412A-A2E5-1315A00437B4} {B83C6BED-11EC-46C8-AFFA-121EEDE94373} = {B83C6BED-11EC-46C8-AFFA-121EEDE94373} {524264F4-DF21-4B79-847F-E7CA643ECD0B} = {524264F4-DF21-4B79-847F-E7CA643ECD0B} @@ -46,6 +47,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bullet2", "..\..\bullet2\ma ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glew", "..\..\glew\make\msvc_7_0\glew_vc7.vcproj", "{BAC615B0-F1AF-418B-8D23-A10FD8870D6A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution 3D Plugin Debug = 3D Plugin Debug @@ -54,6 +59,10 @@ Global Blender Release = Blender Release BlenderPlayer Debug = BlenderPlayer Debug BlenderPlayer Release = BlenderPlayer Release + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {9C71A793-C177-4CAB-8EC5-923D500B39F8}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 @@ -68,6 +77,10 @@ Global {9C71A793-C177-4CAB-8EC5-923D500B39F8}.BlenderPlayer Debug.Build.0 = Blender Release|Win32 {9C71A793-C177-4CAB-8EC5-923D500B39F8}.BlenderPlayer Release.ActiveCfg = Blender Release|Win32 {9C71A793-C177-4CAB-8EC5-923D500B39F8}.BlenderPlayer Release.Build.0 = Blender Release|Win32 + {9C71A793-C177-4CAB-8EC5-923D500B39F8}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {9C71A793-C177-4CAB-8EC5-923D500B39F8}.Debug.Build.0 = 3D Plugin Debug|Win32 + {9C71A793-C177-4CAB-8EC5-923D500B39F8}.Release.ActiveCfg = 3D Plugin Release|Win32 + {9C71A793-C177-4CAB-8EC5-923D500B39F8}.Release.Build.0 = 3D Plugin Release|Win32 {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.3D Plugin Debug.Build.0 = 3D Plugin Debug|Win32 {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 @@ -80,6 +93,10 @@ Global {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.BlenderPlayer Debug.Build.0 = Blender Release|Win32 {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.BlenderPlayer Release.ActiveCfg = Blender Release|Win32 {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.BlenderPlayer Release.Build.0 = Blender Release|Win32 + {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Debug.Build.0 = 3D Plugin Debug|Win32 + {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Release.ActiveCfg = 3D Plugin Release|Win32 + {D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Release.Build.0 = 3D Plugin Release|Win32 {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.3D Plugin Debug.Build.0 = 3D Plugin Debug|Win32 {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 @@ -92,6 +109,10 @@ Global {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Debug.Build.0 = Blender Debug|Win32 {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Release.ActiveCfg = Blender Debug|Win32 {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Release.Build.0 = Blender Debug|Win32 + {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Debug.Build.0 = 3D Plugin Debug|Win32 + {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Release.ActiveCfg = 3D Plugin Release|Win32 + {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Release.Build.0 = 3D Plugin Release|Win32 {524264F4-DF21-4B79-847F-E7CA643ECD0B}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {524264F4-DF21-4B79-847F-E7CA643ECD0B}.3D Plugin Debug.Build.0 = 3D Plugin Debug|Win32 {524264F4-DF21-4B79-847F-E7CA643ECD0B}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 @@ -104,6 +125,10 @@ Global {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Debug.Build.0 = Blender Release|Win32 {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Release.ActiveCfg = Blender Release|Win32 {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Release.Build.0 = Blender Release|Win32 + {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Debug.Build.0 = 3D Plugin Debug|Win32 + {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Release.ActiveCfg = 3D Plugin Release|Win32 + {524264F4-DF21-4B79-847F-E7CA643ECD0B}.Release.Build.0 = 3D Plugin Release|Win32 {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.3D Plugin Debug.Build.0 = 3D Plugin Debug|Win32 {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 @@ -116,6 +141,10 @@ Global {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Debug.Build.0 = Blender Debug|Win32 {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Release.ActiveCfg = Blender Debug|Win32 {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Release.Build.0 = Blender Debug|Win32 + {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Debug.Build.0 = 3D Plugin Debug|Win32 + {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Release.ActiveCfg = 3D Plugin Release|Win32 + {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Release.Build.0 = 3D Plugin Release|Win32 {0112CAD5-3584-412A-A2E5-1315A00437B4}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {0112CAD5-3584-412A-A2E5-1315A00437B4}.3D Plugin Debug.Build.0 = 3D Plugin Debug|Win32 {0112CAD5-3584-412A-A2E5-1315A00437B4}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 @@ -128,6 +157,10 @@ Global {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Debug.Build.0 = Blender Debug|Win32 {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Release.ActiveCfg = Blender Debug|Win32 {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Release.Build.0 = Blender Debug|Win32 + {0112CAD5-3584-412A-A2E5-1315A00437B4}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {0112CAD5-3584-412A-A2E5-1315A00437B4}.Debug.Build.0 = 3D Plugin Debug|Win32 + {0112CAD5-3584-412A-A2E5-1315A00437B4}.Release.ActiveCfg = 3D Plugin Release|Win32 + {0112CAD5-3584-412A-A2E5-1315A00437B4}.Release.Build.0 = 3D Plugin Release|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.3D Plugin Debug.Build.0 = 3D Plugin Debug|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 @@ -140,6 +173,10 @@ Global {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.BlenderPlayer Debug.Build.0 = Blender Release|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.BlenderPlayer Release.ActiveCfg = Blender Release|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.BlenderPlayer Release.Build.0 = Blender Release|Win32 + {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.Debug.Build.0 = 3D Plugin Debug|Win32 + {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.Release.ActiveCfg = 3D Plugin Release|Win32 + {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.Release.Build.0 = 3D Plugin Release|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.3D Plugin Debug.Build.0 = 3D Plugin Debug|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 @@ -152,6 +189,10 @@ Global {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.BlenderPlayer Debug.Build.0 = Blender Release|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.BlenderPlayer Release.ActiveCfg = Blender Release|Win32 {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.BlenderPlayer Release.Build.0 = Blender Release|Win32 + {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.Debug.Build.0 = 3D Plugin Debug|Win32 + {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.Release.ActiveCfg = 3D Plugin Release|Win32 + {F9850C15-FF0A-429E-9D47-89FB433C9BD8}.Release.Build.0 = 3D Plugin Release|Win32 {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.Blender Debug.ActiveCfg = Blender Debug|Win32 @@ -160,6 +201,10 @@ Global {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.Blender Release.Build.0 = Blender Release|Win32 {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.BlenderPlayer Debug.ActiveCfg = BlenderPlayer Debug|Win32 {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.BlenderPlayer Release.ActiveCfg = BlenderPlayer Release|Win32 + {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.Debug.ActiveCfg = BlenderPlayer Debug|Win32 + {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.Debug.Build.0 = BlenderPlayer Debug|Win32 + {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.Release.ActiveCfg = BlenderPlayer Release|Win32 + {FC752464-F413-4D4F-842D-A5D3AA0E6A3D}.Release.Build.0 = BlenderPlayer Release|Win32 {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.3D Plugin Debug.ActiveCfg = 3D Plugin Debug|Win32 {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.3D Plugin Debug.Build.0 = 3D Plugin Debug|Win32 {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.3D Plugin Release.ActiveCfg = 3D Plugin Release|Win32 @@ -172,6 +217,26 @@ Global {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.BlenderPlayer Debug.Build.0 = Blender Release|Win32 {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.BlenderPlayer Release.ActiveCfg = Blender Release|Win32 {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.BlenderPlayer Release.Build.0 = Blender Release|Win32 + {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Debug.ActiveCfg = 3D Plugin Debug|Win32 + {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Debug.Build.0 = 3D Plugin Debug|Win32 + {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Release.ActiveCfg = 3D Plugin Release|Win32 + {FFD3C64A-30E2-4BC7-BC8F-51818C320400}.Release.Build.0 = 3D Plugin Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.3D Plugin Debug.ActiveCfg = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.3D Plugin Debug.Build.0 = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.3D Plugin Release.ActiveCfg = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.3D Plugin Release.Build.0 = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Blender Debug.ActiveCfg = Blender Debug|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Blender Debug.Build.0 = Blender Debug|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Blender Release.ActiveCfg = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Blender Release.Build.0 = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.BlenderPlayer Debug.ActiveCfg = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.BlenderPlayer Debug.Build.0 = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.BlenderPlayer Release.ActiveCfg = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.BlenderPlayer Release.Build.0 = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Debug.ActiveCfg = Blender Debug|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Debug.Build.0 = Blender Debug|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Release.ActiveCfg = Blender Release|Win32 + {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}.Release.Build.0 = Blender Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/projectfiles_vc7/blender/blender.vcproj b/projectfiles_vc7/blender/blender.vcproj index 2f73bfefd27..6372a2f73f5 100644 --- a/projectfiles_vc7/blender/blender.vcproj +++ b/projectfiles_vc7/blender/blender.vcproj @@ -41,7 +41,7 @@ + + + + @@ -396,6 +402,12 @@ + + + + diff --git a/projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj b/projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj index cba8b1558c9..223a1187347 100644 --- a/projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj +++ b/projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj @@ -124,7 +124,7 @@ + + @@ -539,6 +542,9 @@ + + diff --git a/projectfiles_vc7/gameengine/rasterizer/RAS_rasterizer.vcproj b/projectfiles_vc7/gameengine/rasterizer/RAS_rasterizer.vcproj index 40a92a5c181..31520b06546 100644 --- a/projectfiles_vc7/gameengine/rasterizer/RAS_rasterizer.vcproj +++ b/projectfiles_vc7/gameengine/rasterizer/RAS_rasterizer.vcproj @@ -21,7 +21,7 @@ - - - - - - diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index b5e34444d13..716eac81b55 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -44,6 +44,7 @@ struct bActionChannel; struct bPose; struct bPoseChannel; struct Object; +struct ID; /* Kernel prototypes */ #ifdef __cplusplus @@ -157,6 +158,10 @@ void rest_pose(struct bPose *pose); float get_action_frame(struct Object *ob, float cframe); /* map strip time to global time (frame nr) */ float get_action_frame_inv(struct Object *ob, float cframe); +/* builds a list of NlaIpoChannel with ipo values to write in datablock */ +void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, char *name, float ctime); +/* write values returned by extract_ipochannels_from_action, returns the number of value written */ +int execute_ipochannels(ListBase *lb); #ifdef __cplusplus }; diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index a6871aa837f..faf8692b89a 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -40,6 +40,11 @@ struct Object; struct Lattice; struct Mesh; +/* Kernel prototypes */ +#ifdef __cplusplus +extern "C" { +#endif + void free_key(struct Key *sc); struct Key *add_key(struct ID *id); struct Key *copy_key(struct Key *key); @@ -57,6 +62,12 @@ int do_ob_key(struct Object *ob); struct Key *ob_get_key(struct Object *ob); struct KeyBlock *ob_get_keyblock(struct Object *ob); struct KeyBlock *key_get_keyblock(struct Key *key, int index); +// needed for the GE +void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, int mode); + +#ifdef __cplusplus +}; +#endif #endif diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 4860c65f06c..05f2e69fce1 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -860,7 +860,7 @@ typedef struct NlaIpoChannel { int type; } NlaIpoChannel; -static void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, char *name, float ctime) +void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, char *name, float ctime) { bActionChannel *achan= get_action_channel(act, name); IpoCurve *icu; @@ -953,15 +953,18 @@ static void blend_ipochannels(ListBase *dst, ListBase *src, float srcweight, int } } -static void execute_ipochannels(ListBase *lb) +int execute_ipochannels(ListBase *lb) { NlaIpoChannel *nic; + int count = 0; for(nic= lb->first; nic; nic= nic->next) { if(nic->poin) { write_ipo_poin(nic->poin, nic->type, nic->val); + count++; } } + return count; } /* nla timing */ diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 3b4e562a87a..dd6c7ddacd2 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -630,7 +630,7 @@ void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end) } -static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode) +void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode) { KeyBlock *kb; int *ofsp, ofs[3], elemsize, b; diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 86e395b3770..92544f19721 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -411,6 +411,7 @@ void init_actuator(bActuator *act) switch(act->type) { #ifdef __NLA case ACT_ACTION: + case ACT_SHAPEACTION: act->data= MEM_callocN(sizeof(bActionActuator), "actionact"); break; #endif diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 7d0dd9e41c1..fa7cbb06139 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2991,6 +2991,10 @@ static void lib_link_object(FileData *fd, Main *main) bActionActuator *aa= act->data; aa->act= newlibadr(fd, ob->id.lib, aa->act); } + else if(act->type==ACT_SHAPEACTION) { + bActionActuator *aa= act->data; + aa->act= newlibadr(fd, ob->id.lib, aa->act); + } else if(act->type==ACT_PROPERTY) { bPropertyActuator *pa= act->data; pa->ob= newlibadr(fd, ob->id.lib, pa->ob); @@ -8399,6 +8403,10 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) bActionActuator *aa= act->data; expand_doit(fd, mainvar, aa->act); } + else if(act->type==ACT_SHAPEACTION) { + bActionActuator *aa= act->data; + expand_doit(fd, mainvar, aa->act); + } else if(act->type==ACT_PROPERTY) { bPropertyActuator *pa= act->data; expand_doit(fd, mainvar, pa->ob); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index b4a9f225470..2595b95bbf0 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -664,6 +664,7 @@ static void write_actuators(WriteData *wd, ListBase *lb) switch(act->type) { case ACT_ACTION: + case ACT_SHAPEACTION: writestruct(wd, DATA, "bActionActuator", 1, act->data); break; case ACT_SOUND: diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index e34b376737a..a326f5b01d6 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -278,6 +278,7 @@ typedef struct FreeCamera { #define ACT_VISIBILITY 18 #define ACT_2DFILTER 19 #define ACT_PARENT 20 +#define ACT_SHAPEACTION 21 /* actuator flag */ #define ACT_SHOW 1 diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 27caedf0cdd..59fedf04e30 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -677,6 +677,8 @@ static char *controller_pup(void) static char *actuator_name(int type) { switch (type) { + case ACT_SHAPEACTION: + return "Shape Action"; case ACT_ACTION: return "Action"; case ACT_OBJECT: @@ -732,6 +734,14 @@ static char *actuator_pup(Object *owner) "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17" "|Visibility %x18|2D Filter %x19|Parent %x20"; break; + + case OB_MESH: + return "Actuators %t|Shape Action %x21|Motion %x0|Constraint %x9|Ipo %x1" + "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" + "|Scene %x11|Random %x13|Message %x14|CD %x16|Game %x17" + "|Visibility %x18|2D Filter %x19|Parent %x20"; + break; + default: return "Actuators %t|Motion %x0|Constraint %x9|Ipo %x1" "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" @@ -1433,6 +1443,7 @@ static int get_col_actuator(int type) { switch(type) { case ACT_ACTION: return TH_BUT_ACTION; + case ACT_SHAPEACTION: return TH_BUT_ACTION; case ACT_OBJECT: return TH_BUT_NEUTRAL; case ACT_IPO: return TH_BUT_SETTING; case ACT_PROPERTY: return TH_BUT_SETTING1; @@ -1541,6 +1552,7 @@ static short draw_actuatorbuttons(bActuator *act, uiBlock *block, short xco, sho break; } case ACT_ACTION: + case ACT_SHAPEACTION: { /* DrawAct */ #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 0ad9258bcc0..32946267202 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -90,6 +90,7 @@ #include "BKE_object.h" #include "BKE_scene.h" #include "BL_SkinMeshObject.h" +#include "BL_ShapeDeformer.h" #include "BL_SkinDeformer.h" #include "BL_MeshDeformer.h" //#include "BL_ArmatureController.h" @@ -223,15 +224,16 @@ static unsigned int KX_Mcol2uint_new(MCol col) static void SetDefaultFaceType(Scene* scene) { default_face_mode = TF_DYNAMIC; - Base *base = static_cast(scene->base.first); - while(base) + Scene *sce; + Base *base; + + for(SETLOOPER(scene,base)) { if (base->object->type == OB_LAMP) { default_face_mode = TF_DYNAMIC|TF_LIGHT; return; } - base = base->next; } } @@ -800,12 +802,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* // Determine if we need to make a skinned mesh - if (mesh->dvert){ - meshobj = new BL_SkinMeshObject(lightlayer); + if (mesh->dvert || mesh->key){ + meshobj = new BL_SkinMeshObject(mesh, lightlayer); skinMesh = true; } else { - meshobj = new RAS_MeshObject(lightlayer); + meshobj = new RAS_MeshObject(mesh, lightlayer); } MT_Vector4 *tangent = 0; if (tface) @@ -1644,7 +1646,7 @@ static KX_GameObject *gameobject_from_blenderobject( // needed for python scripting kxscene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); - gameobj = new BL_DeformableGameObject(kxscene,KX_Scene::m_callbacks); + gameobj = new BL_DeformableGameObject(ob,kxscene,KX_Scene::m_callbacks); // set transformation gameobj->AddMesh(meshobj); @@ -1655,12 +1657,24 @@ static KX_GameObject *gameobject_from_blenderobject( ((ob->gameflag2 & OB_NEVER_DO_ACTIVITY_CULLING)!=0); gameobj->SetIgnoreActivityCulling(ignoreActivityCulling); - // If this is a skin object, make Skin Controller - if (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && ((Mesh*)ob->data)->dvert){ + // two options exists for deform: shape keys and armature + // only support relative shape key + bool bHasShapeKey = mesh->key != NULL && mesh->key->type==KEY_RELATIVE; + bool bHasDvert = mesh->dvert != NULL; + bool bHasArmature = (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && bHasDvert); + + if (bHasShapeKey) { + // not that we can have shape keys without dvert! + BL_ShapeDeformer *dcont = new BL_ShapeDeformer((BL_DeformableGameObject*)gameobj, + ob, (BL_SkinMeshObject*)meshobj); + ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; + } else if (bHasArmature) { BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj ); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; - } - else if (((Mesh*)ob->data)->dvert){ + } else if (bHasDvert) { + // this case correspond to a mesh that can potentially deform but not with the + // object to which it is attached for the moment. A skin mesh was created in + // BL_ConvertMesh() so must create a deformer too! BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj ); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } @@ -1696,6 +1710,7 @@ static KX_GameObject *gameobject_from_blenderobject( { gameobj->SetPhysicsEnvironment(kxscene->GetPhysicsEnvironment()); gameobj->SetLayer(ob->lay); + gameobj->SetBlenderObject(ob); } return gameobj; } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index 68a2e41ca47..d23274324ee 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -28,6 +28,8 @@ */ #include "BL_DeformableGameObject.h" +#include "BL_ShapeDeformer.h" +#include "BL_ShapeActionActuator.h" #ifdef HAVE_CONFIG_H #include @@ -60,3 +62,48 @@ CValue* BL_DeformableGameObject::GetReplica() ProcessReplica(replica); return replica; } + +bool BL_DeformableGameObject::SetActiveAction(BL_ShapeActionActuator *act, short priority, double curtime) +{ + if (curtime != m_lastframe){ + m_activePriority = 9999; + m_lastframe= curtime; + m_activeAct = NULL; + } + + if (priority<=m_activePriority) + { + if (m_activeAct && (m_activeAct!=act)) + m_activeAct->SetBlendTime(0.0f); /* Reset the blend timer */ + m_activeAct = act; + m_activePriority = priority; + m_lastframe = curtime; + + return true; + } + else{ + act->SetBlendTime(0.0f); + return false; + } +} + +bool BL_DeformableGameObject::GetShape(vector &shape) +{ + shape.clear(); + if (m_pDeformer) + { + Mesh* mesh = ((BL_MeshDeformer*)m_pDeformer)->GetMesh(); + // this check is normally superfluous: a shape deformer can only be created if the mesh + // has relative keys + if (mesh && mesh->key && mesh->key->type==KEY_RELATIVE) + { + KeyBlock *kb; + for (kb = (KeyBlock*)mesh->key->block.first; kb; kb = (KeyBlock*)kb->next) + { + shape.push_back(kb->curval); + } + } + } + return !shape.empty(); +} + diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h index d943cc7388a..57a404ad72b 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.h +++ b/source/gameengine/Converter/BL_DeformableGameObject.h @@ -34,15 +34,28 @@ #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 +#include "DNA_mesh_types.h" #include "KX_GameObject.h" -#include "RAS_Deformer.h" +#include "BL_MeshDeformer.h" +#include + +class BL_ShapeActionActuator; +struct Key; class BL_DeformableGameObject : public KX_GameObject { public: - RAS_Deformer *m_pDeformer; CValue* GetReplica(); + + double GetLastFrame () + { + return m_lastframe; + } + Object* GetBlendObject() + { + return m_blendobj; + } virtual void Relink(GEN_Map*map) { if (m_pDeformer) @@ -50,13 +63,32 @@ public: }; void ProcessReplica(KX_GameObject* replica); - BL_DeformableGameObject(void* sgReplicationInfo, SG_Callbacks callbacks) : + BL_DeformableGameObject(Object* blendobj, void* sgReplicationInfo, SG_Callbacks callbacks) : KX_GameObject(sgReplicationInfo,callbacks), - m_pDeformer(NULL) + m_pDeformer(NULL), + m_activeAct(NULL), + m_lastframe(0.), + m_blendobj(blendobj), + m_activePriority(9999) { m_isDeformable = true; }; virtual ~BL_DeformableGameObject(); + bool SetActiveAction(class BL_ShapeActionActuator *act, short priority, double curtime); + + bool GetShape(vector &shape); + Key* GetKey() + { + return (m_pDeformer) ? ((BL_MeshDeformer*)m_pDeformer)->GetMesh()->key : NULL; + } + +public: + RAS_Deformer *m_pDeformer; +protected: + class BL_ShapeActionActuator *m_activeAct; + double m_lastframe; + Object* m_blendobj; + short m_activePriority; }; diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index 85ba894f9a5..212827a660f 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -198,7 +198,7 @@ void BL_MeshDeformer::RecalcNormals() void BL_MeshDeformer::VerifyStorage() { /* Ensure that we have the right number of verts assigned */ - if (m_tvtot!=m_bmesh->totvert+m_bmesh->totface) { + if (m_tvtot!=m_bmesh->totvert){ if (m_transverts) delete [] m_transverts; if (m_transnors) diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 88dc2500859..8d8b56b1eed 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -32,6 +32,7 @@ #include "RAS_Deformer.h" #include "DNA_object_types.h" +#include "DNA_key_types.h" #include "MT_Point3.h" #include @@ -56,8 +57,9 @@ public: virtual ~BL_MeshDeformer(); virtual void SetSimulatedTime(double time){}; virtual bool Apply(class RAS_IPolyMaterial *mat); - virtual void Update(void){}; + virtual bool Update(void){ return false; }; virtual RAS_Deformer* GetReplica(){return NULL;}; + struct Mesh* GetMesh() { return m_bmesh; }; // virtual void InitDeform(double time){}; protected: class BL_SkinMeshObject* m_pMeshObject; diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp new file mode 100644 index 00000000000..3e1369e1e9f --- /dev/null +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -0,0 +1,797 @@ +/** +* $Id: BL_ShapeActionActuator.cpp 14444 2008-04-16 22:40:48Z hos $ +* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** +*/ + +#if defined (__sgi) +#include +#else +#include +#endif + +#include "SCA_LogicManager.h" +#include "BL_ShapeActionActuator.h" +#include "BL_ActionActuator.h" +#include "BL_ShapeDeformer.h" +#include "KX_GameObject.h" +#include "STR_HashedString.h" +#include "DNA_action_types.h" +#include "DNA_nla_types.h" +#include "DNA_actuator_types.h" +#include "BKE_action.h" +#include "DNA_armature_types.h" +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "MT_Matrix4x4.h" +#include "BKE_utildefines.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +BL_ShapeActionActuator::~BL_ShapeActionActuator() +{ +} + +void BL_ShapeActionActuator::ProcessReplica() +{ + m_localtime=m_startframe; + m_lastUpdate=-1; +} + +void BL_ShapeActionActuator::SetBlendTime (float newtime) +{ + m_blendframe = newtime; +} + +CValue* BL_ShapeActionActuator::GetReplica() +{ + BL_ShapeActionActuator* replica = new BL_ShapeActionActuator(*this);//m_float,GetName()); + replica->ProcessReplica(); + + // this will copy properties and so on... + CValue::AddDataToReplica(replica); + return replica; +} + +bool BL_ShapeActionActuator::ClampLocalTime() +{ + if (m_startframe < m_endframe) { + if (m_localtime < m_startframe) + { + m_localtime = m_startframe; + return true; + } + else if (m_localtime > m_endframe) + { + m_localtime = m_endframe; + return true; + } + } else { + if (m_localtime > m_startframe) + { + m_localtime = m_startframe; + return true; + } + else if (m_localtime < m_endframe) + { + m_localtime = m_endframe; + return true; + } + } + return false; +} + +void BL_ShapeActionActuator::SetStartTime(float curtime) +{ + float direction = m_startframe < m_endframe ? 1.0 : -1.0; + + if (!(m_flag & ACT_FLAG_REVERSE)) + m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate(); + else + m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_KetsjiEngine::GetAnimFrameRate(); +} + +void BL_ShapeActionActuator::SetLocalTime(float curtime) +{ + float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate(); + + if (m_endframe < m_startframe) + delta_time = -delta_time; + + if (!(m_flag & ACT_FLAG_REVERSE)) + m_localtime = m_startframe + delta_time; + else + m_localtime = m_endframe - delta_time; +} + +void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight) +{ + vector::const_iterator it; + float dstweight; + int i; + KeyBlock *kb; + + dstweight = 1.0F - srcweight; + + for (it=m_blendshape.begin(), kb = (KeyBlock*)key->block.first; + kb && it != m_blendshape.end(); + kb = (KeyBlock*)kb->next, it++) { + kb->curval = kb->curval * dstweight + (*it) * srcweight; + } +} + +bool BL_ShapeActionActuator::Update(double curtime, bool frame) +{ + bool bNegativeEvent = false; + bool bPositiveEvent = false; + bool keepgoing = true; + bool wrap = false; + bool apply=true; + int priority; + float newweight; + + // result = true if animation has to be continued, false if animation stops + // maybe there are events for us in the queue ! + if (frame) + { + for (vector::iterator i=m_events.begin(); !(i==m_events.end());i++) + { + if ((*i)->GetNumber() == 0.0f) + bNegativeEvent = true; + else + bPositiveEvent= true; + (*i)->Release(); + + } + m_events.clear(); + + if (bPositiveEvent) + m_flag |= ACT_FLAG_ACTIVE; + + if (bNegativeEvent) + { + if (!(m_flag & ACT_FLAG_ACTIVE)) + return false; + m_flag &= ~ACT_FLAG_ACTIVE; + } + } + + /* This action can only be attached to a deform object */ + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent(); + float length = m_endframe - m_startframe; + + priority = m_priority; + + /* Determine pre-incrementation behaviour and set appropriate flags */ + switch (m_playtype){ + case ACT_ACTION_MOTION: + if (bNegativeEvent){ + keepgoing=false; + apply=false; + }; + break; + case ACT_ACTION_FROM_PROP: + if (bNegativeEvent){ + apply=false; + keepgoing=false; + } + break; + case ACT_ACTION_LOOP_END: + if (bPositiveEvent){ + if (!(m_flag & ACT_FLAG_LOCKINPUT)){ + m_flag &= ~ACT_FLAG_KEYUP; + m_flag &= ~ACT_FLAG_REVERSE; + m_flag |= ACT_FLAG_LOCKINPUT; + m_localtime = m_startframe; + m_starttime = curtime; + } + } + if (bNegativeEvent){ + m_flag |= ACT_FLAG_KEYUP; + } + break; + case ACT_ACTION_LOOP_STOP: + if (bPositiveEvent){ + if (!(m_flag & ACT_FLAG_LOCKINPUT)){ + m_flag &= ~ACT_FLAG_REVERSE; + m_flag &= ~ACT_FLAG_KEYUP; + m_flag |= ACT_FLAG_LOCKINPUT; + SetStartTime(curtime); + } + } + if (bNegativeEvent){ + m_flag |= ACT_FLAG_KEYUP; + m_flag &= ~ACT_FLAG_LOCKINPUT; + keepgoing=false; + apply=false; + } + break; + case ACT_ACTION_FLIPPER: + if (bPositiveEvent){ + if (!(m_flag & ACT_FLAG_LOCKINPUT)){ + m_flag &= ~ACT_FLAG_REVERSE; + m_flag |= ACT_FLAG_LOCKINPUT; + SetStartTime(curtime); + } + } + else if (bNegativeEvent){ + m_flag |= ACT_FLAG_REVERSE; + m_flag &= ~ACT_FLAG_LOCKINPUT; + SetStartTime(curtime); + } + break; + case ACT_ACTION_PLAY: + if (bPositiveEvent){ + if (!(m_flag & ACT_FLAG_LOCKINPUT)){ + m_flag &= ~ACT_FLAG_REVERSE; + m_localtime = m_starttime; + m_starttime = curtime; + m_flag |= ACT_FLAG_LOCKINPUT; + } + } + break; + default: + break; + } + + /* Perform increment */ + if (keepgoing){ + if (m_playtype == ACT_ACTION_MOTION){ + MT_Point3 newpos; + MT_Point3 deltapos; + + newpos = obj->NodeGetWorldPosition(); + + /* Find displacement */ + deltapos = newpos-m_lastpos; + m_localtime += (length/m_stridelength) * deltapos.length(); + m_lastpos = newpos; + } + else{ + SetLocalTime(curtime); + } + } + + /* Check if a wrapping response is needed */ + if (length){ + if (m_localtime < m_startframe || m_localtime > m_endframe) + { + m_localtime = m_startframe + fmod(m_localtime, length); + wrap = true; + } + } + else + m_localtime = m_startframe; + + /* Perform post-increment tasks */ + switch (m_playtype){ + case ACT_ACTION_FROM_PROP: + { + CValue* propval = GetParent()->GetProperty(m_propname); + if (propval) + m_localtime = propval->GetNumber(); + + if (bNegativeEvent){ + keepgoing=false; + } + } + break; + case ACT_ACTION_MOTION: + break; + case ACT_ACTION_LOOP_STOP: + break; + case ACT_ACTION_FLIPPER: + if (wrap){ + if (!(m_flag & ACT_FLAG_REVERSE)){ + m_localtime=m_endframe; + //keepgoing = false; + } + else { + m_localtime=m_startframe; + keepgoing = false; + } + } + break; + case ACT_ACTION_LOOP_END: + if (wrap){ + if (m_flag & ACT_FLAG_KEYUP){ + keepgoing = false; + m_localtime = m_endframe; + m_flag &= ~ACT_FLAG_LOCKINPUT; + } + SetStartTime(curtime); + } + break; + case ACT_ACTION_PLAY: + if (wrap){ + m_localtime = m_endframe; + keepgoing = false; + m_flag &= ~ACT_FLAG_LOCKINPUT; + } + break; + default: + keepgoing = false; + break; + } + + + if (bNegativeEvent) + m_blendframe=0.0f; + + /* Apply the pose if necessary*/ + if (apply) { + + /* Priority test */ + if (obj->SetActiveAction(this, priority, curtime)){ + Key *key = obj->GetKey(); + + if (!key) { + // this could happen if the mesh was changed in the middle of an action + // and the new mesh has no key, stop the action + keepgoing = false; + } + else { + ListBase tchanbase= {NULL, NULL}; + + if (m_blendin && m_blendframe==0.0f){ + // this is the start of the blending, remember the startup shape + obj->GetShape(m_blendshape); + m_blendstart = curtime; + } + // only interested in shape channel + extract_ipochannels_from_action(&tchanbase, &key->id, m_action, "Shape", m_localtime); + + if (!execute_ipochannels(&tchanbase)) { + // no update, this is possible if action does not match the keys, stop the action + keepgoing = false; + } + else { + // the key have changed, apply blending if needed + if (m_blendin && (m_blendframem_blendin) + m_blendframe = m_blendin; + } + m_lastUpdate = m_localtime; + } + BLI_freelistN(&tchanbase); + } + } + else{ + m_blendframe = 0.0f; + } + } + + if (!keepgoing){ + m_blendframe = 0.0f; + } + return keepgoing; +}; + +/* ------------------------------------------------------------------------- */ +/* Python functions */ +/* ------------------------------------------------------------------------- */ + +/* Integration hooks ------------------------------------------------------- */ + +PyTypeObject BL_ShapeActionActuator::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "BL_ShapeActionActuator", + sizeof(BL_ShapeActionActuator), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject BL_ShapeActionActuator::Parents[] = { + &BL_ShapeActionActuator::Type, + &SCA_IActuator::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; + +PyMethodDef BL_ShapeActionActuator::Methods[] = { + {"setAction", (PyCFunction) BL_ShapeActionActuator::sPySetAction, METH_VARARGS, SetAction_doc}, + {"setStart", (PyCFunction) BL_ShapeActionActuator::sPySetStart, METH_VARARGS, SetStart_doc}, + {"setEnd", (PyCFunction) BL_ShapeActionActuator::sPySetEnd, METH_VARARGS, SetEnd_doc}, + {"setBlendin", (PyCFunction) BL_ShapeActionActuator::sPySetBlendin, METH_VARARGS, SetBlendin_doc}, + {"setPriority", (PyCFunction) BL_ShapeActionActuator::sPySetPriority, METH_VARARGS, SetPriority_doc}, + {"setFrame", (PyCFunction) BL_ShapeActionActuator::sPySetFrame, METH_VARARGS, SetFrame_doc}, + {"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc}, + {"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc}, + + {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_VARARGS, GetAction_doc}, + {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_VARARGS, GetStart_doc}, + {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_VARARGS, GetEnd_doc}, + {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_VARARGS, GetBlendin_doc}, + {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_VARARGS, GetPriority_doc}, + {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_VARARGS, GetFrame_doc}, + {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc}, + {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_VARARGS, GetType_doc}, + {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_VARARGS, SetType_doc}, + {NULL,NULL} //Sentinel +}; + +PyObject* BL_ShapeActionActuator::_getattr(const STR_String& attr) { + _getattr_up(SCA_IActuator); +} + +/* setStart */ +char BL_ShapeActionActuator::GetAction_doc[] = +"getAction()\n" +"\tReturns a string containing the name of the current action.\n"; + +PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self, + PyObject* args, + PyObject* kwds) { + PyObject *result; + + if (m_action){ + result = Py_BuildValue("s", m_action->id.name+2); + } + else{ + Py_INCREF(Py_None); + result = Py_None; + } + + return result; +} + +/* getProperty */ +char BL_ShapeActionActuator::GetProperty_doc[] = +"getProperty()\n" +"\tReturns the name of the property to be used in FromProp mode.\n"; + +PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self, + PyObject* args, + PyObject* kwds) { + PyObject *result; + + result = Py_BuildValue("s", (const char *)m_propname); + + return result; +} + +/* getFrame */ +char BL_ShapeActionActuator::GetFrame_doc[] = +"getFrame()\n" +"\tReturns the current frame number.\n"; + +PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self, + PyObject* args, + PyObject* kwds) { + PyObject *result; + + result = Py_BuildValue("f", m_localtime); + + return result; +} + +/* getEnd */ +char BL_ShapeActionActuator::GetEnd_doc[] = +"getEnd()\n" +"\tReturns the last frame of the action.\n"; + +PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self, + PyObject* args, + PyObject* kwds) { + PyObject *result; + + result = Py_BuildValue("f", m_endframe); + + return result; +} + +/* getStart */ +char BL_ShapeActionActuator::GetStart_doc[] = +"getStart()\n" +"\tReturns the starting frame of the action.\n"; + +PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self, + PyObject* args, + PyObject* kwds) { + PyObject *result; + + result = Py_BuildValue("f", m_startframe); + + return result; +} + +/* getBlendin */ +char BL_ShapeActionActuator::GetBlendin_doc[] = +"getBlendin()\n" +"\tReturns the number of interpolation animation frames to be\n" +"\tgenerated when this actuator is triggered.\n"; + +PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self, + PyObject* args, + PyObject* kwds) { + PyObject *result; + + result = Py_BuildValue("f", m_blendin); + + return result; +} + +/* getPriority */ +char BL_ShapeActionActuator::GetPriority_doc[] = +"getPriority()\n" +"\tReturns the priority for this actuator. Actuators with lower\n" +"\tPriority numbers will override actuators with higher numbers.\n"; + +PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self, + PyObject* args, + PyObject* kwds) { + PyObject *result; + + result = Py_BuildValue("i", m_priority); + + return result; +} + +/* setAction */ +char BL_ShapeActionActuator::SetAction_doc[] = +"setAction(action, (reset))\n" +"\t - action : The name of the action to set as the current action.\n" +"\t Should be an action with Shape channels.\n" +"\t - reset : Optional parameter indicating whether to reset the\n" +"\t blend timer or not. A value of 1 indicates that the\n" +"\t timer should be reset. A value of 0 will leave it\n" +"\t unchanged. If reset is not specified, the timer will" +"\t be reset.\n"; + +PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self, + PyObject* args, + PyObject* kwds) { + char *string; + int reset = 1; + + if (PyArg_ParseTuple(args,"s|i",&string, &reset)) + { + bAction *action; + + action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(STR_String(string)); + + if (!action){ + /* NOTE! Throw an exception or something */ + // printf ("setAction failed: Action not found\n", string); + } + else{ + m_action=action; + if (reset) + m_blendframe = 0.f; + } + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* setStart */ +char BL_ShapeActionActuator::SetStart_doc[] = +"setStart(start)\n" +"\t - start : Specifies the starting frame of the animation.\n"; + +PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self, + PyObject* args, + PyObject* kwds) { + float start; + + if (PyArg_ParseTuple(args,"f",&start)) + { + m_startframe = start; + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* setEnd */ +char BL_ShapeActionActuator::SetEnd_doc[] = +"setEnd(end)\n" +"\t - end : Specifies the ending frame of the animation.\n"; + +PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self, + PyObject* args, + PyObject* kwds) { + float end; + + if (PyArg_ParseTuple(args,"f",&end)) + { + m_endframe = end; + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* setBlendin */ +char BL_ShapeActionActuator::SetBlendin_doc[] = +"setBlendin(blendin)\n" +"\t - blendin : Specifies the number of frames of animation to generate\n" +"\t when making transitions between actions.\n"; + +PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self, + PyObject* args, + PyObject* kwds) { + float blendin; + + if (PyArg_ParseTuple(args,"f",&blendin)) + { + m_blendin = blendin; + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* setBlendtime */ +char BL_ShapeActionActuator::SetBlendtime_doc[] = +"setBlendtime(blendtime)\n" +"\t - blendtime : Allows the script to directly modify the internal timer\n" +"\t used when generating transitions between actions. This\n" +"\t parameter must be in the range from 0.0 to 1.0.\n"; + +PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self, + PyObject* args, + PyObject* kwds) { + float blendframe; + + if (PyArg_ParseTuple(args,"f",&blendframe)) + { + m_blendframe = blendframe * m_blendin; + if (m_blendframe<0.f) + m_blendframe = 0.f; + if (m_blendframe>m_blendin) + m_blendframe = m_blendin; + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* setPriority */ +char BL_ShapeActionActuator::SetPriority_doc[] = +"setPriority(priority)\n" +"\t - priority : Specifies the new priority. Actuators will lower\n" +"\t priority numbers will override actuators with higher\n" +"\t numbers.\n"; + +PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self, + PyObject* args, + PyObject* kwds) { + int priority; + + if (PyArg_ParseTuple(args,"i",&priority)) + { + m_priority = priority; + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* setFrame */ +char BL_ShapeActionActuator::SetFrame_doc[] = +"setFrame(frame)\n" +"\t - frame : Specifies the new current frame for the animation\n"; + +PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self, + PyObject* args, + PyObject* kwds) { + float frame; + + if (PyArg_ParseTuple(args,"f",&frame)) + { + m_localtime = frame; + if (m_localtimem_endframe) + m_localtime=m_endframe; + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* setProperty */ +char BL_ShapeActionActuator::SetProperty_doc[] = +"setProperty(prop)\n" +"\t - prop : A string specifying the property name to be used in\n" +"\t FromProp playback mode.\n"; + +PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, + PyObject* args, + PyObject* kwds) { + char *string; + + if (PyArg_ParseTuple(args,"s",&string)) + { + m_propname = string; + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* getType */ +char BL_ShapeActionActuator::GetType_doc[] = +"getType()\n" +"\tReturns the operation mode of the actuator.\n"; +PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self, + PyObject* args, + PyObject* kwds) { + return Py_BuildValue("h", m_playtype); +} + +/* setType */ +char BL_ShapeActionActuator::SetType_doc[] = +"setType(mode)\n" +"\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n" +"\tSet the operation mode of the actuator.\n"; +PyObject* BL_ShapeActionActuator::PySetType(PyObject* self, + PyObject* args, + PyObject* kwds) { + short typeArg; + + if (!PyArg_ParseTuple(args, "h", &typeArg)) { + return NULL; + } + + switch (typeArg) { + case ACT_ACTION_PLAY: + case ACT_ACTION_FLIPPER: + case ACT_ACTION_LOOP_STOP: + case ACT_ACTION_LOOP_END: + case ACT_ACTION_FROM_PROP: + m_playtype = typeArg; + break; + default: + printf("Invalid type for action actuator: %d\n", typeArg); /* error */ + } + + Py_Return; +} + diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h new file mode 100644 index 00000000000..c4236a5208e --- /dev/null +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -0,0 +1,133 @@ +/** + * $Id: BL_ShapeActionActuator.h 14444 2008-04-16 22:40:48Z hos $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BL_SHAPEACTIONACTUATOR +#define BL_SHAPEACTIONACTUATOR + +#include "GEN_HashedPtr.h" +#include "SCA_IActuator.h" +#include "MT_Point3.h" +#include + +struct Key; +class BL_ShapeActionActuator : public SCA_IActuator +{ +public: + Py_Header; + BL_ShapeActionActuator(SCA_IObject* gameobj, + const STR_String& propname, + float starttime, + float endtime, + struct bAction *action, + short playtype, + short blendin, + short priority, + float stride, + PyTypeObject* T=&Type) + : SCA_IActuator(gameobj,T), + + m_lastpos(0, 0, 0), + m_blendframe(0), + m_flag(0), + m_startframe (starttime), + m_endframe(endtime) , + m_starttime(0), + m_localtime(starttime), + m_lastUpdate(-1), + m_blendin(blendin), + m_blendstart(0), + m_stridelength(stride), + m_playtype(playtype), + m_priority(priority), + m_action(action), + m_propname(propname) + { + }; + virtual ~BL_ShapeActionActuator(); + virtual bool Update(double curtime, bool frame); + virtual CValue* GetReplica(); + virtual void ProcessReplica(); + + void SetBlendTime (float newtime); + void BlendShape(struct Key* key, float weigth); + + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetAction); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendin); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetPriority); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetStart); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetEnd); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetFrame); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetProperty); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendtime); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetChannel); + + KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetAction); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetBlendin); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetPriority); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetStart); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetEnd); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetFrame); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetProperty); +// KX_PYMETHOD(BL_ActionActuator,GetChannel); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetType); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType); + + virtual PyObject* _getattr(const STR_String& attr); + +protected: + + void SetStartTime(float curtime); + void SetLocalTime(float curtime); + bool ClampLocalTime(); + + MT_Point3 m_lastpos; + float m_blendframe; + int m_flag; + /** The frame this action starts */ + float m_startframe; + /** The frame this action ends */ + float m_endframe; + /** The time this action started */ + float m_starttime; + /** The current time of the action */ + float m_localtime; + + float m_lastUpdate; + float m_blendin; + float m_blendstart; + float m_stridelength; + short m_playtype; + short m_priority; + struct bAction *m_action; + STR_String m_propname; + vector m_blendshape; +}; + +#endif + diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp new file mode 100644 index 00000000000..54b1041c328 --- /dev/null +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -0,0 +1,125 @@ +/** + * $Id: BL_ShapeDeformer.cpp 14444 2008-04-16 22:40:48Z hos $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifdef WIN32 +#pragma warning (disable : 4786) +#endif //WIN32 + +#include "MEM_guardedalloc.h" +#include "BL_ShapeDeformer.h" +#include "GEN_Map.h" +#include "STR_HashedString.h" +#include "RAS_IPolygonMaterial.h" +#include "BL_SkinMeshObject.h" + +//#include "BL_ArmatureController.h" +#include "DNA_armature_types.h" +#include "DNA_action_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_key.h" +#include "MT_Point3.h" + +extern "C"{ + #include "BKE_lattice.h" +} + #include "BKE_utildefines.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#define __NLA_DEFNORMALS +//#undef __NLA_DEFNORMALS + + +BL_ShapeDeformer::~BL_ShapeDeformer() +{ +}; + +RAS_Deformer *BL_ShapeDeformer::GetReplica() +{ + BL_ShapeDeformer *result; + + result = new BL_ShapeDeformer(*this); + result->ProcessReplica(); + return result; +} + +void BL_ShapeDeformer::ProcessReplica() +{ +} + +bool BL_ShapeDeformer::Update(void) +{ + bool bShapeUpdate = false; + bool bSkinUpdate = false; + + /* See if the object shape has changed */ + if (m_lastShapeUpdate != m_gameobj->GetLastFrame()) { + /* the key coefficient have been set already, we just need to blend the keys */ + Object* blendobj = m_gameobj->GetBlendObject(); + + // make sure the vertex weight cache is in line with this object + m_pMeshObject->CheckWeightCache(blendobj); + + /* we will blend the key directly in mvert array: it is used by armature as the start position */ + do_rel_key(0, m_bmesh->totvert, m_bmesh->totvert, (char *)m_bmesh->mvert->co, m_bmesh->key, 0); + + // Don't release the weight array as in Blender, it will most likely be reusable on next frame + // The weight array are ultimately deleted when the skin mesh is destroyed + + /* Update the current frame */ + m_lastShapeUpdate=m_gameobj->GetLastFrame(); + + // As we have changed, the mesh, the skin deformer must update as well. + // This will force the update + BL_SkinDeformer::ForceUpdate(); + bShapeUpdate = true; + } + // check for armature deform + bSkinUpdate = BL_SkinDeformer::Update(); + + if (!bSkinUpdate && bShapeUpdate) { + // this means that there is no armature, we still need to copy the vertex to m_transverts + // and update the normal (was not done after shape key calculation) + + /* store verts locally */ + VerifyStorage(); + + for (int v =0; vtotvert; v++) + VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); + + RecalcNormals(); + bSkinUpdate = true; + } + return bSkinUpdate; +} diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h new file mode 100644 index 00000000000..920eae86b7e --- /dev/null +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -0,0 +1,93 @@ +/** + * $Id: BL_SkinDeformer.h 14444 2008-04-16 22:40:48Z hos $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BL_SHAPEDEFORMER +#define BL_SHAPEDEFORMER + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#include "BL_SkinDeformer.h" +#include "BL_DeformableGameObject.h" +#include + + +class BL_ShapeDeformer : public BL_SkinDeformer +{ +public: + virtual void Relink(GEN_Map*map) + { + void **h_obj = (*map)[m_gameobj]; + if (h_obj){ + m_gameobj = (BL_DeformableGameObject*)(*h_obj); + } + else + m_gameobj=NULL; + // relink the underlying skin deformer + BL_SkinDeformer::Relink(map); + }; + BL_ShapeDeformer(BL_DeformableGameObject *gameobj, + Object *bmeshobj, + BL_SkinMeshObject *mesh) + : + BL_SkinDeformer(bmeshobj, mesh), + m_lastShapeUpdate(-1), + m_gameobj(gameobj) + { + }; + + /* this second constructor is needed for making a mesh deformable on the fly. */ + BL_ShapeDeformer(BL_DeformableGameObject *gameobj, + struct Object *bmeshobj_old, + struct Object *bmeshobj_new, + class BL_SkinMeshObject *mesh, + bool release_object, + BL_ArmatureObject* arma = NULL) + : + BL_SkinDeformer(bmeshobj_old, bmeshobj_new, mesh, release_object, arma), + m_lastShapeUpdate(-1), + m_gameobj(gameobj) + { + }; + + virtual void ProcessReplica(); + virtual RAS_Deformer *GetReplica(); + virtual ~BL_ShapeDeformer(); + + bool Update (void); + +protected: + double m_lastShapeUpdate; + BL_DeformableGameObject* m_gameobj; + +}; + +#endif + diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index 0f884674c09..78fc73f21a1 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -57,6 +57,19 @@ extern "C"{ #define __NLA_DEFNORMALS //#undef __NLA_DEFNORMALS +BL_SkinDeformer::BL_SkinDeformer(struct Object *bmeshobj, + class BL_SkinMeshObject *mesh, + BL_ArmatureObject* arma) + : // + BL_MeshDeformer(bmeshobj, mesh), + m_armobj(arma), + m_lastArmaUpdate(-1), + m_defbase(&bmeshobj->defbase), + m_releaseobject(false) +{ + Mat4CpyMat4(m_obmat, bmeshobj->obmat); +}; + BL_SkinDeformer::BL_SkinDeformer( struct Object *bmeshobj_old, // Blender object that owns the new mesh struct Object *bmeshobj_new, // Blender object that owns the original mesh @@ -65,25 +78,22 @@ BL_SkinDeformer::BL_SkinDeformer( BL_ArmatureObject* arma) : BL_MeshDeformer(bmeshobj_old, mesh), m_armobj(arma), - m_lastUpdate(-1), + m_lastArmaUpdate(-1), m_defbase(&bmeshobj_old->defbase), m_releaseobject(release_object) { - Mat4CpyMat4(m_obmat, bmeshobj_old->obmat); - m_restoremat = true; // this is needed to ensure correct deformation of mesh: // the deformation is done with Blender's armature_deform_verts() function // that takes an object as parameter and not a mesh. The object matrice is used - // in the calculation, so we must force the same matrice to simulate a pure replacement of mesh - Mat4CpyMat4(bmeshobj_old->obmat, bmeshobj_new->obmat); + // in the calculation, so we must use the matrix of the original object to + // simulate a pure replacement of the mesh. + Mat4CpyMat4(m_obmat, bmeshobj_new->obmat); } BL_SkinDeformer::~BL_SkinDeformer() { if(m_releaseobject && m_armobj) m_armobj->Release(); - if (m_restoremat) - Mat4CpyMat4(m_objMesh->obmat, m_obmat); } bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) @@ -98,15 +108,13 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) MT_Point3 pt; // float co[3]; - if (!m_armobj) + if (!Update()) + // no need to update the cache return false; - Update(); - array = m_pMeshObject->GetVertexCache(mat); mvarray = m_pMeshObject->GetMVertCache(mat); diarray = m_pMeshObject->GetDIndexCache(mat); - // For each array for (i=0; iGetLastFrame()){ + if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()){ + float obmat[4][4]; // the original object matrice /* Do all of the posing necessary */ m_armobj->ApplyPose(); @@ -161,14 +170,27 @@ void BL_SkinDeformer::Update(void) for (int v =0; vtotvert; v++) VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); + // save matrix first + Mat4CpyMat4(obmat, m_objMesh->obmat); + // set reference matrix + Mat4CpyMat4(m_objMesh->obmat, m_obmat); + armature_deform_verts( par_arma, m_objMesh, NULL, m_transverts, NULL, m_bmesh->totvert, ARM_DEF_VGROUP, NULL, NULL ); + + // restore matrix + Mat4CpyMat4(m_objMesh->obmat, obmat); + #ifdef __NLA_DEFNORMALS RecalcNormals(); #endif /* Update the current frame */ - m_lastUpdate=m_armobj->GetLastFrame(); + m_lastArmaUpdate=m_armobj->GetLastFrame(); + + /* indicate that the m_transverts and normals are up to date */ + return true; } + return false; } /* XXX note: I propose to drop this function */ diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index 79f6453a25d..603e716fb1e 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -52,27 +52,20 @@ public: // void SetArmatureController (BL_ArmatureController *cont); virtual void Relink(GEN_Map*map) { - void **h_obj = (*map)[m_armobj]; - if (h_obj){ - SetArmature( (BL_ArmatureObject*)(*h_obj) ); + if (m_armobj){ + void **h_obj = (*map)[m_armobj]; + if (h_obj){ + SetArmature( (BL_ArmatureObject*)(*h_obj) ); + } + else + m_armobj=NULL; } - else - m_armobj=NULL; } void SetArmature (class BL_ArmatureObject *armobj); BL_SkinDeformer(struct Object *bmeshobj, class BL_SkinMeshObject *mesh, - BL_ArmatureObject* arma = NULL) - : // - BL_MeshDeformer(bmeshobj, mesh), - m_armobj(arma), - m_lastUpdate(-1), - m_defbase(&bmeshobj->defbase), - m_restoremat(false), - m_releaseobject(false) - { - }; + BL_ArmatureObject* arma = NULL); /* this second constructor is needed for making a mesh deformable on the fly. */ BL_SkinDeformer(struct Object *bmeshobj_old, @@ -84,16 +77,20 @@ public: virtual void ProcessReplica(); virtual RAS_Deformer *GetReplica(); virtual ~BL_SkinDeformer(); - void Update (void); + bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); + void ForceUpdate() + { + m_lastArmaUpdate = -1.0; + }; + protected: BL_ArmatureObject* m_armobj; // Our parent object float m_time; - double m_lastUpdate; + double m_lastArmaUpdate; ListBase* m_defbase; - float m_obmat[4][4]; // the original object matrice in case of dynamic mesh replacement - bool m_restoremat; + float m_obmat[4][4]; // the reference matrix for skeleton deform bool m_releaseobject; }; diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp index 69feb72f5dc..9d3702b53a2 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.cpp +++ b/source/gameengine/Converter/BL_SkinMeshObject.cpp @@ -150,5 +150,63 @@ void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObje } +static get_def_index(Object* ob, const char* vgroup) +{ + bDeformGroup *curdef; + int index = 0; + + for (curdef = (bDeformGroup*)ob->defbase.first; curdef; curdef=(bDeformGroup*)curdef->next, index++) + if (!strcmp(curdef->name, vgroup)) + return index; + return -1; +} + +void BL_SkinMeshObject::CheckWeightCache(Object* obj) +{ + KeyBlock *kb; + int kbindex, defindex; + MDeformVert *dvert= NULL; + int totvert, i, j; + float *weights; + + if (!m_mesh->key) + return; + + for(kbindex=0, kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next, kbindex++) + { + // first check the cases where the weight must be cleared + if (kb->vgroup[0] == 0 || + m_mesh->dvert == NULL || + (defindex = get_def_index(obj, kb->vgroup)) == -1) { + if (kb->weights) { + MEM_freeN(kb->weights); + kb->weights = NULL; + } + m_cacheWeightIndex[kbindex] = -1; + } else if (m_cacheWeightIndex[kbindex] != defindex) { + // a weight array is required but the cache is not matching + if (kb->weights) { + MEM_freeN(kb->weights); + kb->weights = NULL; + } + + dvert= m_mesh->dvert; + totvert= m_mesh->totvert; + + weights= (float*)MEM_callocN(totvert*sizeof(float), "weights"); + + for (i=0; i < totvert; i++, dvert++) { + for(j=0; jtotweight; j++) { + if (dvert->dw[j].def_nr == defindex) { + weights[i]= dvert->dw[j].weight; + break; + } + } + } + kb->weights = weights; + m_cacheWeightIndex[kbindex] = defindex; + } + } +} diff --git a/source/gameengine/Converter/BL_SkinMeshObject.h b/source/gameengine/Converter/BL_SkinMeshObject.h index 2422d4cd4c9..cc2b8de600e 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.h +++ b/source/gameengine/Converter/BL_SkinMeshObject.h @@ -33,7 +33,7 @@ #ifdef WIN32 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 - +#include "MEM_guardedalloc.h" #include "RAS_MeshObject.h" #include "RAS_Deformer.h" #include "RAS_IPolygonMaterial.h" @@ -41,6 +41,7 @@ #include "BL_MeshDeformer.h" #include "DNA_mesh_types.h" +#include "DNA_key_types.h" #include "DNA_meshdata_types.h" typedef vector BL_MVertArray; @@ -105,6 +106,8 @@ class BL_SkinMeshObject : public RAS_MeshObject } protected: + vector m_cacheWeightIndex; + public: struct BL_MDVertMap { RAS_IPolyMaterial *mat; int index; }; vector > m_mvert_to_dvert_mapping; @@ -113,10 +116,33 @@ public: // void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,class RAS_BucketManager* bucketmgr); int FindVertexArray(int numverts,RAS_IPolyMaterial* polymat); - BL_SkinMeshObject(int lightlayer) : RAS_MeshObject (lightlayer) - { m_class = 1;}; + BL_SkinMeshObject(Mesh* mesh, int lightlayer) : RAS_MeshObject (mesh, lightlayer) + { + m_class = 1; + if (m_mesh && m_mesh->key) + { + KeyBlock *kb; + int count=0; + // initialize weight cache for shape objects + // count how many keys in this mesh + for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) + count++; + m_cacheWeightIndex.resize(count,-1); + } + }; - virtual ~BL_SkinMeshObject(){ + virtual ~BL_SkinMeshObject() + { + if (m_mesh && m_mesh->key) + { + KeyBlock *kb; + // remove the weight cache to avoid memory leak + for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) { + if(kb->weights) + MEM_freeN(kb->weights); + kb->weights= NULL; + } + } }; const vecIndexArrays& GetDIndexCache (RAS_IPolyMaterial* mat) @@ -154,6 +180,8 @@ public: return index; } + // for shape keys, + void CheckWeightCache(struct Object* obj); }; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 6b594e2e70b..f219c3a1472 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -84,6 +84,7 @@ #include "DNA_actuator_types.h" #include "DNA_packedFile_types.h" #include "BL_ActionActuator.h" +#include "BL_ShapeActionActuator.h" /* end of blender include block */ #include "BL_BlenderDataConversion.h" @@ -195,6 +196,30 @@ void BL_ConvertActuators(char* maggiename, else printf ("Discarded action actuator from non-armature object [%s]\n", blenderobject->id.name+2); } + case ACT_SHAPEACTION: + { + if (blenderobject->type==OB_MESH){ + bActionActuator* actact = (bActionActuator*) bact->data; + STR_String propname = (actact->name ? actact->name : ""); + + BL_ShapeActionActuator* tmpbaseact = new BL_ShapeActionActuator( + gameobj, + propname, + actact->sta, + actact->end, + actact->act, + actact->type, // + 1, because Blender starts to count at zero, + actact->blendin, + actact->priority, + actact->stridelength + // Ketsji at 1, because zero is reserved for "NoDef" + ); + baseact= tmpbaseact; + break; + } + else + printf ("Discarded shape action actuator from non-mesh object [%s]\n", blenderobject->id.name+2); + } case ACT_IPO: { bIpoActuator* ipoact = (bIpoActuator*) bact->data; diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 4b0fc741b8f..e8251e0ceaa 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -120,7 +120,7 @@ public: virtual int GetGameObjectType() {return -1;} typedef enum ObjectTypes { - OBJ_ARMATURE=0 + OBJ_ARMATURE=0, }ObjectTypes; }; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 5698c106b17..88b936aafd5 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -78,6 +78,7 @@ KX_GameObject::KX_GameObject( m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), + m_pBlenderObject(NULL), m_bVisible(true), m_pPhysicsController1(NULL), m_pPhysicsEnvironment(NULL), diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 8a90ec1463a..63a660617c4 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -55,7 +55,7 @@ struct KX_ClientObjectInfo; class RAS_MeshObject; class KX_IPhysicsController; class PHY_IPhysicsEnvironment; - +struct Object; /** * KX_GameObject is the main class for dynamic objects. @@ -71,6 +71,7 @@ protected: STR_String m_text; int m_layer; std::vector m_meshes; + struct Object* m_pBlenderObject; bool m_bSuspendDynamics; bool m_bUseObjectColor; @@ -359,6 +360,20 @@ public: return m_pSGNode; } + /** + * @section blender object accessor functions. + */ + + struct Object* GetBlenderObject( ) + { + return m_pBlenderObject; + } + + void SetBlenderObject( struct Object* obj) + { + m_pBlenderObject = obj; + } + /** * Set the Scene graph node for this game object. * warning - it is your responsibility to make sure diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index e4054e07475..fff33ca82fd 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -74,7 +74,7 @@ #include "KX_IPhysicsController.h" #include "KX_BlenderSceneConverter.h" -#include "BL_SkinDeformer.h" +#include "BL_ShapeDeformer.h" #include "BL_DeformableGameObject.h" // to get USE_BULLET! @@ -809,67 +809,80 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) -void KX_Scene::ReplaceMesh(class CValue* gameobj,void* meshobj) +void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) { - KX_GameObject* newobj = static_cast(gameobj); + KX_GameObject* gameobj = static_cast(obj); RAS_MeshObject* mesh = static_cast(meshobj); - const STR_String origMeshName = newobj->GetMesh(0)->GetName(); - - if( !newobj || !mesh ) + if(!gameobj || !mesh) { std::cout << "warning: invalid object, mesh will not be replaced" << std::endl; return; } - newobj->RemoveMeshes(); - newobj->AddMesh(mesh); - - bool isDeformer = (newobj->m_isDeformable && mesh->m_class == 1); - if(isDeformer) - { - /* FindBlendObjByGameObj() can return 0... - In the case of 0 here, - the replicated object that is calling this function - is some how not in the map. (which is strange because it's added) - So we will search the map by the first mesh name - to try to locate it there. If its still not found - spit some message rather than crash - */ - Object* blendobj = static_cast(m_logicmgr->FindBlendObjByGameObj(newobj)); - Object* oldblendobj = static_cast(m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName())); + gameobj->RemoveMeshes(); + gameobj->AddMesh(mesh); - bool parSkin = blendobj && blendobj->parent && blendobj->parent->type == OB_ARMATURE && blendobj->partype==PARSKEL; - bool releaseParent = true; - KX_GameObject* parentobj = newobj->GetParent(); - - - // lookup by mesh name if blendobj is 0 - if( !blendobj && parentobj ) + if (gameobj->m_isDeformable) + { + BL_DeformableGameObject* newobj = static_cast( gameobj ); + + if (newobj->m_pDeformer) { - blendobj = static_cast(m_logicmgr->FindBlendObjByGameMeshName(origMeshName)); - - // replace the mesh on the parent armature - if( blendobj ) - parSkin = parentobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE; - - // can't do it - else - std::cout << "warning: child object for " << parentobj->GetName().ReadPtr() - << " not found, and can't create!" << std::endl; + delete newobj->m_pDeformer; + newobj->m_pDeformer = NULL; } - if( blendobj && oldblendobj ) + if (mesh->m_class == 1) { - isDeformer = (static_cast(blendobj->data)->dvert != 0); - BL_DeformableGameObject* deformIter =0; + // we must create a new deformer but which one? + KX_GameObject* parentobj = newobj->GetParent(); + // this always return the original game object (also for replicate) + Object* blendobj = newobj->GetBlenderObject(); + // object that owns the new mesh + Object* oldblendobj = static_cast(m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName())); + Mesh* blendmesh = mesh->GetMesh(); - // armature parent - if( parSkin && isDeformer ) + bool bHasShapeKey = blendmesh->key != NULL && blendmesh->key->type==KEY_RELATIVE; + bool bHasDvert = blendmesh->dvert != NULL; + bool bHasArmature = + parentobj && // current parent is armature + parentobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE && + oldblendobj && // needed for mesh deform + blendobj->parent && // original object had armature (not sure this test is needed) + blendobj->parent->type == OB_ARMATURE && + blendobj->partype==PARSKEL && + blendmesh->dvert!=NULL; // mesh has vertex group + bool releaseParent = true; + + if (bHasShapeKey) + { + BL_ShapeDeformer* shapeDeformer; + if (bHasArmature) + { + shapeDeformer = new BL_ShapeDeformer( + newobj, + oldblendobj, blendobj, + static_cast(mesh), + true, + static_cast( parentobj ) + ); + releaseParent= false; + } + else + { + shapeDeformer = new BL_ShapeDeformer( + newobj, + oldblendobj, blendobj, + static_cast(mesh), + false, + NULL + ); + } + newobj->m_pDeformer = shapeDeformer; + } + else if (bHasArmature) { - deformIter = static_cast( newobj ); - delete deformIter->m_pDeformer; - BL_SkinDeformer* skinDeformer = new BL_SkinDeformer( oldblendobj, blendobj, static_cast(mesh), @@ -877,27 +890,22 @@ void KX_Scene::ReplaceMesh(class CValue* gameobj,void* meshobj) static_cast( parentobj ) ); releaseParent= false; - deformIter->m_pDeformer = skinDeformer; + newobj->m_pDeformer = skinDeformer; } - - // normal deformer - if( !parSkin && isDeformer) + else if (bHasDvert) { - deformIter = static_cast( newobj ); - delete deformIter->m_pDeformer; - BL_MeshDeformer* meshdeformer = new BL_MeshDeformer( oldblendobj, static_cast(mesh) ); - - deformIter->m_pDeformer = meshdeformer; + newobj->m_pDeformer = meshdeformer; } + + // release parent reference if its not being used + if( releaseParent && parentobj) + parentobj->Release(); } - // release parent reference if its not being used - if( releaseParent && parentobj) - parentobj->Release(); } - newobj->Bucketize(); + gameobj->Bucketize(); } diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h index bea68e203a9..4e8484ab880 100644 --- a/source/gameengine/Rasterizer/RAS_Deformer.h +++ b/source/gameengine/Rasterizer/RAS_Deformer.h @@ -43,7 +43,7 @@ public: virtual ~RAS_Deformer(){}; virtual void Relink(GEN_Map*map)=0; virtual bool Apply(class RAS_IPolyMaterial *polymat)=0; - virtual void Update(void)=0; + virtual bool Update(void)=0; virtual RAS_Deformer *GetReplica()=0; protected: class RAS_MeshObject *m_pMesh; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index db74110ceea..d7ab88a6b06 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -63,12 +63,13 @@ KX_ArrayOptimizer::~KX_ArrayOptimizer() -RAS_MeshObject::RAS_MeshObject(int lightlayer) +RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer) : m_bModified(true), m_lightlayer(lightlayer), m_zsort(false), m_MeshMod(true), - m_class(0) + m_class(0), + m_mesh(mesh) { } diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index d8e7a3391aa..d9aa133efb2 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -43,6 +43,7 @@ #include "GEN_HashedPtr.h" +struct Mesh; /** * This class holds an array of vertices and indicies. */ @@ -144,9 +145,10 @@ protected: GEN_Map m_matVertexArrayS; RAS_MaterialBucket::Set m_materials; + Mesh* m_mesh; public: // for now, meshes need to be in a certain layer (to avoid sorting on lights in realtime) - RAS_MeshObject(int lightlayer); + RAS_MeshObject(Mesh* mesh, int lightlayer); virtual ~RAS_MeshObject(); vector m_sortedMaterials; @@ -258,6 +260,7 @@ public: bool MeshModified(); void SetMeshModified(bool v){m_MeshMod = v;} + Mesh* GetMesh() { return m_mesh; } };