diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2008-07-20 12:52:48 +0400 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2008-07-20 12:52:48 +0400 |
commit | 037f1188e63c1b8b05d9421ee8f6395bcb3f1ab7 (patch) | |
tree | c9476e0daa75e0e4dbd8cfc9035f851067d4ea29 | |
parent | b369936b1168984b37b04d4d78184ce59442de9e (diff) | |
parent | a8785893c5657592c9cc27ce844664b5d62397de (diff) |
svn merge -r 15529:15649 https://svn.blender.org/svnroot/bf-blender/trunk/blender
99 files changed, 1706 insertions, 626 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b58fe945663..5a23e77d9f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,10 +197,17 @@ IF(UNIX) ENDIF(UNIX) IF(WIN32) - INCLUDE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake) + INCLUDE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake) + SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/windows) + # Setup 64bit and 64bit windows systems + IF(CMAKE_CL_64) + message("64 bit compiler detected.") + SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/win64) + ENDIF(CMAKE_CL_64) + SET(PYTHON ${LIBDIR}/python) SET(PYTHON_VERSION 2.5) SET(PYTHON_INC "${PYTHON}/include/python${PYTHON_VERSION}") @@ -214,12 +221,20 @@ IF(WIN32) SET(OPENAL_LIB openal_static) SET(OPENAL_LIBPATH ${OPENAL}/lib) - SET(PNG_LIB libpng_st) + IF(CMAKE_CL_64) + SET(PNG_LIB libpng) + ELSE(CMAKE_CL_64) + SET(PNG_LIB libpng_st) + ENDIF(CMAKE_CL_64) SET(JPEG_LIB libjpeg) SET(ZLIB ${LIBDIR}/zlib) SET(ZLIB_INC ${ZLIB}/include) - SET(ZLIB_LIB libz) + IF(CMAKE_CL_64) + SET(ZLIB_LIB zlib) + ELSE(CMAKE_CL_64) + SET(ZLIB_LIB libz) + ENDIF(CMAKE_CL_64) SET(ZLIB_LIBPATH ${ZLIB}/lib) SET(PTHREADS ${LIBDIR}/pthreads) @@ -302,7 +317,11 @@ IF(WIN32) SET(WINTAB_INC ${LIBDIR}/wintab/include) - SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib") + IF(CMAKE_CL_64) + SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib;MSVCRT.lib ") + ELSE(CMAKE_CL_64) + SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib ") + ENDIF(CMAKE_CL_64) SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt.lib;libc.lib ") ENDIF(WIN32) @@ -24,22 +24,22 @@ dir to one of these locations (your home directory being recommended). -------------------------------------Links-------------------------------------- Getting Involved: -http://www.blender.org/docs/get_involved.html +http://www.blender.org/community/get-involved Community: -http://www.blender3d.org/Community/ +http://www.blender.org/Community Main blender development site: -http://www.blender.org/ +http://www.blender.org The Blender project homepage: -http://projects.blender.org/projects/bf-blender/ +http://projects.blender.org/projects/bf-blender Documentation: -http://www.blender.org/modules.php?op=modload&name=documentation&file=index +http://www.blender.org/education-help Bug tracker: -http://projects.blender.org/tracker/?atid=125&group_id=9&func=browse +http://www.blender.org/development/report-a-bug Feature request tracker: -http://projects.blender.org/tracker/?atid=128&group_id=9&func=browse +http://wiki.blender.org/index.php/Requests diff --git a/intern/bsp/intern/BSP_CSGMesh.cpp b/intern/bsp/intern/BSP_CSGMesh.cpp index 553f39a4642..ca7795b3cf5 100644 --- a/intern/bsp/intern/BSP_CSGMesh.cpp +++ b/intern/bsp/intern/BSP_CSGMesh.cpp @@ -197,7 +197,7 @@ BuildEdges( for (int vert = 0; vert < vertex_num; ++vert) { - BSP_FaceInd fi(f_it - f_it_begin); + BSP_FaceInd fi(size_t (f_it - f_it_begin)); InsertEdge(prev_vi,face.m_verts[vert],fi,dummy); prev_vi = face.m_verts[vert]; } diff --git a/intern/container/CTR_TaggedIndex.h b/intern/container/CTR_TaggedIndex.h index 7a7bd85e890..68d2536c879 100644 --- a/intern/container/CTR_TaggedIndex.h +++ b/intern/container/CTR_TaggedIndex.h @@ -93,6 +93,16 @@ public: } +#if defined(_WIN64) + CTR_TaggedIndex( + const unsigned __int64 val + ) : + m_val ( ((unsigned __int64)val & index_mask) + | ( (empty_tag << tag_shift) + & (~index_mask) ) ) { + } +#endif + CTR_TaggedIndex( const CTR_TaggedIndex &my_index ): @@ -124,6 +134,12 @@ public: return (long int)(m_val & index_mask); } +#if defined(_WIN64) + operator unsigned __int64 () const { + return (unsigned __int64)(m_val & index_mask); + } +#endif + bool IsEmpty( ) const { diff --git a/intern/decimation/intern/LOD_ManMesh2.cpp b/intern/decimation/intern/LOD_ManMesh2.cpp index eeb497bb09e..2fe49b36583 100644 --- a/intern/decimation/intern/LOD_ManMesh2.cpp +++ b/intern/decimation/intern/LOD_ManMesh2.cpp @@ -477,7 +477,7 @@ DeleteVertex( return; } - LOD_VertexInd last = LOD_VertexInd(verts.end() - verts.begin() - 1); + LOD_VertexInd last = LOD_VertexInd(size_t(verts.end() - verts.begin() - 1)); if (!(last == v)) { @@ -533,7 +533,7 @@ DeleteEdge( return; } - LOD_EdgeInd last = LOD_EdgeInd(edges.end() - edges.begin() - 1); + LOD_EdgeInd last = LOD_EdgeInd(size_t(edges.end() - edges.begin() - 1)); if (!(last == e)) { vector<LOD_EdgeInd> e_verts; @@ -573,7 +573,7 @@ DeleteFace( return; } - LOD_FaceInd last = LOD_FaceInd(faces.end() - faces.begin() - 1); + LOD_FaceInd last = LOD_FaceInd(size_t (faces.end() - faces.begin() - 1)); if (!(last == f)) { diff --git a/intern/elbeem/intern/controlparticles.cpp b/intern/elbeem/intern/controlparticles.cpp index 70a94bb2d1a..75b7e9bfd80 100644 --- a/intern/elbeem/intern/controlparticles.cpp +++ b/intern/elbeem/intern/controlparticles.cpp @@ -177,8 +177,6 @@ int ControlParticles::initFromObject(ntlGeometryObjModel *model) { } model->setGeoInitType(FGI_CONTROL); - - initTime(mCPSTimeStart , mCPSTimeEnd); delete tree; delete genscene; diff --git a/intern/elbeem/intern/solver_init.cpp b/intern/elbeem/intern/solver_init.cpp index fd7a0b6be2c..b1222d48ce5 100644 --- a/intern/elbeem/intern/solver_init.cpp +++ b/intern/elbeem/intern/solver_init.cpp @@ -704,7 +704,7 @@ bool LbmFsgrSolver::initializeSolverMemory() //std::cerr<<" memEstFine "<< memEstFine <<" maxWin:" <<maxWinMemChunk <<" maxMac:" <<maxMacMemChunk ; // DEBUG #ifdef WIN32 double maxWinMemChunk = 1100.*1024.*1024.; - if(memEstFine> maxWinMemChunk) { + if(sizeof(void *)==4 && memEstFine>maxWinMemChunk) { memBlockAllocProblem = true; } #endif // WIN32 diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 293f8fc1661..f5c7c08ebfe 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -42,6 +42,14 @@ #include "GHOST_SystemWin32.h" +// win64 doesn't define GWL_USERDATA +#ifdef WIN32 +#ifndef GWL_USERDATA +#define GWL_USERDATA GWLP_USERDATA +#define GWL_WNDPROC GWLP_WNDPROC +#endif +#endif + /* * According to the docs the mouse wheel message is supported from windows 98 * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 905b2f7ac63..fef58d071a4 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -48,6 +48,14 @@ #define M_PI 3.1415926536 #endif +// win64 doesn't define GWL_USERDATA +#ifdef WIN32 +#ifndef GWL_USERDATA +#define GWL_USERDATA GWLP_USERDATA +#define GWL_WNDPROC GWLP_WNDPROC +#endif +#endif + LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass"; const int GHOST_WindowWin32::s_maxTitleLength = 128; HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL; diff --git a/projectfiles_vc7/blender/src/BL_src.vcproj b/projectfiles_vc7/blender/src/BL_src.vcproj index 6f91aeed8b5..226bedbbfd8 100644 --- a/projectfiles_vc7/blender/src/BL_src.vcproj +++ b/projectfiles_vc7/blender/src/BL_src.vcproj @@ -21,7 +21,7 @@ <Tool Name="VCCLCompilerTool" InlineFunctionExpansion="1" - AdditionalIncludeDirectories="..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\ghost\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\opennl\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\blenkey\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\memutil\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\source\blender;..\..\..\source\blender\img;..\..\..\source\blender\verify;..\..\..\source\blender\ftfont;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\include;..\..\..\source\blender\renderui;..\..\..\source\blender\blenloader;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenpluginapi;..\..\..\source\blender\renderconverter;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\radiosity\extern\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\network;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\build\msvc_7\extern\verse\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\ffmpeg\include" + AdditionalIncludeDirectories="..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\ghost\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\opennl\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\blenkey\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\memutil\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\source\blender;..\..\..\source\blender\img;..\..\..\source\blender\verify;..\..\..\source\blender\ftfont;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\include;..\..\..\source\blender\renderui;..\..\..\source\blender\blenloader;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenpluginapi;..\..\..\source\blender\renderconverter;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\radiosity\extern\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\network;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\build\msvc_7\extern\verse\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\ffmpeg\include" PreprocessorDefinitions="NDEBUG;WIN32;_LIB;_CONSOLE;GAMEBLENDER=1;WITH_QUICKTIME;INTERNATIONAL;WITH_VERSE;WITH_OPENEXR;WITH_DDS;WITH_BULLET=1;WITH_FFMPEG" StringPooling="TRUE" RuntimeLibrary="0" @@ -73,7 +73,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories="..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\ghost\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\opennl\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\blenkey\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\memutil\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\source\blender;..\..\..\source\blender\img;..\..\..\source\blender\verify;..\..\..\source\blender\ftfont;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\include;..\..\..\source\blender\renderui;..\..\..\source\blender\blenloader;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenpluginapi;..\..\..\source\blender\renderconverter;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\radiosity\extern\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\network;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\build\msvc_7\extern\verse\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\ffmpeg\include" + AdditionalIncludeDirectories="..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\ghost\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\opennl\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\blenkey\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\memutil\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\source\blender;..\..\..\source\blender\img;..\..\..\source\blender\verify;..\..\..\source\blender\ftfont;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\include;..\..\..\source\blender\renderui;..\..\..\source\blender\blenloader;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenpluginapi;..\..\..\source\blender\renderconverter;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\radiosity\extern\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\network;..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\build\msvc_7\extern\verse\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_7\extern\glew\include" PreprocessorDefinitions="_DEBUG;WIN32;_LIB;_CONSOLE;GAMEBLENDER;WITH_QUICKTIME;INTERNATIONAL;WITH_VERSE;WITH_OPENEXR;WITH_DDS;WITH_BULLET = 1;WITH_FFMPEG" BasicRuntimeChecks="3" RuntimeLibrary="1" diff --git a/projectfiles_vc7/gameengine/rasterizer/RAS_rasterizer.vcproj b/projectfiles_vc7/gameengine/rasterizer/RAS_rasterizer.vcproj index 31520b06546..9d55a7712fc 100644 --- a/projectfiles_vc7/gameengine/rasterizer/RAS_rasterizer.vcproj +++ b/projectfiles_vc7/gameengine/rasterizer/RAS_rasterizer.vcproj @@ -21,7 +21,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\kernel\gen_system" + AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\..\lib\windows\python\include\python2.5" PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_GLEXT" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -125,7 +125,7 @@ <Tool Name="VCCLCompilerTool" InlineFunctionExpansion="1" - AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\kernel\gen_system" + AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\..\lib\windows\python\include\python2.5" PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_GLEXT" StringPooling="TRUE" RuntimeLibrary="0" @@ -229,7 +229,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\kernel\gen_system" + AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\..\lib\windows\python\include\python2.5" PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_GLEXT" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -281,7 +281,7 @@ <Tool Name="VCCLCompilerTool" InlineFunctionExpansion="1" - AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\kernel\gen_system" + AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\Expressions;..\..\..\..\lib\windows\python\include\python2.5" PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_GLEXT" StringPooling="TRUE" RuntimeLibrary="0" diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 57ecffbb796..43805959e62 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -459,9 +459,10 @@ int BKE_ptcache_object_reset(Object *ob, int mode) PTCacheID pid; ParticleSystem *psys; ModifierData *md; - int reset; + int reset, skip; reset= 0; + skip= 0; if(ob->soft) { BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); @@ -469,11 +470,18 @@ int BKE_ptcache_object_reset(Object *ob, int mode) } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - BKE_ptcache_id_from_particles(&pid, ob, psys); - reset |= BKE_ptcache_id_reset(&pid, mode); - + /* Baked softbody hair has to be checked first, because we don't want to reset */ + /* particles or softbody in that case -jahka */ if(psys->soft) { BKE_ptcache_id_from_softbody(&pid, ob, psys->soft); + if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) + reset |= BKE_ptcache_id_reset(&pid, mode); + else + skip = 1; + } + + if(skip == 0) { + BKE_ptcache_id_from_particles(&pid, ob, psys); reset |= BKE_ptcache_id_reset(&pid, mode); } } diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index c97ca3c6a8a..b7598ec0c4d 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -60,6 +60,7 @@ #define SMALL_NUMBER 1.e-8 #define ABS(x) ((x) < 0 ? -(x) : (x)) #define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; } +#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c) #if defined(WIN32) || defined(__APPLE__) @@ -3800,12 +3801,50 @@ int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], flo /* Adapted from the paper by Kasper Fauerby */ /* "Improved Collision detection and Response" */ +static int getLowestRoot(float a, float b, float c, float maxR, float* root) +{ + // Check if a solution exists + float determinant = b*b - 4.0f*a*c; + + // If determinant is negative it means no solutions. + if (determinant >= 0.0f) + { + // calculate the two roots: (if determinant == 0 then + // x1==x2 but let’s disregard that slight optimization) + float sqrtD = sqrt(determinant); + float r1 = (-b - sqrtD) / (2.0f*a); + float r2 = (-b + sqrtD) / (2.0f*a); + + // Sort so x1 <= x2 + if (r1 > r2) + SWAP( float, r1, r2); + + // Get lowest root: + if (r1 > 0.0f && r1 < maxR) + { + *root = r1; + return 1; + } + + // It is possible that we want x2 - this can happen + // if x1 < 0 + if (r2 > 0.0f && r2 < maxR) + { + *root = r2; + return 1; + } + } + // No (valid) solutions + return 0; +} + int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint) { float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3]; - float a, b, c, d, e, x, y, z, t, t0, t1, radius2=radius*radius; + float a, b, c, d, e, x, y, z, radius2=radius*radius; float elen2,edotv,edotbv,nordotv,vel2; - int embedded_in_plane=0, found_by_sweep=0; + float newLambda; + int found_by_sweep=0; VecSubf(e1,v1,v0); VecSubf(e2,v2,v0); @@ -3814,44 +3853,41 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f /*---test plane of tri---*/ Crossf(nor,e1,e2); Normalize(nor); + /* flip normal */ if(Inpf(nor,vel)>0.0f) VecMulf(nor,-1.0f); a=Inpf(p1,nor)-Inpf(v0,nor); - nordotv=Inpf(nor,vel); - if ((nordotv > -0.000001) && (nordotv < 0.000001)) { - if(fabs(a)>=1.0f) + if (fabs(nordotv) < 0.000001) + { + if(fabs(a)>=radius) + { return 0; - else{ - embedded_in_plane=1; - t0=0.0f; - t1=1.0f; } } - else{ - t0=(radius-a)/nordotv; - t1=(-radius-a)/nordotv; - /* make t0<t1 */ - if(t0>t1){b=t1; t1=t0; t0=b;} + else + { + float t0=(-a+radius)/nordotv; + float t1=(-a-radius)/nordotv; + + if(t0>t1) + SWAP(float, t0, t1); if(t0>1.0f || t1<0.0f) return 0; /* clamp to [0,1] */ - t0=(t0<0.0f)?0.0f:((t0>1.0f)?1.0:t0); - t1=(t1<0.0f)?0.0f:((t1>1.0f)?1.0:t1); - } + CLAMP(t0, 0.0f, 1.0f); + CLAMP(t1, 0.0f, 1.0f); -/*---test inside of tri---*/ - if(embedded_in_plane==0){ + /*---test inside of tri---*/ /* plane intersection point */ - VecCopyf(point,vel); - VecMulf(point,t0); - VecAddf(point,point,p1); - VecCopyf(temp,nor); - VecMulf(temp,radius); - VecSubf(point,point,temp); + + point[0] = p1[0] + vel[0]*t0 - nor[0]*radius; + point[1] = p1[1] + vel[1]*t0 - nor[1]*radius; + point[2] = p1[2] + vel[2]*t0 - nor[2]*radius; + /* is the point in the tri? */ a=Inpf(e1,e1); @@ -3866,14 +3902,19 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f y=e*a-d*b; z=x+y-(a*c-b*b); - if(( ((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y)) ) & 0x80000000){ + + if( z <= 0.0f && (x >= 0.0f && y >= 0.0f)) + { + //( ((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y)) ) & 0x80000000){ *lambda=t0; VecCopyf(ipoint,point); return 1; } } + *lambda=1.0f; + /*---test points---*/ a=vel2=Inpf(vel,vel); @@ -3881,73 +3922,42 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f VecSubf(temp,p1,v0); b=2.0f*Inpf(vel,temp); c=Inpf(temp,temp)-radius2; - d=b*b-4*a*c; - - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x<y?x:y; - } - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,v0); - found_by_sweep=1; - } + if(getLowestRoot(a, b, c, *lambda, lambda)) + { + VecCopyf(ipoint,v0); + found_by_sweep=1; } /*v1*/ VecSubf(temp,p1,v1); b=2.0f*Inpf(vel,temp); c=Inpf(temp,temp)-radius2; - d=b*b-4*a*c; - - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x<y?x:y; - } - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,v1); - found_by_sweep=1; - } + if(getLowestRoot(a, b, c, *lambda, lambda)) + { + VecCopyf(ipoint,v1); + found_by_sweep=1; } + /*v2*/ VecSubf(temp,p1,v2); b=2.0f*Inpf(vel,temp); c=Inpf(temp,temp)-radius2; - d=b*b-4*a*c; - - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x<y?x:y; - } - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,v2); - found_by_sweep=1; - } + if(getLowestRoot(a, b, c, *lambda, lambda)) + { + VecCopyf(ipoint,v2); + found_by_sweep=1; } /*---test edges---*/ + VecSubf(e3,v2,v1); //wasnt yet calculated + + /*e1*/ VecSubf(bv,v0,p1); + elen2 = Inpf(e1,e1); edotv = Inpf(e1,vel); edotbv = Inpf(e1,bv); @@ -3955,27 +3965,18 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f a=elen2*(-Inpf(vel,vel))+edotv*edotv; b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; - d=b*b-4*a*c; - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x<y?x:y; - } - e=(edotv*t-edotbv)/elen2; + if(getLowestRoot(a, b, c, *lambda, &newLambda)) + { + e=(edotv*newLambda-edotbv)/elen2; - if((e>=0.0f) && (e<=1.0f)){ - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,e1); - VecMulf(ipoint,e); - VecAddf(ipoint,ipoint,v0); - found_by_sweep=1; - } + if(e >= 0.0f && e <= 1.0f) + { + *lambda = newLambda; + VecCopyf(ipoint,e1); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v0); + found_by_sweep=1; } } @@ -3988,32 +3989,27 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f a=elen2*(-Inpf(vel,vel))+edotv*edotv; b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; - d=b*b-4*a*c; - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x<y?x:y; - } - e=(edotv*t-edotbv)/elen2; + if(getLowestRoot(a, b, c, *lambda, &newLambda)) + { + e=(edotv*newLambda-edotbv)/elen2; - if((e>=0.0f) && (e<=1.0f)){ - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,e2); - VecMulf(ipoint,e); - VecAddf(ipoint,ipoint,v0); - found_by_sweep=1; - } + if(e >= 0.0f && e <= 1.0f) + { + *lambda = newLambda; + VecCopyf(ipoint,e2); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v0); + found_by_sweep=1; } } /*e3*/ - VecSubf(e3,v2,v1); + VecSubf(bv,v0,p1); + elen2 = Inpf(e1,e1); + edotv = Inpf(e1,vel); + edotbv = Inpf(e1,bv); + VecSubf(bv,v1,p1); elen2 = Inpf(e3,e3); edotv = Inpf(e3,vel); @@ -4022,30 +4018,22 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f a=elen2*(-Inpf(vel,vel))+edotv*edotv; b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; - d=b*b-4*a*c; - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x<y?x:y; - } - e=(edotv*t-edotbv)/elen2; + if(getLowestRoot(a, b, c, *lambda, &newLambda)) + { + e=(edotv*newLambda-edotbv)/elen2; - if((e>=0.0f) && (e<=1.0f)){ - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,e3); - VecMulf(ipoint,e); - VecAddf(ipoint,ipoint,v1); - found_by_sweep=1; - } + if(e >= 0.0f && e <= 1.0f) + { + *lambda = newLambda; + VecCopyf(ipoint,e3); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v1); + found_by_sweep=1; } } + return found_by_sweep; } int AxialLineIntersectsTriangle(int axis, float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index fe352610a40..3e618a483e3 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -451,7 +451,7 @@ void IMB_exr_begin_write(void *handle, char *filename, int width, int height, in openexr_header_compression(&header, compress); /* header.lineOrder() = DECREASING_Y; this crashes in windows for file read! */ - header.insert ("BlenderMultiChannel", StringAttribute ("Blender V2.43")); + header.insert ("BlenderMultiChannel", StringAttribute ("Blender V2.43 and newer")); data->ofile = new OutputFile(filename, header); } diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 2d751f56fc5..7e0f703681b 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -141,6 +141,7 @@ void paste_actdata(void); /* Group/Channel Operations */ struct bActionGroup *get_active_actiongroup(struct bAction *act); void set_active_actiongroup(struct bAction *act, struct bActionGroup *agrp, short select); +void actionbone_group_copycolors(struct bActionGroup *grp, short init_new); void verify_pchan2achan_grouping(struct bAction *act, struct bPose *pose, char name[]); void sync_pchan2achan_grouping(void); void action_groups_group(short add_group); @@ -166,6 +167,7 @@ void deselect_action_channels(short mode); void deselect_actionchannels(struct bAction *act, short mode); int select_channel(struct bAction *act, struct bActionChannel *achan, int selectmode); void select_actionchannel_by_name(struct bAction *act, char *name, int select); +void select_action_group_channels(struct bAction *act, struct bActionGroup *agrp); void selectkeys_leftright (short leftright, short select_mode); /* Action Markers */ diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h index e6cbe7bb69a..df514190270 100644 --- a/source/blender/include/BIF_resources.h +++ b/source/blender/include/BIF_resources.h @@ -591,6 +591,9 @@ void BIF_load_ui_colors (void); char *BIF_ThemeGetColorPtr(struct bTheme *btheme, int spacetype, int colorid); char *BIF_ThemeColorsPup(int spacetype); +/* only for Bone Color sets */ +char *BIF_ThemeColorSetsPup(short inc_custom); + void BIF_def_color (BIFColorID colorid, unsigned char r, unsigned char g, unsigned char b); diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index a798224b35b..6f8b94d7cd1 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -409,6 +409,12 @@ #define B_ACTCOPYKEYS 710 #define B_ACTPASTEKEYS 711 +#define B_ACTCUSTCOLORS 712 +#define B_ACTCOLSSELECTOR 713 +#define B_ACTGRP_SELALL 714 +#define B_ACTGRP_ADDTOSELF 715 +#define B_ACTGRP_UNGROUP 716 + /* TIME: 751 - 800 */ #define B_TL_REW 751 #define B_TL_PLAY 752 diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index a467722e8e1..ac9761f165d 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -196,9 +196,7 @@ typedef struct bVisibilityActuator { } bVisibilityActuator; typedef struct bTwoDFilterActuator{ - char pad[2]; - /* bitwise flag for enabling or disabling depth(bit 0) and luminance(bit 1) */ - short texture_flag; + char pad[4]; /* Tells what type of 2D Filter */ short type; /* (flag == 0) means 2D filter is activate and diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 3de5b0ff5ba..cd1c047dac9 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -116,6 +116,7 @@ typedef struct ThemeWireColor { /* flags for ThemeWireColor */ #define TH_WIRECOLOR_CONSTCOLS (1<<0) +#define TH_WIRECOLOR_TEXTCOLS (1<<1) /* A theme */ typedef struct bTheme { diff --git a/source/blender/python/api2_2x/Library.c b/source/blender/python/api2_2x/Library.c index 799735c2062..468263c4208 100644 --- a/source/blender/python/api2_2x/Library.c +++ b/source/blender/python/api2_2x/Library.c @@ -1135,9 +1135,78 @@ static PyObject *M_Library_Load(PyObject *self, PyObject * args) return (PyObject *)lib; } +static PyObject *M_Library_GetPaths(PyObject *self, PyObject * args) +{ + PyObject *list; + PyObject *name; + int type=0; + Library *lib; + + if( !PyArg_ParseTuple( args, "|i", &type ) || type < 0 || type > 2 ) { + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected an int between 0 and 2." ); + } + + list = PyList_New(0); + + for(lib= G.main->library.first; lib; lib= lib->id.next) { + if (type==0) { + /* any type is ok */ + } else if (type==1 && lib->parent == 0) { + /* only direct linked */ + } else if (type==2 && lib->parent != 0) { + /* only indirect */ + } else { + continue; /* incompatible type */ + } + + name = PyString_FromString(lib->name); + PyList_Append(list, name); + Py_DECREF(name); + } + return list; +} + +static PyObject *M_Library_ReplacePath(PyObject *self, PyObject * args) +{ + char *name_from, *name_to; + Library *lib; + + if( !PyArg_ParseTuple( args, "ss", &name_from, &name_to )) { + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected the name of a library path" ); + } + + for(lib= G.main->library.first; lib; lib= lib->id.next) { + if (strcmp(lib->name, name_from)==0) { + if (lib->parent) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "path is indirectly linked, cannot be changed." ); + } + + if (strlen(name_to) > sizeof(lib->name)) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "string length too long, cannot set path." ); + } + + strcpy(lib->name, name_to); + Py_RETURN_NONE; + } + } + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "path given does not exist as a library" ); +} + + + static struct PyMethodDef M_Library_methods[] = { {"load", (PyCFunction)M_Library_Load, METH_VARARGS, "(string) - declare a .blend file for use as a library"}, + {"paths", (PyCFunction)M_Library_GetPaths, METH_VARARGS, + "(type) - return a list of library paths, type 0 for all, 1 only direct links, 2 only indirect links"}, + {"replace", (PyCFunction)M_Library_ReplacePath, METH_VARARGS, + "(from, to) - replace the path of an existing, directly linked library."}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/api2_2x/doc/LibData.py b/source/blender/python/api2_2x/doc/LibData.py index 47bd7fdb763..daa6a186531 100644 --- a/source/blender/python/api2_2x/doc/LibData.py +++ b/source/blender/python/api2_2x/doc/LibData.py @@ -27,17 +27,37 @@ Example:: """ def load(filename,relative=False): - """ - Select an existing .blend file for use as a library. Unlike the - Library module, multiple libraries can be defined at the same time. - - @type filename: string - @param filename: The filename of a Blender file. Filenames starting with "//" will be loaded relative to the blend file's location. - @type relative: boolean - @param relative: Convert relative paths to absolute paths (default). Setting this parameter to True will leave paths relative. - @rtype: Library - @return: return a L{Library} object. - """ + """ + Select an existing .blend file for use as a library. Unlike the + Library module, multiple libraries can be defined at the same time. + + @type filename: string + @param filename: The filename of a Blender file. Filenames starting with "//" will be loaded relative to the blend file's location. + @type relative: boolean + @param relative: Convert relative paths to absolute paths (default). Setting this parameter to True will leave paths relative. + @rtype: Library + @return: return a L{Library} object. + """ + +def paths(link=0): + """ + Returns a list of paths used in the current blend file. + + @type link: int + @param link: 0 (default if no args given) for all library paths, 1 for directly linked library paths only, 2 for indirectly linked library paths only. + @rtype: List + @return: return a list of path strings. + """ + +def replace(pathFrom, pathTo): + """ + Replaces an existing directly linked path. + + @type pathFrom: string + @param pathFrom: An existing library path. + @type pathTo: string + @param pathTo: A new library path. + """ class Libraries: """ diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py index 475a4fc5b10..d4dc83e84a0 100644 --- a/source/blender/python/api2_2x/doc/Render.py +++ b/source/blender/python/api2_2x/doc/Render.py @@ -833,9 +833,7 @@ class RenderData: def enableCropping(toggle): """ - Enable/disable exclusion of border rendering from total image. - @type toggle: int - @param toggle: pass 1 for on / 0 for off + Deprecated: see the L{crop} attribute. """ def setImageType(type): diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index b446af7efd4..d382d450970 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -985,7 +985,7 @@ PyObject *RenderData_EnableCropping( void ) /* return M_Render_BitToggleInt( args, R_MOVIECROP, &self->renderContext->mode ); */ - printf("cropping option is now default, obsolete\n"); + printf("obsolete: movie cropping option is now default\n"); Py_RETURN_NONE; } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 67be0ce4c00..4520e4c10bb 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -671,8 +671,10 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) RenderPass *zpass; GroupObject *go; LampRen *lar; - - int x, y; + RenderLayer *rlpp[RE_MAX_OSA]; + + int totsample, fullsample, sample; + int x, y,od; short first_lamp; float *zrect; float *rgbrect; @@ -683,7 +685,10 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) fac = 0.5; facm = 1.0 - fac; - + + totsample= get_sample_layers(pa, rl, rlpp); + fullsample= (totsample > 1); + /* check that z pass is enabled */ if(pa->rectz==NULL) return; for(zpass= rl->passes.first; zpass; zpass= zpass->next) @@ -708,9 +713,10 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) zrect = zpass->rect; rgbrect = rl->rectf; + od=0; /* for each x,y and sun lamp*/ for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { - for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, zrect++, rgbrect+=4) { + for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, zrect++, od++) { first_lamp = 1; for(go=R.lights.first; go; go= go->next) { @@ -724,7 +730,7 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) } if(lar->sunsky->effect_type & LA_SUN_EFFECT_AP){ - VECCOPY(tmp_rgb, rgbrect); + VECCOPY(tmp_rgb, (float*)(rgbrect+4*od)); shadeAtmPixel(lar->sunsky, tmp_rgb, x, y, *zrect); @@ -743,7 +749,16 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) /* if at least for one sun lamp aerial perspective was applied*/ if(first_lamp==0) - VECCOPY(rgbrect, rgb); + { + if(fullsample) { + for(sample=0; sample<totsample; sample++) { + VECCOPY((float*)(rlpp[sample]->rectf + od*4), rgb); + } + } + else { + VECCOPY((float*)(rgbrect+4*od), rgb); + } + } } } } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 579905315bb..c91c9e2f799 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -3545,7 +3545,7 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) for(rpass= rl->passes.first; rpass; rpass= rpass->next) { float *col= NULL; - int pixsize= 0; + int pixsize= 3; switch(rpass->passtype) { case SCE_PASS_RGBA: @@ -3580,6 +3580,10 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) col= &shr->mist; pixsize= 1; break; + case SCE_PASS_Z: + col= &shr->z; + pixsize= 1; + break; case SCE_PASS_VECTOR: { @@ -3612,14 +3616,18 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) for(samp= 1; samp<R.osa; samp++, fp+=delta) { col[0]+= fp[0]; - col[1]+= fp[1]; - col[2]+= fp[2]; - if(pixsize) col[3]+= fp[3]; + if(pixsize>1) { + col[1]+= fp[1]; + col[2]+= fp[2]; + if(pixsize==4) col[3]+= fp[3]; + } } col[0]*= weight; - col[1]*= weight; - col[2]*= weight; - if(pixsize) col[3]*= weight; + if(pixsize>1) { + col[1]*= weight; + col[2]*= weight; + if(pixsize==4) col[3]*= weight; + } } } @@ -3973,7 +3981,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas /* general shader info, passes */ shade_sample_initialize(&ssamp, pa, rl); - addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); + addpassflag= rl->passflag & ~(SCE_PASS_COMBINED); addzbuf= rl->passflag & SCE_PASS_Z; if(R.osa) diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 7eff79fec88..529a795a101 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -513,7 +513,6 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an } else { editmesh_deselect_by_material(G.obedit->actcol-1); } - allqueue(REDRAWVIEW3D, 0); } else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) { nu= editNurb.first; @@ -553,8 +552,9 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an nu= nu->next; } BIF_undo_push("Select material index"); - allqueue(REDRAWVIEW3D, 0); } + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWVIEW3D, 0); } countall(); break; @@ -5153,32 +5153,6 @@ static void verify_posegroup_groupname(void *arg1, void *arg2) BLI_uniquename(&pose->agroups, grp, "Group", offsetof(bActionGroup, name), 32); } -static char *build_colorsets_menustr () -{ - DynStr *pupds= BLI_dynstr_new(); - char *str; - char buf[48]; - int i; - - /* add title first (and the "default" entry) */ - BLI_dynstr_append(pupds, "Bone Color Set%t|Default Colors%x0|"); - - /* loop through set indices, adding them */ - for (i=1; i<21; i++) { - sprintf(buf, "%d - Theme Color Set%%x%d|", i, i); - BLI_dynstr_append(pupds, buf); - } - - /* add the 'custom' entry */ - BLI_dynstr_append(pupds, "Custom Set %x-1"); - - /* convert to normal MEM_malloc'd string */ - str= BLI_dynstr_get_cstring(pupds); - BLI_dynstr_free(pupds); - - return str; -} - static void editing_panel_links(Object *ob) { uiBlock *block; @@ -5338,32 +5312,14 @@ static void editing_panel_links(Object *ob) /* color set for 'active' group */ if (pose->active_group && grp) { uiBlockBeginAlign(block); - menustr= build_colorsets_menustr(); + menustr= BIF_ThemeColorSetsPup(1); uiDefButI(block, MENU,B_POSEGRP_RECALC, menustr, xco,85,140,19, &grp->customCol, -1, 20, 0.0, 0.0, "Index of set of Custom Colors to shade Group's bones with. 0 = Use Default Color Scheme, -1 = Use Custom Color Scheme"); MEM_freeN(menustr); /* show color-selection/preview */ if (grp->customCol) { - if (grp->customCol > 0) { - /* copy theme colors on-to group's custom color in case user tries to edit color */ - bTheme *btheme= U.themes.first; - ThemeWireColor *col_set= &btheme->tarm[(grp->customCol - 1)]; - - memcpy(&grp->cs, col_set, sizeof(ThemeWireColor)); - } - else { - /* init custom colors with a generic multi-color rgb set, if not initialised already */ - if (grp->cs.solid[0] == 0) { - /* define for setting colors in theme below */ - #define SETCOL(col, r, g, b, a) col[0]=r; col[1]=g; col[2]= b; col[3]= a; - - SETCOL(grp->cs.solid, 0xff, 0x00, 0x00, 255); - SETCOL(grp->cs.select, 0x81, 0xe6, 0x14, 255); - SETCOL(grp->cs.active, 0x18, 0xb6, 0xe0, 255); - - #undef SETCOL - } - } + /* do color copying/init (to stay up to date) */ + actionbone_group_copycolors(grp, 1); /* color changing */ uiDefButC(block, COL, B_POSEGRP_MCUSTOM, "", xco, 65, 30, 19, grp->cs.solid, 0, 0, 0, 0, "Color to use for surface of bones"); diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index cc4df06e22d..441d00ffc30 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2536,11 +2536,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh break; case ACT_2DFILTER_CUSTOMFILTER: uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30,yco-44,width-60,19,&tdfa->int_arg,0.0,MAX_RENDER_PASS-1,0.0,0.0,"Set motion blur value"); - uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+30,yco-64,width/2-32, 19, &tdfa->text, ""); - uiDefButS(block, TOG|BIT|0, B_REDR, "Depth", xco+width/2+2 , yco - 64, width/4-16 , 19, - &tdfa->texture_flag, 0.0, 0.0, 0, 0, "Includes Depth Texture (bgl_DepthTexture)"); - uiDefButS(block, TOG|BIT|1, B_REDR, "Luminance", xco+3*width/4-14 , yco - 64, width/4-16 , 19, - &tdfa->texture_flag, 0.0, 0.0, 0, 0, "Includes Luminance Texture (bgl_LuminanceTexture)"); + uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+30,yco-64,width-60, 19, &tdfa->text, ""); break; } diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index af90d01fb59..3b0167d673c 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -137,36 +137,42 @@ static void load_new_sample(char *str) /* called from fileselect */ bSample *sample, *newsample; sound = G.buts->lockpoin; + + /* No Sound or Selected the same sample as we alredy have, just ignore */ + if (sound==NULL || str==sound->name) + return; + + if (sizeof(sound->sample->name) < strlen(str)) { + error("Path too long: %s", str); + return; + } + + // save values + sample = sound->sample; + strcpy(name, sound->sample->name); + strcpy(sound->name, str); + sound_set_sample(sound, NULL); + sound_initialize_sample(sound); - if (sound) { - // save values - sample = sound->sample; - strcpy(name, sound->sample->name); - - strcpy(sound->name, str); - sound_set_sample(sound, NULL); - sound_initialize_sample(sound); - - if (sound->sample->type == SAMPLE_INVALID) { - error("Not a valid sample: %s", str); + if (sound->sample->type == SAMPLE_INVALID) { + error("Not a valid sample: %s", str); - newsample = sound->sample; + newsample = sound->sample; - // restore values - strcpy(sound->name, name); - sound_set_sample(sound, sample); + // restore values + strcpy(sound->name, name); + sound_set_sample(sound, sample); - // remove invalid sample + // remove invalid sample - sound_free_sample(newsample); - BLI_remlink(samples, newsample); - MEM_freeN(newsample); - } + sound_free_sample(newsample); + BLI_remlink(samples, newsample); + MEM_freeN(newsample); + return; } - + BIF_undo_push("Load new audio file"); allqueue(REDRAWBUTSSCENE, 0); - } @@ -403,7 +409,7 @@ static void sound_panel_sound(bSound *sound) sample = sound->sample; /* info string */ - if (sound->sample && sound->sample->len) { + if (sound->sample && sound->sample->len && sound->sample->channels && sound->sample->bits) { char *tmp; if (sound->sample->channels == 1) tmp= "Mono"; else if (sound->sample->channels == 2) tmp= "Stereo"; @@ -1174,18 +1180,18 @@ static void seq_panel_proxy() 130,140,120,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Use a custom directory to store data"); - } - if (last_seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { - uiDefIconBut(block, BUT, B_SEQ_SEL_PROXY_DIR, - ICON_FILESEL, 10, 120, 20, 20, 0, 0, 0, 0, 0, - "Select the directory/name for " - "the proxy storage"); + if (last_seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { + uiDefIconBut(block, BUT, B_SEQ_SEL_PROXY_DIR, + ICON_FILESEL, 10, 120, 20, 20, 0, 0, 0, 0, 0, + "Select the directory/name for " + "the proxy storage"); - uiDefBut(block, TEX, - B_SEQ_BUT_RELOAD, "Dir: ", - 30,120,220,20, last_seq->strip->proxy->dir, - 0.0, 160.0, 100, 0, ""); + uiDefBut(block, TEX, + B_SEQ_BUT_RELOAD, "Dir: ", + 30,120,220,20, last_seq->strip->proxy->dir, + 0.0, 160.0, 100, 0, ""); + } } if (last_seq->flag & SEQ_USE_PROXY) { diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 89466151a39..6fe37c1c6e5 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -32,6 +32,7 @@ #include <math.h> #include <stdlib.h> +#include <string.h> #ifdef HAVE_CONFIG_H #include <config.h> @@ -56,6 +57,7 @@ #include "DNA_space_types.h" #include "DNA_constraint_types.h" #include "DNA_key_types.h" +#include "DNA_userdef_types.h" #include "BKE_action.h" #include "BKE_depsgraph.h" @@ -928,12 +930,55 @@ static void draw_channel_strips(void) void do_actionbuts(unsigned short event) { switch(event) { + /* general */ case REDRAWVIEW3D: allqueue(REDRAWVIEW3D, 0); break; case B_REDR: allqueue(REDRAWACTION, 0); break; + + /* action-groups */ + case B_ACTCUSTCOLORS: /* only when of the color wells is edited */ + { + bActionGroup *agrp= get_active_actiongroup(G.saction->action); + + if (agrp) + agrp->customCol= -1; + + allqueue(REDRAWACTION, 0); + } + break; + case B_ACTCOLSSELECTOR: /* sync color set after using selector */ + { + bActionGroup *agrp= get_active_actiongroup(G.saction->action); + + if (agrp) + actionbone_group_copycolors(agrp, 1); + + allqueue(REDRAWACTION, 0); + } + break; + case B_ACTGRP_SELALL: /* select all grouped channels */ + { + bAction *act= G.saction->action; + bActionGroup *agrp= get_active_actiongroup(act); + + /* select all in group, then reselect/activate group as the previous operation clears that */ + select_action_group_channels(act, agrp); + agrp->flag |= (AGRP_ACTIVE|AGRP_SELECTED); + + allqueue(REDRAWACTION, 0); + } + break; + case B_ACTGRP_ADDTOSELF: /* add all selected action channels to self */ + action_groups_group(0); + break; + case B_ACTGRP_UNGROUP: /* remove channels from active group */ + // FIXME: todo... + printf("FIXME: remove achans from active Action-Group not implemented yet! \n"); + break; + } } @@ -941,14 +986,68 @@ void do_actionbuts(unsigned short event) static void action_panel_properties(short cntrl) // ACTION_HANDLER_PROPERTIES { uiBlock *block; - + void *data; + short datatype; + block= uiNewBlock(&curarea->uiblocks, "action_panel_properties", UI_EMBOSS, UI_HELV, curarea->win); uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); uiSetPanelHandler(ACTION_HANDLER_PROPERTIES); // for close and esc - if (uiNewPanel(curarea, block, "Transform Properties", "Action", 10, 230, 318, 204)==0) + + /* get datatype */ + data= get_action_context(&datatype); + //if (data == NULL) return; + + if (uiNewPanel(curarea, block, "Active Channel Properties", "Action", 10, 230, 318, 204)==0) return; - - uiDefBut(block, LABEL, 0, "test text", 10,180,300,19, 0, 0, 0, 0, 0, ""); + + /* currently, only show data for actions */ + if (datatype == ACTCONT_ACTION) { + bActionGroup *agrp= get_active_actiongroup(data); + //bActionChannel *achan= get_hilighted_action_channel(data); + char *menustr; + + /* only for action-groups */ + if (agrp) { + /* general stuff */ + uiDefBut(block, LABEL, 1, "Action Group:", 10, 180, 150, 19, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefBut(block, TEX, B_REDR, "Name: ", 10,160,150,20, agrp->name, 0.0, 31.0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, AGRP_EXPANDED, B_REDR, "Expanded", 170, 160, 75, 20, &agrp->flag, 0, 0, 0, 0, "Action Group is expanded"); + uiDefButBitI(block, TOG, AGRP_PROTECTED, B_REDR, "Protected", 245, 160, 75, 20, &agrp->flag, 0, 0, 0, 0, "Action Group is protected"); + uiBlockEndAlign(block); + + /* color stuff */ + uiDefBut(block, LABEL, 1, "Group Colors:", 10, 107, 150, 19, NULL, 0.0, 0.0, 0, 0, ""); + uiBlockBeginAlign(block); + menustr= BIF_ThemeColorSetsPup(1); + uiDefButI(block, MENU,B_ACTCOLSSELECTOR, menustr, 10,85,150,19, &agrp->customCol, -1, 20, 0.0, 0.0, "Index of set of Custom Colors to shade Group's bones with. 0 = Use Default Color Scheme, -1 = Use Custom Color Scheme"); + MEM_freeN(menustr); + + /* show color-selection/preview */ + if (agrp->customCol) { + /* do color copying/init (to stay up to date) */ + actionbone_group_copycolors(agrp, 1); + + /* color changing */ + uiDefButC(block, COL, B_ACTCUSTCOLORS, "", 10, 65, 50, 19, agrp->cs.active, 0, 0, 0, 0, "Color to use for 'top-level' channels"); + uiDefButC(block, COL, B_ACTCUSTCOLORS, "", 60, 65, 50, 19, agrp->cs.select, 0, 0, 0, 0, "Color to use for '2nd-level' channels"); + uiDefButC(block, COL, B_ACTCUSTCOLORS, "", 110, 65, 50, 19, agrp->cs.solid, 0, 0, 0, 0, "Color to use for '3rd-level' channels"); + } + uiBlockEndAlign(block); + + /* commands for active group */ + uiDefBut(block, BUT, B_ACTGRP_SELALL, "Select Grouped", 170,85,150,20, 0, 21, 0, 0, 0, "Select all action-channels belonging to this group (same as doing Ctrl-Shift-LMB)"); + + uiBlockBeginAlign(block); + uiDefBut(block, BUT, B_ACTGRP_ADDTOSELF, "Add to Group", 170,60,150,20, 0, 21, 0, 0, 0, "Add selected action-channels to this group"); + uiDefBut(block, BUT, B_ACTGRP_UNGROUP, "Un-Group", 170,40,150,20, 0, 21, 0, 0, 0, "Remove selected action-channels from this group (unimplemented)"); + uiBlockEndAlign(block); + } + } + else { + /* Currently, there isn't anything to display for these types ... */ + } } static void action_blockhandlers(ScrArea *sa) diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index f93a1526e3c..4cc0e52ce3f 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -1114,6 +1114,38 @@ void action_groups_ungroup (void) allqueue(REDRAWACTION, 0); } +/* Copy colors from a specified theme's color set to an Action/Bone Group */ +void actionbone_group_copycolors (bActionGroup *grp, short init_new) +{ + /* error checking */ + if (grp == NULL) + return; + + /* only do color copying if using a custom color */ + if (grp->customCol) { + if (grp->customCol > 0) { + /* copy theme colors on-to group's custom color in case user tries to edit color */ + bTheme *btheme= U.themes.first; + ThemeWireColor *col_set= &btheme->tarm[(grp->customCol - 1)]; + + memcpy(&grp->cs, col_set, sizeof(ThemeWireColor)); + } + else if (init_new) { + /* init custom colors with a generic multi-color rgb set, if not initialised already (and allowed to do so) */ + if (grp->cs.solid[0] == 0) { + /* define for setting colors in theme below */ + #define SETCOL(col, r, g, b, a) col[0]=r; col[1]=g; col[2]= b; col[3]= a; + + SETCOL(grp->cs.solid, 0xff, 0x00, 0x00, 255); + SETCOL(grp->cs.select, 0x81, 0xe6, 0x14, 255); + SETCOL(grp->cs.active, 0x18, 0xb6, 0xe0, 255); + + #undef SETCOL + } + } + } +} + /* This function is used when inserting keyframes for pose-channels. It assigns the * action-channel with the nominated name to a group with the same name as that of * the pose-channel with the nominated name. @@ -1160,34 +1192,9 @@ void verify_pchan2achan_grouping (bAction *act, bPose *pose, char name[]) /* copy name */ sprintf(grp->name, agrp->name); - /* deal with group-color copying */ - if (agrp->customCol) { - if (agrp->customCol > 0) { - /* copy theme colors on-to group's custom color in case user tries to edit color */ - bTheme *btheme= U.themes.first; - ThemeWireColor *col_set= &btheme->tarm[(agrp->customCol - 1)]; - - memcpy(&grp->cs, col_set, sizeof(ThemeWireColor)); - } - else { - /* init custom colors with a generic multi-color rgb set, if not initialised already */ - if (agrp->cs.solid[0] == 0) { - /* define for setting colors in theme below */ - #define SETCOL(col, r, g, b, a) col[0]=r; col[1]=g; col[2]= b; col[3]= a; - - SETCOL(grp->cs.solid, 0xff, 0x00, 0x00, 255); - SETCOL(grp->cs.select, 0x81, 0xe6, 0x14, 255); - SETCOL(grp->cs.active, 0x18, 0xb6, 0xe0, 255); - - #undef SETCOL - } - else { - /* just copy color set specified */ - memcpy(&grp->cs, &agrp->cs, sizeof(ThemeWireColor)); - } - } - } - grp->customCol= agrp->customCol; + /* deal with group-color copying (grp is destination, agrp is source) */ + memcpy(grp, agrp, sizeof(bActionGroup)); + actionbone_group_copycolors(grp, 1); BLI_addtail(&act->groups, grp); } @@ -2697,6 +2704,28 @@ int select_icu_channel(bAction *act, IpoCurve *icu, int selectmode) return flag; } + +/* select only the active action-group's action channels */ +void select_action_group_channels (bAction *act, bActionGroup *agrp) +{ + bActionChannel *achan; + + /* error checking */ + if (ELEM(NULL, act, agrp)) + return; + + /* deselect all other channels */ + deselect_actionchannels(act, 0); + + /* only select channels in group */ + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + select_channel(act, achan, SELECT_ADD); + + /* messy... set active bone */ + select_poseelement_by_name(achan->name, 1); + } +} + /* ----------------------------------------- */ /* De-selects or inverts the selection of Channels in a given Action @@ -3672,17 +3701,8 @@ static void mouse_actionchannels (short mval[]) select_action_group(act, agrp, SELECT_INVERT); } else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) { - bActionChannel *achan; - /* select all in group (and deselect everthing else) */ - deselect_actionchannels(act, 0); - - for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { - select_channel(act, achan, SELECT_ADD); - - /* messy... set active bone */ - select_poseelement_by_name(achan->name, 1); - } + select_action_group_channels(act, agrp); select_action_group(act, agrp, SELECT_ADD); } else { @@ -4682,11 +4702,13 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case NKEY: if (G.qual==0) { - numbuts_action(); - - /* no panel (yet). current numbuts are not easy to put in panel... */ - //add_blockhandler(curarea, ACTION_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE); - //scrarea_queue_winredraw(curarea); + /* panel will not always show useful info! */ + if (mval[0] > ACTWIDTH) { + add_blockhandler(curarea, ACTION_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE); + scrarea_queue_winredraw(curarea); + } + else + numbuts_action(); } break; diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 9eef61e11f9..188f7476728 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -340,8 +340,9 @@ void free_editface(EditFace *efa) #endif EM_remove_selection(efa, EDITFACE); - if (G.editMesh->act_face==efa) - EM_set_actFace(NULL); + if (G.editMesh->act_face==efa) { + EM_set_actFace( G.editMesh->faces.first == efa ? NULL : G.editMesh->faces.first); + } CustomData_em_free_block(&G.editMesh->fdata, &efa->data); if(efa->fast==0) @@ -1059,7 +1060,11 @@ void make_editMesh() EM_hide_reset(); /* sets helper flags which arent saved */ EM_fgon_flags(); - + + if (EM_get_actFace(0)==NULL) { + EM_set_actFace( G.editMesh->faces.first ); /* will use the first face, this is so we alwats have an active face */ + } + /* vertex coordinates change with cache edit, need to recalc */ if(cacheedit) recalc_editnormals(); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 2e5785eaab8..6af4f47ed11 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -5505,6 +5505,7 @@ void selectlinks(int nr) allqueue(REDRAWDATASELECT, 0); allqueue(REDRAWOOPS, 0); BIF_undo_push("Select linked"); + countall(); } } diff --git a/source/blender/src/editsound.c b/source/blender/src/editsound.c index 1cb7ec276cb..05eb094a7c2 100644 --- a/source/blender/src/editsound.c +++ b/source/blender/src/editsound.c @@ -148,7 +148,7 @@ void winqreadsoundspace(ScrArea *sa, void *spacedata, BWinEvent *evt) first= 0; CFRA= cfra; update_for_newframe(); - force_draw_plus(SPACE_VIEW3D, 1); + force_draw_all(0); } else PIL_sleep_ms(30); diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 4fbf92d646e..19e2e4b6245 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -5405,7 +5405,9 @@ uiBlock *uiNewBlock(ListBase *lb, char *name, short dt, short font, short win) int getsizex, getsizey; bwin_getsize(win, &getsizex, &getsizey); - block->aspect= 2.0/( (getsizex)*block->winmat[0][0]); + /* TODO - investigate why block->winmat[0][0] is negative + * in the image view when viewRedrawForce is called */ + block->aspect= 2.0/fabs( (getsizex)*block->winmat[0][0]); } uiSetCurFont(block, font); diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index 2d8b0c81175..fb2bfe5b605 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -756,6 +756,13 @@ static void poselib_keytag_pose (tPoseLib_PreviewData *pld) */ static void poselib_preview_get_next (tPoseLib_PreviewData *pld, int step) { + /* check if we no longer have search-string, but don't have any marker */ + if (pld->marker == NULL) { + if ((step) && (pld->searchstr[0] == 0)) + pld->marker= pld->act->markers.first; + } + + /* the following operations assume that there is a starting point and direction */ if ((pld->marker) && (step)) { /* search-string dictates a special approach */ if (pld->searchstr[0]) { @@ -1262,9 +1269,14 @@ void poselib_preview_poses (Object *ob, short apply_active) /* get search-string */ index= pld.search_cursor; - memcpy(&tempstr[0], &pld.searchstr[0], index); - tempstr[index]= '|'; - memcpy(&tempstr[index+1], &pld.searchstr[index], 64-index); + if (IN_RANGE(index, 0, 64)) { + memcpy(&tempstr[0], &pld.searchstr[0], index); + tempstr[index]= '|'; + memcpy(&tempstr[index+1], &pld.searchstr[index], 64-index); + } + else { + strncpy(tempstr, pld.searchstr, 64); + } /* get marker name */ if (pld.marker) diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index 046d14c990d..f47f14a605c 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -52,6 +52,7 @@ #include "BIF_interface_icons.h" #include "BLI_blenlib.h" +#include "BLI_dynstr.h" #include "blendef.h" // CLAMP #include "datatoc.h" @@ -784,6 +785,33 @@ char *BIF_ThemeColorsPup(int spacetype) return cp; } +char *BIF_ThemeColorSetsPup (short inc_custom) +{ + DynStr *pupds= BLI_dynstr_new(); + char *str; + char buf[48]; + int i; + + /* add title first (and the "default" entry) */ + BLI_dynstr_append(pupds, "Bone Color Set%t|Default Colors%x0|"); + + /* loop through set indices, adding them */ + for (i=1; i<21; i++) { + sprintf(buf, "%d - Theme Color Set%%x%d|", i, i); + BLI_dynstr_append(pupds, buf); + } + + /* add the 'custom' entry */ + if (inc_custom) + BLI_dynstr_append(pupds, "Custom Set %x-1"); + + /* convert to normal MEM_malloc'd string */ + str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); + + return str; +} + void BIF_SetTheme(ScrArea *sa) { if(sa==NULL) { // called for safety, when delete themes diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 3b8bb4c3929..58420604c83 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -4844,9 +4844,9 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if( cfra!=CFRA || first ) { first= 0; - + CFRA= cfra; - force_draw(0); + force_draw_all(0); update_for_newframe(); /* for audio scrubbing */ } else PIL_sleep_ms(30); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 10e49cdd218..562d9a4934d 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -3623,7 +3623,7 @@ void special_aftertrans_update(TransInfo *t) } } } - else if (t->spacetype == SPACE_ACTION) { + if (t->spacetype == SPACE_ACTION) { void *data; short datatype; diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 4af5ac4d5d2..b3a3a47152a 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -332,6 +332,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); PyObject *gameLogic = initGameLogic(startscene); + PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module. initGameKeys(); initPythonConstraintBinding(); @@ -399,7 +400,14 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, exitstring = ketsjiengine->GetExitString(); // when exiting the mainloop - dictionaryClearByHand(gameLogic); + + // Clears the dictionary by hand: + // This prevents, extra references to global variables + // inside the GameLogic dictionary when the python interpreter is finalized. + // which allows the scene to safely delete them :) + // see: (space.c)->start_game + PyDict_Clear(PyModule_GetDict(gameLogic)); + ketsjiengine->StopEngine(); exitGamePythonScripting(); networkdevice->Disconnect(); @@ -591,6 +599,7 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); PyObject *gameLogic = initGameLogic(startscene); + PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module initGameKeys(); initPythonConstraintBinding(); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 73d2870720a..220d174d464 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -483,9 +483,9 @@ void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer) } } -void KX_BlenderRenderTools::Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short texture_flag) +void KX_BlenderRenderTools::Update2DFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text) { - m_filtermanager.EnableFilter(filtermode, pass, text, texture_flag); + m_filtermanager.EnableFilter(propNames, gameObj, filtermode, pass, text); } void KX_BlenderRenderTools::Render2DFilters(RAS_ICanvas* canvas) diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index 7748e31156d..8abce1b8c3e 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -101,7 +101,7 @@ public: virtual void MotionBlur(RAS_IRasterizer* rasterizer); - virtual void Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short texture_flag); + virtual void Update2DFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text); virtual void Render2DFilters(RAS_ICanvas* canvas); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index f3e22cd297a..1f1ac6da119 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1847,7 +1847,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie, int aspect_width; int aspect_height; vector<MT_Vector3> inivel,iniang; - + set<Group*> grouplist; // list of groups to be converted + set<Object*> allblobj; // all objects converted + set<Object*> groupobj; // objects from groups (never in active layer) + if (alwaysUseExpandFraming) { frame_type = RAS_FrameSettings::e_frame_extend; aspect_width = canvas->GetWidth(); @@ -1919,6 +1922,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for (SETLOOPER(blenderscene, base)) { Object* blenderobject = base->object; + allblobj.insert(blenderobject); + KX_GameObject* gameobj = gameobject_from_blenderobject( base->object, kxscene, @@ -2046,7 +2051,9 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); gameobj->Bucketize(); - + + if (gameobj->IsDupliGroup()) + grouplist.insert(blenderobject->dup_group); } else { @@ -2073,6 +2080,188 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } + if (!grouplist.empty()) + { + // now convert the group referenced by dupli group object + // keep track of all groups already converted + set<Group*> allgrouplist = grouplist; + set<Group*> tempglist; + // recurse + while (!grouplist.empty()) + { + set<Group*>::iterator git; + tempglist.clear(); + tempglist.swap(grouplist); + for (git=tempglist.begin(); git!=tempglist.end(); git++) + { + Group* group = *git; + GroupObject* go; + for(go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next) + { + Object* blenderobject = go->ob; + if (converter->FindGameObject(blenderobject) == NULL) + { + allblobj.insert(blenderobject); + groupobj.insert(blenderobject); + KX_GameObject* gameobj = gameobject_from_blenderobject( + blenderobject, + kxscene, + rendertools, + converter, + blenderscene); + + // this code is copied from above except that + // object from groups are never is active layer + bool isInActiveLayer = false; + bool addobj=true; + + if (converter->addInitFromFrame) + if (!isInActiveLayer) + addobj=false; + + if (gameobj&&addobj) + { + MT_Point3 posPrev; + MT_Matrix3x3 angor; + if (converter->addInitFromFrame) + blenderscene->r.cfra=blenderscene->r.sfra; + + MT_Point3 pos = MT_Point3( + blenderobject->loc[0]+blenderobject->dloc[0], + blenderobject->loc[1]+blenderobject->dloc[1], + blenderobject->loc[2]+blenderobject->dloc[2] + ); + MT_Vector3 eulxyz = MT_Vector3( + blenderobject->rot[0], + blenderobject->rot[1], + blenderobject->rot[2] + ); + MT_Vector3 scale = MT_Vector3( + blenderobject->size[0], + blenderobject->size[1], + blenderobject->size[2] + ); + if (converter->addInitFromFrame){//rcruiz + float eulxyzPrev[3]; + blenderscene->r.cfra=blenderscene->r.sfra-1; + update_for_newframe(); + MT_Vector3 tmp=pos-MT_Point3(blenderobject->loc[0]+blenderobject->dloc[0], + blenderobject->loc[1]+blenderobject->dloc[1], + blenderobject->loc[2]+blenderobject->dloc[2] + ); + eulxyzPrev[0]=blenderobject->rot[0]; + eulxyzPrev[1]=blenderobject->rot[1]; + eulxyzPrev[2]=blenderobject->rot[2]; + + double fps = (double) blenderscene->r.frs_sec/ + (double) blenderscene->r.frs_sec_base; + + tmp.scale(fps, fps, fps); + inivel.push_back(tmp); + tmp=eulxyz-eulxyzPrev; + tmp.scale(fps, fps, fps); + iniang.push_back(tmp); + blenderscene->r.cfra=blenderscene->r.sfra; + update_for_newframe(); + } + + gameobj->NodeSetLocalPosition(pos); + gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz)); + gameobj->NodeSetLocalScale(scale); + gameobj->NodeUpdateGS(0,true); + + BL_ConvertIpos(blenderobject,gameobj,converter); + // TODO: expand to multiple ipos per mesh + Material *mat = give_current_material(blenderobject, 1); + if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter); + + sumolist->Add(gameobj->AddRef()); + + BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer); + + + gameobj->SetName(blenderobject->id.name); + + // templist to find Root Parents (object with no parents) + templist->Add(gameobj->AddRef()); + + // update children/parent hierarchy + if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame)) + { + // blender has an additional 'parentinverse' offset in each object + SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks()); + + // define a normal parent relationship for this node. + KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New(); + parentinversenode->SetParentRelation(parent_relation); + + parentChildLink pclink; + pclink.m_blenderchild = blenderobject; + pclink.m_gamechildnode = parentinversenode; + vec_parent_child.push_back(pclink); + + float* fl = (float*) blenderobject->parentinv; + MT_Transform parinvtrans(fl); + parentinversenode->SetLocalPosition(parinvtrans.getOrigin()); + parentinversenode->SetLocalOrientation(parinvtrans.getBasis()); + + parentinversenode->AddChild(gameobj->GetSGNode()); + } + + // needed for python scripting + logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj); + + // needed for dynamic object morphing + logicmgr->RegisterGameObj(gameobj, blenderobject); + for (int i = 0; i < gameobj->GetMeshCount(); i++) + logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject); + + converter->RegisterGameObject(gameobj, blenderobject); + // this was put in rapidly, needs to be looked at more closely + // only draw/use objects in active 'blender' layers + + logicbrick_conversionlist->Add(gameobj->AddRef()); + + if (converter->addInitFromFrame){ + posPrev=gameobj->NodeGetWorldPosition(); + angor=gameobj->NodeGetWorldOrientation(); + } + if (isInActiveLayer) + { + objectlist->Add(gameobj->AddRef()); + //tf.Add(gameobj->GetSGNode()); + + gameobj->NodeUpdateGS(0,true); + gameobj->Bucketize(); + + } + else + { + //we must store this object otherwise it will be deleted + //at the end of this function if it is not a root object + inactivelist->Add(gameobj->AddRef()); + + } + if (gameobj->IsDupliGroup()) + { + // check that the group is not already converted + if (allgrouplist.insert(blenderobject->dup_group).second) + grouplist.insert(blenderobject->dup_group); + } + if (converter->addInitFromFrame){ + gameobj->NodeSetLocalPosition(posPrev); + gameobj->NodeSetLocalOrientation(angor); + } + + } + if (gameobj) + gameobj->Release(); + } + } + } + } + } + if (blenderscene->camera) { KX_Camera *gamecamera= (KX_Camera*) converter->FindGameObject(blenderscene->camera); @@ -2081,15 +2270,18 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } // Set up armatures - for(SETLOOPER(blenderscene, base)){ - if (base->object->type==OB_MESH){ - Mesh *me = (Mesh*)base->object->data; + set<Object*>::iterator oit; + for(oit=allblobj.begin(); oit!=allblobj.end(); oit++) + { + Object* blenderobj = *oit; + if (blenderobj->type==OB_MESH){ + Mesh *me = (Mesh*)blenderobj->data; if (me->dvert){ - KX_GameObject *obj = converter->FindGameObject(base->object); + KX_GameObject *obj = converter->FindGameObject(blenderobj); - if (base->object->parent && base->object->parent->type==OB_ARMATURE && base->object->partype==PARSKEL){ - KX_GameObject *par = converter->FindGameObject(base->object->parent); + if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){ + KX_GameObject *par = converter->FindGameObject(blenderobj->parent); if (par) ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par); } @@ -2174,7 +2366,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { meshobj = gameobj->GetMesh(0); } - BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,activeLayerBitInfo,physics_engine,converter,processCompoundChildren); + int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0; + BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren); } processCompoundChildren = true; @@ -2189,7 +2382,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { meshobj = gameobj->GetMesh(0); } - BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,activeLayerBitInfo,physics_engine,converter,processCompoundChildren); + int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0; + BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren); } @@ -2311,22 +2505,25 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,executePriority, activeLayerBitInfo,isInActiveLayer,rendertools,converter); + int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; + bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; + BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,executePriority, layerMask,isInActiveLayer,rendertools,converter); } for ( i=0;i<logicbrick_conversionlist->GetCount();i++) { KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,executePriority,activeLayerBitInfo,isInActiveLayer,converter); + int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; + bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; + BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,executePriority,layerMask,isInActiveLayer,converter); } for ( i=0;i<logicbrick_conversionlist->GetCount();i++) { KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,activeLayerBitInfo,isInActiveLayer,canvas,converter); + int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; + bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; + BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter); } // apply the initial state to controllers for ( i=0;i<logicbrick_conversionlist->GetCount();i++) @@ -2344,5 +2541,19 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // Calculate the scene btree - // too slow - commented out. //kxscene->SetNodeTree(tf.MakeTree()); + + // instantiate dupli group, we will loop trough the object + // that are in active layers. Note that duplicating group + // has the effect of adding objects at the end of objectlist. + // Only loop through the first part of the list. + int objcount = objectlist->GetCount(); + for (i=0;i<objcount;i++) + { + KX_GameObject* gameobj = (KX_GameObject*) objectlist->GetValue(i); + if (gameobj->IsDupliGroup()) + { + kxscene->DupliGroupRecurse(gameobj, 0); + } + } } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h index 57a404ad72b..315ad18c42c 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.h +++ b/source/gameengine/Converter/BL_DeformableGameObject.h @@ -60,6 +60,7 @@ public: { if (m_pDeformer) m_pDeformer->Relink (map); + KX_GameObject::Relink(map); }; void ProcessReplica(KX_GameObject* replica); diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index eb5c1467ea5..b2e54539b19 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -109,6 +109,13 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) vector<IpoCurve*>::iterator it; void *poin; int type; + // the shape drivers use the bone matrix as input. Must + // update the matrix now + Object* par_arma = m_armobj->GetArmatureObject(); + m_armobj->ApplyPose(); + where_is_pose( par_arma ); + PoseApplied(true); + for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) { // no need to set a specific time: this curve has a driver IpoCurve *icu = *it; diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index d3442fe5298..f96c40c098f 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -66,7 +66,8 @@ BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj, m_armobj(arma), m_lastArmaUpdate(-1), m_defbase(&bmeshobj->defbase), - m_releaseobject(false) + m_releaseobject(false), + m_poseApplied(false) { Mat4CpyMat4(m_obmat, bmeshobj->obmat); }; @@ -98,32 +99,28 @@ BL_SkinDeformer::~BL_SkinDeformer() m_armobj->Release(); } -bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *) +bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) { size_t i, j; - if (!Update()) - // no need to update the cache - return false; + // update the vertex in m_transverts + Update(); - // Update all materials at once, so we can do the above update test - // without ending up with some materials not updated - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); - mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + // The vertex cache can only be updated for this deformer: + // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) + // share the same mesh (=the same cache). As the rendering is done per polymaterial + // cycling through the objects, the entire mesh cache cannot be updated in one shot. + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + // For each array + for (i=0; i<vertexarrays.size(); i++) { + KX_VertexArray& vertexarray = (*vertexarrays[i]); - // For each array - for (i=0; i<vertexarrays.size(); i++) { - KX_VertexArray& vertexarray = (*vertexarrays[i]); - - // For each vertex - // copy the untransformed data from the original mvert - for (j=0; j<vertexarray.size(); j++) { - RAS_TexVert& v = vertexarray[j]; - v.SetXYZ(m_transverts[v.getOrigIndex()]); - } + // For each vertex + // copy the untransformed data from the original mvert + for (j=0; j<vertexarray.size(); j++) { + RAS_TexVert& v = vertexarray[j]; + v.SetXYZ(m_transverts[v.getOrigIndex()]); } } @@ -153,9 +150,11 @@ bool BL_SkinDeformer::Update(void) /* XXX note: where_is_pose() (from BKE_armature.h) calculates all matrices needed to start deforming */ /* but it requires the blender object pointer... */ - Object* par_arma = m_armobj->GetArmatureObject(); - where_is_pose( par_arma ); + if (!PoseApplied()){ + m_armobj->ApplyPose(); + where_is_pose( par_arma ); + } /* store verts locally */ VerifyStorage(); @@ -180,7 +179,8 @@ bool BL_SkinDeformer::Update(void) /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); - + /* reset for next frame */ + PoseApplied(false); /* indicate that the m_transverts and normals are up to date */ return true; } diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index f35db8273c4..d3fc5ae2a81 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -81,10 +81,13 @@ public: virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); + bool PoseApplied() + { return m_poseApplied; } + void PoseApplied(bool applied) + { m_poseApplied = applied; } bool PoseUpdated(void) { if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) { - m_armobj->ApplyPose(); return true; } return false; @@ -102,6 +105,7 @@ protected: ListBase* m_defbase; float m_obmat[4][4]; // the reference matrix for skeleton deform bool m_releaseobject; + bool m_poseApplied; }; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 1f87e9d9ac7..8739fb109fd 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -503,7 +503,7 @@ void BL_ConvertActuators(char* maggiename, case ACT_PROPERTY: { bPropertyActuator* propact = (bPropertyActuator*) bact->data; - CValue* destinationObj = NULL; + SCA_IObject* destinationObj = NULL; /* here the destinationobject is searched. problem with multiple scenes: other scenes @@ -539,7 +539,7 @@ void BL_ConvertActuators(char* maggiename, // does the 'original' for replication exists, and // is it in a non-active layer ? - CValue* originalval = NULL; + SCA_IObject* originalval = NULL; if (editobact->ob && !(editobact->ob->lay & activeLayerBitInfo)) originalval = converter->FindGameObject(editobact->ob); @@ -1000,7 +1000,7 @@ void BL_ConvertActuators(char* maggiename, } tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, - _2dfilter->float_arg,_2dfilter->int_arg,_2dfilter->texture_flag,ketsjiEngine->GetRasterizer(),rendertools); + _2dfilter->float_arg,_2dfilter->int_arg,ketsjiEngine->GetRasterizer(),rendertools); if (_2dfilter->text) { diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index f0195d5df82..48136eb9dc3 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -405,7 +405,20 @@ bool CValue::RemoveProperty(const STR_String & inName) return false; } - +// +// Get Property Names +// +vector<STR_String> CValue::GetPropertyNames() +{ + vector<STR_String> result; + if(!m_pNamedPropertyArray) return result; + for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin(); + !(it == m_pNamedPropertyArray->end());it++) + { + result.push_back((*it).first); + } + return result; +} // // Clear all properties diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 561e5521d60..bcf231cf4f0 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -286,6 +286,7 @@ public: STR_String GetPropertyText(const STR_String & inName,const STR_String& deftext=""); // Get text description of property with name <inName>, returns an empty string if there is no property named <inName> float GetPropertyNumber(const STR_String& inName,float defnumber); virtual bool RemoveProperty(const STR_String & inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed + virtual vector<STR_String> GetPropertyNames(); virtual void ClearProperties(); // Clear all properties virtual void SetPropertiesModified(bool inModified); // Set all properties' modified flag to <inModified> diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 56249bb52ec..96a770a553f 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -7,7 +7,6 @@ #endif #include <iostream> - SCA_2DFilterActuator::~SCA_2DFilterActuator() { } @@ -18,7 +17,6 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( short flag, float float_arg, int int_arg, - short texture_flag, RAS_IRasterizer* rasterizer, RAS_IRenderTools* rendertools, PyTypeObject* T) @@ -26,11 +24,15 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( m_type(type), m_flag(flag), m_int_arg(int_arg), - m_texture_flag(texture_flag), m_float_arg(float_arg), m_rasterizer(rasterizer), m_rendertools(rendertools) { + m_gameObj = NULL; + if(gameobj){ + m_propNames = gameobj->GetPropertyNames(); + m_gameObj = gameobj; + } } void SCA_2DFilterActuator::SetShaderText(STR_String text) @@ -52,8 +54,6 @@ CValue* SCA_2DFilterActuator::GetReplica() bool SCA_2DFilterActuator::Update() { - bool result = false; - bool bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); @@ -74,7 +74,7 @@ bool SCA_2DFilterActuator::Update() } else if(m_type < RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS) { - m_rendertools->Update2DFilter(m_type, m_int_arg, m_shaderText, m_texture_flag); + m_rendertools->Update2DFilter(m_propNames, m_gameObj, m_type, m_int_arg, m_shaderText); } return true; } diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h index 451a7b9491a..7ec07cf5b19 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h @@ -5,18 +5,17 @@ #include "RAS_IRenderTools.h" #include "SCA_IActuator.h" - class SCA_2DFilterActuator : public SCA_IActuator { Py_Header; private: - + vector<STR_String> m_propNames; + void * m_gameObj; RAS_2DFilterManager::RAS_2DFILTER_MODE m_type; short m_flag; float m_float_arg; int m_int_arg; - short m_texture_flag; STR_String m_shaderText; RAS_IRasterizer* m_rasterizer; RAS_IRenderTools* m_rendertools; @@ -29,7 +28,6 @@ public: short flag, float float_arg, int int_arg, - short texture_flag, RAS_IRasterizer* rasterizer, RAS_IRenderTools* rendertools, PyTypeObject* T=&Type diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index f6efd485adb..e73358bc1e8 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -82,7 +82,10 @@ void SCA_ILogicBrick::ReParent(SCA_IObject* parent) m_gameobj = parent; } - +void SCA_ILogicBrick::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + // nothing to do +} CValue* SCA_ILogicBrick::Calc(VALUE_OPERATOR op, CValue *val) { diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index 80bc6ae3b86..c28711ac0f6 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -32,6 +32,8 @@ #include "Value.h" #include "SCA_IObject.h" #include "BoolValue.h" +#include "GEN_Map.h" +#include "GEN_HashedPtr.h" class SCA_ILogicBrick : public CValue { @@ -59,6 +61,7 @@ public: SCA_IObject* GetParent(); virtual void ReParent(SCA_IObject* parent); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); // act as a BoolValue (with value IsPositiveTrigger) virtual CValue* Calc(VALUE_OPERATOR op, CValue *val); diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index c5bb4a41552..25b4af696ea 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -306,7 +306,7 @@ const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist) } #endif -void SCA_IObject::Suspend(void) +void SCA_IObject::Suspend() { if ((!m_ignore_activity_culling) && (!m_suspended)) { diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index ebe1cd51863..7062f2cef6a 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -42,7 +42,7 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,CValue* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T ) +SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T ) : SCA_IActuator(gameobj,T), m_type(acttype), m_propname(propname), @@ -51,14 +51,14 @@ SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,CValue* sourceOb { // protect ourselves against someone else deleting the source object // don't protect against ourselves: it would create a dead lock - if (m_sourceObj && m_sourceObj != GetParent()) - m_sourceObj->AddRef(); + if (m_sourceObj) + m_sourceObj->RegisterActuator(this); } SCA_PropertyActuator::~SCA_PropertyActuator() { - if (m_sourceObj && m_sourceObj != GetParent()) - m_sourceObj->Release(); + if (m_sourceObj) + m_sourceObj->UnregisterActuator(this); } bool SCA_PropertyActuator::Update() @@ -185,10 +185,31 @@ void SCA_PropertyActuator::ProcessReplica() // no need to check for self reference like in the constructor: // the replica will always have a different parent if (m_sourceObj) - m_sourceObj->AddRef(); + m_sourceObj->RegisterActuator(this); SCA_IActuator::ProcessReplica(); } +bool SCA_PropertyActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == m_sourceObj) + { + // this object is being deleted, we cannot continue to track it. + m_sourceObj = NULL; + return true; + } + return false; +} + +void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_sourceObj]; + if (h_obj) { + if (m_sourceObj) + m_sourceObj->UnregisterActuator(this); + m_sourceObj = (SCA_IObject*)(*h_obj); + m_sourceObj->RegisterActuator(this); + } +} /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index f8305901c51..1e435684572 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -52,7 +52,7 @@ class SCA_PropertyActuator : public SCA_IActuator int m_type; STR_String m_propname; STR_String m_exprtxt; - CValue* m_sourceObj; // for copy property actuator + SCA_IObject* m_sourceObj; // for copy property actuator public: @@ -60,7 +60,7 @@ public: SCA_PropertyActuator( SCA_IObject* gameobj, - CValue* sourceObj, + SCA_IObject* sourceObj, const STR_String& propname, const STR_String& expr, int acttype, @@ -74,7 +74,9 @@ public: GetReplica( ); - void ProcessReplica(); + virtual void ProcessReplica(); + virtual bool UnlinkObject(SCA_IObject* clientobj); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual bool Update(); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 76386079bdf..01ae4072335 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -116,7 +116,7 @@ CValue* SCA_PythonController::GetReplica() void SCA_PythonController::SetScriptText(const STR_String& text) { - m_scriptText = "import GameLogic\n" + text; + m_scriptText = text; m_bModified = true; } @@ -354,8 +354,10 @@ SCA_PythonController::PyGetSensor(PyObject* self, PyObject* value) return sensor->AddRef(); } } - - PyErr_SetString(PyExc_AttributeError, "Unable to find requested sensor"); + + char emsg[96]; + PyOS_snprintf( emsg, sizeof( emsg ), "Unable to find requested sensor \"%s\"", scriptArg ); + PyErr_SetString(PyExc_AttributeError, emsg); return NULL; } @@ -382,8 +384,10 @@ SCA_PythonController::PyGetActuator(PyObject* self, PyObject* value) return actua->AddRef(); } } - - PyErr_SetString(PyExc_AttributeError, "Unable to find requested actuator"); + + char emsg[96]; + PyOS_snprintf( emsg, sizeof( emsg ), "Unable to find requested actuator \"%s\"", scriptArg ); + PyErr_SetString(PyExc_AttributeError, emsg); return NULL; } diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index a5017574873..8b828393c67 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -602,9 +602,9 @@ void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer) } } -void GPC_RenderTools::Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short texture_flag) +void GPC_RenderTools::Update2DFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text) { - m_filtermanager.EnableFilter(filtermode, pass, text, texture_flag); + m_filtermanager.EnableFilter(propNames, gameObj, filtermode, pass, text); } void GPC_RenderTools::Render2DFilters(RAS_ICanvas* canvas) diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index cb7193f3513..8fae3d2b305 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -142,7 +142,7 @@ public: virtual void MotionBlur(RAS_IRasterizer* rasterizer); - virtual void Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short texture_flag); + virtual void Update2DFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text); virtual void Render2DFilters(RAS_ICanvas* canvas); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index d6908b53d40..b5ebffb9378 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -644,7 +644,7 @@ bool GPG_Application::startEngine(void) PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest); m_ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(m_rasterizer, m_canvas); - PyObject *gameLogic = initGameLogic(startscene); + PyDict_SetItemString(dictionaryobject, "GameLogic", initGameLogic(startscene)); // Same as importing the module initGameKeys(); initPythonConstraintBinding(); diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 70443ced7a9..e25deaf05a9 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -13,11 +13,13 @@ #include "KX_ClientObjectInfo.h" #include "PHY_IPhysicsEnvironment.h" +#include "CcdPhysicsEnvironment.h" KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna) : KX_IPhysicsController(dyna,(PHY_IPhysicsController*)this), -CcdPhysicsController(ci) +CcdPhysicsController(ci), +m_savedCollisionFlags(0) { } @@ -161,14 +163,34 @@ void KX_BulletPhysicsController::setRigidBody(bool rigid) { } -void KX_BulletPhysicsController::SuspendDynamics() +void KX_BulletPhysicsController::SuspendDynamics(bool ghost) { - GetRigidBody()->setActivationState(DISABLE_SIMULATION); - + btRigidBody *body = GetRigidBody(); + if (body->getActivationState() != DISABLE_SIMULATION) + { + btBroadphaseProxy* handle = body->getBroadphaseHandle(); + m_savedCollisionFlags = body->getCollisionFlags(); + m_savedCollisionFilterGroup = handle->m_collisionFilterGroup; + m_savedCollisionFilterMask = handle->m_collisionFilterMask; + body->setActivationState(DISABLE_SIMULATION); + GetPhysicsEnvironment()->updateCcdPhysicsController(this, + btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)), + btBroadphaseProxy::StaticFilter, + btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + } } + void KX_BulletPhysicsController::RestoreDynamics() { - GetRigidBody()->forceActivationState(ACTIVE_TAG); + btRigidBody *body = GetRigidBody(); + if (body->getActivationState() == DISABLE_SIMULATION) + { + GetRigidBody()->forceActivationState(ACTIVE_TAG); + GetPhysicsEnvironment()->updateCcdPhysicsController(this, + m_savedCollisionFlags, + m_savedCollisionFilterGroup, + m_savedCollisionFilterMask); + } } SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode) diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index 0853755dffa..3d7c7e5b030 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -7,7 +7,10 @@ class KX_BulletPhysicsController : public KX_IPhysicsController ,public CcdPhysicsController { - +private: + int m_savedCollisionFlags; + short int m_savedCollisionFilterGroup; + short int m_savedCollisionFilterMask; public: KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna); @@ -39,7 +42,7 @@ public: virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - virtual void SuspendDynamics(); + virtual void SuspendDynamics(bool ghost); virtual void RestoreDynamics(); virtual SG_Controller* GetReplica(class SG_Node* destnode); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 27f4870de10..0a97b6f0a2f 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -49,7 +49,7 @@ STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; KX_CameraActuator::KX_CameraActuator( SCA_IObject* gameobj, - CValue *obj, + SCA_IObject *obj, MT_Scalar hght, MT_Scalar minhght, MT_Scalar maxhght, @@ -63,11 +63,14 @@ KX_CameraActuator::KX_CameraActuator( m_maxHeight (maxhght), m_x (xytog) { + if (m_ob) + m_ob->RegisterActuator(this); } KX_CameraActuator::~KX_CameraActuator() { - //nothing to do + if (m_ob) + m_ob->UnregisterActuator(this); } CValue* @@ -81,9 +84,36 @@ GetReplica( return replica; }; +void KX_CameraActuator::ProcessReplica() +{ + if (m_ob) + m_ob->RegisterActuator(this); + SCA_IActuator::ProcessReplica(); +} +bool KX_CameraActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == m_ob) + { + // this object is being deleted, we cannot continue to track it. + m_ob = NULL; + return true; + } + return false; +} +void KX_CameraActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_ob]; + if (h_obj) { + if (m_ob) + m_ob->UnregisterActuator(this); + m_ob = (SCA_IObject*)(*h_obj); + m_ob->RegisterActuator(this); + } +} + /* three functions copied from blender arith... don't know if there's an equivalent */ static float Kx_Normalize(float *n) @@ -181,8 +211,14 @@ static void Kx_VecUpMat3(float *vec, float mat[][3], short axis) bool KX_CameraActuator::Update(double curtime, bool frame) { - bool result = true; + /* wondering... is it really neccesary/desirable to suppress negative */ + /* events here? */ + bool bNegativeEvent = IsNegativeEvent(); + RemoveAllEvents(); + if (bNegativeEvent || !m_ob) + return false; + KX_GameObject *obj = (KX_GameObject*) GetParent(); MT_Point3 from = obj->NodeGetWorldPosition(); MT_Matrix3x3 frommat = obj->NodeGetWorldOrientation(); @@ -195,13 +231,6 @@ bool KX_CameraActuator::Update(double curtime, bool frame) float mindistsq, maxdistsq, distsq; float mat[3][3]; - /* wondering... is it really neccesary/desirable to suppress negative */ - /* events here? */ - bool bNegativeEvent = IsNegativeEvent(); - RemoveAllEvents(); - - if (bNegativeEvent) return false; - /* The rules: */ /* CONSTRAINT 1: not implemented */ /* CONSTRAINT 2: can camera see actor? */ @@ -315,7 +344,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame) actormat[2][0]= mat[0][2]; actormat[2][1]= mat[1][2]; actormat[2][2]= mat[2][2]; obj->NodeSetLocalOrientation(actormat); - return result; + return true; } CValue *KX_CameraActuator::findObject(char *obName) @@ -404,7 +433,11 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* gameobj; if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj)) { - m_ob = (CValue*)gameobj; + if (m_ob) + m_ob->UnregisterActuator(this); + m_ob = (SCA_IObject*)gameobj; + if (m_ob) + m_ob->RegisterActuator(this); Py_Return; } PyErr_Clear(); @@ -412,10 +445,13 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, char* objectname; if (PyArg_ParseTuple(args, "s", &objectname)) { - CValue *object = (CValue*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname)); + SCA_IObject *object = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname)); if(object) { + if (m_ob != NULL) + m_ob->UnregisterActuator(this); m_ob = object; + m_ob->RegisterActuator(this); Py_Return; } } diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index eb007e403ec..488b36922b0 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -49,7 +49,7 @@ class KX_CameraActuator : public SCA_IActuator Py_Header; private : /** Object that will be tracked. */ - CValue *m_ob; + SCA_IObject *m_ob; /** height (float), */ //const MT_Scalar m_height; @@ -87,7 +87,7 @@ private : SCA_IObject *gameobj, //const CValue *ob, - CValue *ob, + SCA_IObject *ob, MT_Scalar hght, MT_Scalar minhght, MT_Scalar maxhght, @@ -103,6 +103,7 @@ private : /** Methods Inherited from CValue */ CValue* GetReplica(); + virtual void ProcessReplica(); /** Methods inherited from SCA_IActuator */ @@ -110,7 +111,10 @@ private : double curtime, bool frame ); + virtual bool UnlinkObject(SCA_IObject* clientobj); + /** Methods inherited from SCA_ILogicBrick */ + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 2ac4f909077..1845fdd7b50 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -61,6 +61,8 @@ typedef unsigned long uint_ptr; #include "KX_RayCast.h" #include "KX_PythonInit.h" #include "KX_PyMath.h" +#include "SCA_IActuator.h" +#include "SCA_ISensor.h" // This file defines relationships between parents and children // in the game engine. @@ -238,6 +240,10 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) if (rootlist->RemoveValue(this)) // the object was in parent list, decrement ref count as it's now removed Release(); + if (m_pPhysicsController1) + { + m_pPhysicsController1->SuspendDynamics(true); + } } } @@ -258,6 +264,10 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) if (!rootlist->SearchValue(this)) // object was not in root list, add it now and increment ref count rootlist->Add(AddRef()); + if (m_pPhysicsController1) + { + m_pPhysicsController1->RestoreDynamics(); + } } } @@ -832,7 +842,7 @@ void KX_GameObject::Resume(void) } } -void KX_GameObject::Suspend(void) +void KX_GameObject::Suspend() { if ((!m_ignore_activity_culling) && (!m_suspended)) { @@ -1660,6 +1670,20 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, * --------------------------------------------------------------------- */ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter) { - /* intentionally empty ? */ + // we will relink the sensors and actuators that use object references + // if the object is part of the replicated hierarchy, use the new + // object reference instead + SCA_SensorList& sensorlist = GetSensors(); + SCA_SensorList::iterator sit; + for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++) + { + (*sit)->Relink(map_parameter); + } + SCA_ActuatorList& actuatorlist = GetActuators(); + SCA_ActuatorList::iterator ait; + for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++) + { + (*ait)->Relink(map_parameter); + } } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index ddbf863aa1a..eba154e1094 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -47,6 +47,7 @@ #include "KX_Scene.h" #include "KX_KetsjiEngine.h" /* for m_anim_framerate */ #include "KX_IPhysicsController.h" /* for suspend/resume */ +#include "DNA_object_types.h" #define KX_OB_DYNAMIC 1 @@ -392,6 +393,13 @@ public: m_pBlenderObject = obj; } + bool IsDupliGroup() + { + return (m_pBlenderObject && + (m_pBlenderObject->transflag & OB_DUPLIGROUP) && + m_pBlenderObject->dup_group != NULL) ? true : false; + } + /** * Set the Scene graph node for this game object. * warning - it is your responsibility to make sure diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index 2ec66a883eb..bc4cc185a04 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -78,7 +78,7 @@ public: virtual MT_Vector3 getReactionForce()=0; virtual void setRigidBody(bool rigid)=0; - virtual void SuspendDynamics()=0; + virtual void SuspendDynamics(bool ghost=false)=0; virtual void RestoreDynamics()=0; virtual SG_Controller* GetReplica(class SG_Node* destnode)=0; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 20187a193ba..db099d56b55 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -231,7 +231,10 @@ void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer) } - +/* + * At the moment the GameLogic module is imported into 'pythondictionary' after this function is called. + * if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand. + */ void KX_KetsjiEngine::SetPythonDictionary(PyObject* pythondictionary) { MT_assert(pythondictionary); diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index d69871275b9..89699d80031 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -135,9 +135,6 @@ CValue* KX_NearSensor::GetReplica() void KX_NearSensor::ReParent(SCA_IObject* parent) { - - SCA_ISensor::ReParent(parent); - m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); m_client_info->m_sensors.push_back(this); @@ -151,6 +148,7 @@ void KX_NearSensor::ReParent(SCA_IObject* parent) */ ((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL); SynchronizeTransform(); + SCA_ISensor::ReParent(parent); } diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp index 4e45ce484e3..8b0a6dafc22 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp @@ -177,7 +177,7 @@ void KX_OdePhysicsController::setRigidBody(bool rigid) } -void KX_OdePhysicsController::SuspendDynamics() +void KX_OdePhysicsController::SuspendDynamics(bool) { ODEPhysicsController::SuspendDynamics(); } diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h index 07a0bee9775..c96c71c81f9 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.h +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h @@ -74,7 +74,7 @@ public: virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); - virtual void SuspendDynamics(); + virtual void SuspendDynamics(bool); virtual void RestoreDynamics(); diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 8b379bcd44f..fd1b56838e2 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -46,19 +46,22 @@ KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj, int mode, - CValue *ob, + SCA_IObject *ob, PyTypeObject* T) : SCA_IActuator(gameobj, T), m_mode(mode), m_ob(ob) { + if (m_ob) + m_ob->RegisterActuator(this); } KX_ParentActuator::~KX_ParentActuator() { - /* intentionally empty */ + if (m_ob) + m_ob->UnregisterActuator(this); } @@ -73,6 +76,36 @@ CValue* KX_ParentActuator::GetReplica() return replica; } +void KX_ParentActuator::ProcessReplica() +{ + if (m_ob) + m_ob->RegisterActuator(this); + SCA_IActuator::ProcessReplica(); +} + + +bool KX_ParentActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == m_ob) + { + // this object is being deleted, we cannot continue to track it. + m_ob = NULL; + return true; + } + return false; +} + +void KX_ParentActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_ob]; + if (h_obj) { + if (m_ob) + m_ob->UnregisterActuator(this); + m_ob = (SCA_IObject*)(*h_obj); + m_ob->RegisterActuator(this); + } +} + bool KX_ParentActuator::Update() @@ -87,7 +120,8 @@ bool KX_ParentActuator::Update() KX_Scene *scene = PHY_GetActiveScene(); switch (m_mode) { case KX_PARENT_SET: - obj->SetParent(scene, (KX_GameObject*)m_ob); + if (m_ob) + obj->SetParent(scene, (KX_GameObject*)m_ob); break; case KX_PARENT_REMOVE: obj->RemoveParent(scene); @@ -148,7 +182,11 @@ PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* args, PyObjec PyObject* gameobj; if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj)) { - m_ob = (CValue*)gameobj; + if (m_ob != NULL) + m_ob->UnregisterActuator(this); + m_ob = (SCA_IObject*)gameobj; + if (m_ob) + m_ob->RegisterActuator(this); Py_Return; } PyErr_Clear(); @@ -156,10 +194,13 @@ PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* args, PyObjec char* objectname; if (PyArg_ParseTuple(args, "s", &objectname)) { - CValue *object = (CValue*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname)); + SCA_IObject *object = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname)); if(object) { + if (m_ob != NULL) + m_ob->UnregisterActuator(this); m_ob = object; + m_ob->RegisterActuator(this); Py_Return; } } diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index 86dcd4e6c12..93b07cd424b 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -47,7 +47,7 @@ class KX_ParentActuator : public SCA_IActuator int m_mode; /** Object to set as parent */ - CValue *m_ob; + SCA_IObject *m_ob; @@ -62,12 +62,15 @@ class KX_ParentActuator : public SCA_IActuator KX_ParentActuator(class SCA_IObject* gameobj, int mode, - CValue *ob, + SCA_IObject *ob, PyTypeObject* T=&Type); virtual ~KX_ParentActuator(); virtual bool Update(); virtual CValue* GetReplica(); + virtual void ProcessReplica(); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); + virtual bool UnlinkObject(SCA_IObject* clientobj); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 433e0636833..61ed8b6a8e4 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -828,20 +828,9 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook Py_FatalError("can't initialize module GameLogic"); } - return d; + return m; } -void dictionaryClearByHand(PyObject *dict) -{ - // Clears the dictionary by hand: - // This prevents, extra references to global variables - // inside the GameLogic dictionary when the python interpreter is finalized. - // which allows the scene to safely delete them :) - // see: (space.c)->start_game - if(dict) PyDict_Clear(dict); -} - - // Python Sandbox code // override builtin functions import() and open() diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index c7d8f1b78bc..41cf7fd67b3 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -47,7 +47,6 @@ PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur void exitGamePlayerPythonScripting(); PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level); void exitGamePythonScripting(); -void dictionaryClearByHand(PyObject *dict); void PHY_SetActiveScene(class KX_Scene* scene); class KX_Scene* PHY_GetActiveScene(); diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 987e0b946b2..bf2ba18f490 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -80,10 +80,7 @@ CValue* KX_RadarSensor::GetReplica() { KX_RadarSensor* replica = new KX_RadarSensor(*this); replica->m_colliders = new CListValue(); - replica->m_bCollision = false; - replica->m_bTriggered= false; - replica->m_hitObject = NULL; - replica->m_bLastTriggered = false; + replica->Init(); // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -92,6 +89,10 @@ CValue* KX_RadarSensor::GetReplica() if (replica->m_physCtrl) { replica->m_physCtrl = replica->m_physCtrl->GetReplica(); + if (replica->m_physCtrl) + { + replica->m_physCtrl->setNewClientInfo(replica->m_client_info); + } } //todo: make sure replication works fine! diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 76ce086ab97..e36891b56f4 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -48,7 +48,7 @@ /* ------------------------------------------------------------------------- */ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, - CValue* original, + SCA_IObject *original, int time, SCA_IScene* scene, const MT_Vector3& linvel, @@ -61,6 +61,9 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, m_linear_velocity(linvel), m_localFlag(local) { + if (m_OriginalObject) + m_OriginalObject->RegisterActuator(this); + m_lastCreatedObject = NULL; m_timeProp = time; } @@ -69,6 +72,8 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, KX_SCA_AddObjectActuator::~KX_SCA_AddObjectActuator() { + if (m_OriginalObject) + m_OriginalObject->UnregisterActuator(this); if (m_lastCreatedObject) m_lastCreatedObject->Release(); } @@ -108,12 +113,40 @@ CValue* KX_SCA_AddObjectActuator::GetReplica() // this will copy properties and so on... replica->ProcessReplica(); - replica->m_lastCreatedObject=NULL; CValue::AddDataToReplica(replica); return replica; } +void KX_SCA_AddObjectActuator::ProcessReplica() +{ + if (m_OriginalObject) + m_OriginalObject->RegisterActuator(this); + m_lastCreatedObject=NULL; + SCA_IActuator::ProcessReplica(); +} + +bool KX_SCA_AddObjectActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == m_OriginalObject) + { + // this object is being deleted, we cannot continue to track it. + m_OriginalObject = NULL; + return true; + } + return false; +} + +void KX_SCA_AddObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_OriginalObject]; + if (h_obj) { + if (m_OriginalObject) + m_OriginalObject->UnregisterActuator(this); + m_OriginalObject = (SCA_IObject*)(*h_obj); + m_OriginalObject->RegisterActuator(this); + } +} /* ------------------------------------------------------------------------- */ @@ -181,7 +214,11 @@ PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self, PyObject* gameobj; if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj)) { - m_OriginalObject = (CValue*)gameobj; + if (m_OriginalObject != NULL) + m_OriginalObject->UnregisterActuator(this); + m_OriginalObject = (SCA_IObject*)gameobj; + if (m_OriginalObject) + m_OriginalObject->RegisterActuator(this); Py_Return; } PyErr_Clear(); @@ -189,8 +226,11 @@ PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self, char* objectname; if (PyArg_ParseTuple(args, "s", &objectname)) { - m_OriginalObject= (CValue*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));; - + if (m_OriginalObject != NULL) + m_OriginalObject->UnregisterActuator(this); + m_OriginalObject = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));; + if (m_OriginalObject) + m_OriginalObject->RegisterActuator(this); Py_Return; } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 2126a646303..1359f39278d 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -53,7 +53,7 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator int m_timeProp; /// Original object reference (object to replicate) - CValue* m_OriginalObject; + SCA_IObject* m_OriginalObject; /// Object will be added to the following scene SCA_IScene* m_scene; @@ -75,7 +75,7 @@ public: KX_SCA_AddObjectActuator( SCA_IObject *gameobj, - CValue* original, + SCA_IObject *original, int time, SCA_IScene* scene, const MT_Vector3& linvel, @@ -89,6 +89,15 @@ public: GetReplica( ) ; + virtual void + ProcessReplica(); + + virtual bool + UnlinkObject(SCA_IObject* clientobj); + + virtual void + Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); + virtual bool Update(); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 065800379d8..1bdd4002805 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -66,6 +66,8 @@ #include "SG_Controller.h" #include "SG_IObject.h" #include "SG_Tree.h" +#include "DNA_group_types.h" +#include "BKE_anim.h" #include "KX_SG_NodeRelationships.h" @@ -429,6 +431,11 @@ void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gam KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CValue* gameobj) { + // for group duplication, limit the duplication of the hierarchy to the + // objects that are part of the group. + if (!IsObjectInGroup(gameobj)) + return NULL; + KX_GameObject* orgobj = (KX_GameObject*)gameobj; KX_GameObject* newobj = (KX_GameObject*)orgobj->GetReplica(); m_map_gameobject_to_replica.insert(orgobj, newobj); @@ -506,6 +513,11 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal // hierarchy that's because first ALL bricks must exist in the new // replica of the hierarchy in order to make cross-links work properly // ! +// It is VERY important that the order of sensors and actuators in +// the replicated object is preserved: it is is used to reconnect the logic. +// This method is more robust then using the bricks name in case of complex +// group replication. The replication of logic bricks is done in +// SCA_IObject::ReParentLogic(), make sure it preserves the order of the bricks. void KX_Scene::ReplicateLogic(KX_GameObject* newobj) { // also relink the controller to sensors/actuators @@ -528,37 +540,38 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj) for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());its++) { SCA_ISensor* oldsensor = (*its); - STR_String name = oldsensor->GetName(); - //find this name in the list - SCA_ISensor* newsensor = newobj->FindSensor(name); + SCA_IObject* oldsensorobj = oldsensor->GetParent(); + SCA_IObject* newsensorobj = NULL; - if (newsensor) + // the original owner of the sensor has been replicated? + void **h_obj = m_map_gameobject_to_replica[oldsensorobj]; + if (h_obj) + newsensorobj = (SCA_IObject*)(*h_obj); + if (!newsensorobj) { - // relink this newsensor to the controller - m_logicmgr->RegisterToSensor(cont,newsensor); + // no, then the sensor points outside the hierachy, keep it the same + if (m_objectlist->SearchValue(oldsensorobj)) + // only replicate links that points to active objects + m_logicmgr->RegisterToSensor(cont,oldsensor); } else { - // it can be linked somewhere in the hierarchy or... - for (vector<KX_GameObject*>::iterator git = m_logicHierarchicalGameObjects.begin(); - !(git==m_logicHierarchicalGameObjects.end());++git) - { - newsensor = (*git)->FindSensor(name); - if (newsensor) - break; - } + // yes, then the new sensor has the same position + SCA_SensorList& sensorlist = oldsensorobj->GetSensors(); + SCA_SensorList::iterator sit; + SCA_ISensor* newsensor = NULL; + int sensorpos; - if (newsensor) - { - // relink this newsensor to the controller somewhere else within this - // hierarchy - m_logicmgr->RegisterToSensor(cont,newsensor); - } - else + for (sensorpos=0, sit=sensorlist.begin(); sit!=sensorlist.end(); sit++, sensorpos++) { - // must be an external sensor, so... - m_logicmgr->RegisterToSensor(cont,oldsensor); + if ((*sit) == oldsensor) + { + newsensor = newsensorobj->GetSensors().at(sensorpos); + break; + } } + assert(newsensor != NULL); + m_logicmgr->RegisterToSensor(cont,newsensor); } } @@ -566,38 +579,40 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj) for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());ita++) { SCA_IActuator* oldactuator = (*ita); - STR_String name = oldactuator->GetName(); - //find this name in the list - SCA_IActuator* newactuator = newobj->FindActuator(name); - if (newactuator) + SCA_IObject* oldactuatorobj = oldactuator->GetParent(); + SCA_IObject* newactuatorobj = NULL; + + // the original owner of the sensor has been replicated? + void **h_obj = m_map_gameobject_to_replica[oldactuatorobj]; + if (h_obj) + newactuatorobj = (SCA_IObject*)(*h_obj); + + if (!newactuatorobj) { - // relink this newsensor to the controller - m_logicmgr->RegisterToActuator(cont,newactuator); - newactuator->SetUeberExecutePriority(m_ueberExecutionPriority); + // no, then the sensor points outside the hierachy, keep it the same + if (m_objectlist->SearchValue(oldactuatorobj)) + // only replicate links that points to active objects + m_logicmgr->RegisterToActuator(cont,oldactuator); } else { - // it can be linked somewhere in the hierarchy or... - for (vector<KX_GameObject*>::iterator git = m_logicHierarchicalGameObjects.begin(); - !(git==m_logicHierarchicalGameObjects.end());++git) - { - newactuator= (*git)->FindActuator(name); - if (newactuator) - break; - } + // yes, then the new sensor has the same position + SCA_ActuatorList& actuatorlist = oldactuatorobj->GetActuators(); + SCA_ActuatorList::iterator ait; + SCA_IActuator* newactuator = NULL; + int actuatorpos; - if (newactuator) + for (actuatorpos=0, ait=actuatorlist.begin(); ait!=actuatorlist.end(); ait++, actuatorpos++) { - // relink this actuator to the controller somewhere else within this - // hierarchy - m_logicmgr->RegisterToActuator(cont,newactuator); - newactuator->SetUeberExecutePriority(m_ueberExecutionPriority); - } - else - { - // must be an external actuator, so... - m_logicmgr->RegisterToActuator(cont,oldactuator); + if ((*ait) == oldactuator) + { + newactuator = newactuatorobj->GetActuators().at(actuatorpos); + break; + } } + assert(newactuator != NULL); + m_logicmgr->RegisterToActuator(cont,newactuator); + newactuator->SetUeberExecutePriority(m_ueberExecutionPriority); } } } @@ -605,6 +620,146 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj) newobj->ResetState(); } +void KX_Scene::DupliGroupRecurse(CValue* obj, int level) +{ + KX_GameObject* groupobj = (KX_GameObject*) obj; + KX_GameObject* replica; + KX_GameObject* gameobj; + Object* blgroupobj = groupobj->GetBlenderObject(); + Group* group; + GroupObject *go; + vector<KX_GameObject*> duplilist; + + if (!groupobj->IsDupliGroup() || + level>MAX_DUPLI_RECUR) + return; + + // we will add one group at a time + m_logicHierarchicalGameObjects.clear(); + m_map_gameobject_to_replica.clear(); + m_ueberExecutionPriority++; + // for groups will do something special: + // we will force the creation of objects to those in the group only + // Again, this is match what Blender is doing (it doesn't care of parent relationship) + m_groupGameObjects.clear(); + + group = blgroupobj->dup_group; + for(go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next) + { + Object* blenderobj = go->ob; + if (blgroupobj == blenderobj) + // this check is also in group_duplilist() + continue; + gameobj = m_sceneConverter->FindGameObject(blenderobj); + if (gameobj == NULL) + { + // this object has not been converted!!! + // Should not happen as dupli group are created automatically + continue; + } + if (blenderobj->lay & group->layer==0) + { + // object is not visible in the 3D view, will not be instantiated + continue; + } + m_groupGameObjects.insert(gameobj); + } + + set<CValue*>::iterator oit; + for (oit=m_groupGameObjects.begin(); oit != m_groupGameObjects.end(); oit++) + { + gameobj = (KX_GameObject*)(*oit); + if (gameobj->GetParent() != NULL) + { + // this object is not a top parent. Either it is the child of another + // object in the group and it will be added automatically when the parent + // is added. Or it is the child of an object outside the group and the group + // is inconsistent, skip it anyway + continue; + } + replica = (KX_GameObject*) AddNodeReplicaObject(NULL,gameobj); + // add to 'rootparent' list (this is the list of top hierarchy objects, updated each frame) + m_parentlist->Add(replica->AddRef()); + + // recurse replication into children nodes + NodeList& children = gameobj->GetSGNode()->GetSGChildren(); + + replica->GetSGNode()->ClearSGChildren(); + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* orgnode = (*childit); + SG_Node* childreplicanode = orgnode->GetSGReplica(); + if (childreplicanode) + replica->GetSGNode()->AddChild(childreplicanode); + } + // don't replicate logic now: we assume that the objects in the group can have + // logic relationship, even outside parent relationship + // In order to match 3D view, the position of groupobj is used as a + // transformation matrix instead of the new position. This means that + // the group reference point is 0,0,0 + + // get the rootnode's scale + MT_Vector3 newscale = groupobj->NodeGetWorldScaling(); + // set the replica's relative scale with the rootnode's scale + replica->NodeSetRelativeScale(newscale); + + MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); + + MT_Point3 newpos = groupobj->NodeGetWorldPosition() + + newscale*(groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldPosition()); + replica->NodeSetLocalPosition(newpos); + + if (replica->GetPhysicsController()) + { + replica->GetPhysicsController()->setPosition(newpos); + replica->GetPhysicsController()->setOrientation(newori.getRotation()); + replica->GetPhysicsController()->setScaling(newscale); + } + + replica->GetSGNode()->UpdateWorldData(0); + replica->GetSGNode()->SetBBox(gameobj->GetSGNode()->BBox()); + replica->GetSGNode()->SetRadius(gameobj->GetSGNode()->Radius()); + // done with replica + replica->Release(); + } + + // the logic must be replicated first because we need + // the new logic bricks before relinking + vector<KX_GameObject*>::iterator git; + for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) + { + (*git)->ReParentLogic(); + } + + // relink any pointers as necessary, sort of a temporary solution + for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) + { + // this will also relink the actuator to objects within the hierarchy + (*git)->Relink(&m_map_gameobject_to_replica); + // add the object in the layer of the parent + (*git)->SetLayer(groupobj->GetLayer()); + } + + // replicate crosslinks etc. between logic bricks + for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) + { + ReplicateLogic((*git)); + } + + // now look if object in the hierarchy have dupli group and recurse + for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) + { + if ((*git) != groupobj && (*git)->IsDupliGroup()) + // can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects + duplilist.push_back((*git)); + } + + for (git = duplilist.begin(); !(git == duplilist.end()); ++git) + { + DupliGroupRecurse((*git), level+1); + } +} SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, @@ -614,6 +769,7 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, m_logicHierarchicalGameObjects.clear(); m_map_gameobject_to_replica.clear(); + m_groupGameObjects.clear(); // todo: place a timebomb in the object, for temporarily objects :) // lifespan of zero means 'this object lives forever' @@ -647,24 +803,26 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, { SG_Node* orgnode = (*childit); SG_Node* childreplicanode = orgnode->GetSGReplica(); - replica->GetSGNode()->AddChild(childreplicanode); + if (childreplicanode) + replica->GetSGNode()->AddChild(childreplicanode); } - // relink any pointers as necessary, sort of a temporary solution + // now replicate logic vector<KX_GameObject*>::iterator git; for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) { + (*git)->ReParentLogic(); + } + + // relink any pointers as necessary, sort of a temporary solution + for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) + { + // this will also relink the actuators in the hierarchy (*git)->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent (*git)->SetLayer(parentobj->GetLayer()); } - // now replicate logic - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - (*git)->ReParentLogic(); - } - // replicate crosslinks etc. between logic bricks for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) { diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 28dee1b5893..80a2abe287a 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -216,6 +216,16 @@ protected: */ std::vector<KX_GameObject*> m_logicHierarchicalGameObjects; + /** + * This temporary variable will contain the list of + * object that can be added during group instantiation. + * objects outside this list will not be added (can + * happen with children that are outside the group). + * Used in AddReplicaObject. If the list is empty, it + * means don't care. + */ + std::set<CValue*> m_groupGameObjects; + /** * Pointer to system variable passed in in constructor * only used in constructor so we do not need to keep it @@ -291,6 +301,12 @@ public: * Update all transforms according to the scenegraph. */ void UpdateParents(double curtime); + void DupliGroupRecurse(CValue* gameobj, int level); + bool IsObjectInGroup(CValue* gameobj) + { + return (m_groupGameObjects.empty() || + m_groupGameObjects.find(gameobj) != m_groupGameObjects.end()); + } SCA_IObject* AddReplicaObject(CValue* gameobj, CValue* locationobj, int lifespan=0); diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 8f7cffd506f..d6164dc812a 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -58,13 +58,16 @@ KX_SceneActuator::KX_SceneActuator(SCA_IObject *gameobj, m_KetsjiEngine=ketsjiEngine; m_camera = camera; m_nextSceneName = nextSceneName; + if (m_camera) + m_camera->RegisterActuator(this); } /* End of constructor */ KX_SceneActuator::~KX_SceneActuator() { - // there's nothing to be done here, really.... + if (m_camera) + m_camera->UnregisterActuator(this); } /* end of destructor */ @@ -79,6 +82,34 @@ CValue* KX_SceneActuator::GetReplica() return replica; } +void KX_SceneActuator::ProcessReplica() +{ + if (m_camera) + m_camera->RegisterActuator(this); + SCA_IActuator::ProcessReplica(); +} + +bool KX_SceneActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == (SCA_IObject*)m_camera) + { + // this object is being deleted, we cannot continue to track it. + m_camera = NULL; + return true; + } + return false; +} + +void KX_SceneActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_camera]; + if (h_obj) { + if (m_camera) + m_camera->UnregisterActuator(this); + m_camera = (KX_Camera*)(*h_obj); + m_camera->RegisterActuator(this); + } +} bool KX_SceneActuator::Update() @@ -332,7 +363,11 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, PyObject *cam; if (PyArg_ParseTuple(args, "O!", &KX_Camera::Type, &cam)) { + if (m_camera) + m_camera->UnregisterActuator(this); m_camera = (KX_Camera*) cam; + if (m_camera) + m_camera->RegisterActuator(this); Py_Return; } PyErr_Clear(); @@ -345,7 +380,13 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, } KX_Camera *camOb = FindCamera(camName); - if (camOb) m_camera = camOb; + if (camOb) + { + if (m_camera) + m_camera->UnregisterActuator(this); + m_camera = camOb; + m_camera->RegisterActuator(this); + } Py_Return; } diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index cfc79b93f8e..55aaf629d7c 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -82,6 +82,9 @@ class KX_SceneActuator : public SCA_IActuator virtual ~KX_SceneActuator(); virtual CValue* GetReplica(); + virtual void ProcessReplica(); + virtual bool UnlinkObject(SCA_IObject* clientobj); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual bool Update(); diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 949156571a7..34a3baec093 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -291,7 +291,8 @@ PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObje char* name = objectname.Ptr(); if (!name) { - Py_Return; /* internal error */ + PyErr_SetString(PyExc_RuntimeError, "Unable to get sound filename"); + return NULL; } else return PyString_FromString(name); } diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp index 6ea5461dbaa..ffb078b346e 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp @@ -101,7 +101,7 @@ void KX_SumoPhysicsController::SetSumoTransform(bool nondynaonly) } -void KX_SumoPhysicsController::SuspendDynamics() +void KX_SumoPhysicsController::SuspendDynamics(bool) { SumoPhysicsController::SuspendDynamics(); } diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h index 8c061ae4056..33666036c0d 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h @@ -76,7 +76,7 @@ public: void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - void SuspendDynamics(); + void SuspendDynamics(bool); void RestoreDynamics(); virtual void getOrientation(MT_Quaternion& orn); virtual void setOrientation(const MT_Quaternion& orn); diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 731a610c2eb..c580aa4d4e5 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -210,6 +210,18 @@ bool KX_TrackToActuator::UnlinkObject(SCA_IObject* clientobj) return false; } +void KX_TrackToActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_object]; + if (h_obj) { + if (m_object) + m_object->UnregisterActuator(this); + m_object = (SCA_IObject*)(*h_obj); + m_object->RegisterActuator(this); + } +} + + bool KX_TrackToActuator::Update(double curtime, bool frame) { bool result = false; diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index a03aa115baa..1d1cf46d21b 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -68,6 +68,7 @@ class KX_TrackToActuator : public SCA_IActuator virtual void ProcessReplica(); virtual bool UnlinkObject(SCA_IObject* clientobj); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual bool Update(double curtime, bool frame); /* Python part */ diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index c9d346e316d..7f5457121ea 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -466,6 +466,16 @@ void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctr } +void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctrl, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask) +{ + // this function is used when the collisionning group of a controller is changed + // remove and add the collistioning object + btRigidBody* body = ctrl->GetRigidBody(); + + m_dynamicsWorld->removeCollisionObject(body); + body->setCollisionFlags(newCollisionFlags); + m_dynamicsWorld->addCollisionObject(body, newCollisionGroup, newCollisionMask); +} void CcdPhysicsEnvironment::beginFrame() { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 9f14cf6cbef..dff17517b85 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -183,6 +183,8 @@ protected: void removeCcdPhysicsController(CcdPhysicsController* ctrl); + void updateCcdPhysicsController(CcdPhysicsController* ctrl, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask); + btBroadphaseInterface* getBroadphase(); diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt index 18a755afefd..6d53ee53471 100644 --- a/source/gameengine/Rasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/CMakeLists.txt @@ -32,6 +32,8 @@ SET(INC ../../../intern/string ../../../intern/moto/include ../../../extern/glew/include + ../Expressions + ${PYTHON_INC} ) BLENDERLIB(bf_rasterizer "${SRC}" "${INC}") diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile index 1ca3e3b0283..e3b1f274ee5 100644 --- a/source/gameengine/Rasterizer/Makefile +++ b/source/gameengine/Rasterizer/Makefile @@ -41,6 +41,9 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../kernel/gen_system CPPFLAGS += -I../BlenderRoutines +CPPFLAGS += -I../Expressions + +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index 23153fcd86c..958fead33ce 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -52,6 +52,7 @@ #include <config.h> #endif +#include "Value.h" RAS_2DFilterManager::RAS_2DFilterManager(): texturewidth(-1), textureheight(-1), @@ -73,12 +74,14 @@ numberoffilters(0) m_filters[passindex] = 0; m_enabled[passindex] = 0; texflag[passindex] = 0; + m_gameObjects[passindex] = NULL; } texname[0] = texname[1] = texname[2] = -1; } RAS_2DFilterManager::~RAS_2DFilterManager() { + FreeTextures(); } unsigned int RAS_2DFilterManager::CreateShaderProgram(char* shadersource) @@ -150,6 +153,27 @@ unsigned int RAS_2DFilterManager::CreateShaderProgram(int filtermode) } return 0; } +void RAS_2DFilterManager::AnalyseShader(int passindex, vector<STR_String>& propNames) +{ + texflag[passindex] = 0; + if(glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture") != -1) + { + texflag[passindex] |= 0x1; + } + if(glGetUniformLocationARB(m_filters[passindex], "bgl_LuminanceTexture") != -1) + { + texflag[passindex] |= 0x2; + } + + if(m_gameObjects[passindex]) + { + int objProperties = propNames.size(); + int i; + for(i=0; i<objProperties; i++) + if(glGetUniformLocationARB(m_filters[passindex], propNames[i]) != -1) + m_properties[passindex].push_back(propNames[i]); + } +} void RAS_2DFilterManager::StartShaderProgram(int passindex) { @@ -177,7 +201,7 @@ void RAS_2DFilterManager::StartShaderProgram(int passindex) } /* send luminance texture to glsl program if it needs */ - if(texflag[passindex] & 0x1){ + if(texflag[passindex] & 0x2){ uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_LuminanceTexture"); glActiveTextureARB(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, texname[2]); @@ -203,6 +227,17 @@ void RAS_2DFilterManager::StartShaderProgram(int passindex) { glUniform1fARB(uniformLoc,textureheight); } + + int i, objProperties = m_properties[passindex].size(); + for(i=0; i<objProperties; i++) + { + uniformLoc = glGetUniformLocationARB(m_filters[passindex], m_properties[passindex][i]); + if(uniformLoc != -1) + { + float value = ((CValue*)m_gameObjects[passindex])->GetPropertyNumber(m_properties[passindex][i], 0.0); + glUniform1fARB(uniformLoc,value); + } + } } void RAS_2DFilterManager::EndShaderProgram() @@ -210,14 +245,21 @@ void RAS_2DFilterManager::EndShaderProgram() glUseProgramObjectARB(0); } -void RAS_2DFilterManager::SetupTexture() +void RAS_2DFilterManager::FreeTextures() { - if(texname[0]!=-1 || texname[1]!=-1) - { - glDeleteTextures(2, (GLuint*)texname); - } - glGenTextures(3, (GLuint*)texname); + if(texname[0]!=-1) + glDeleteTextures(1, (GLuint*)&texname[0]); + if(texname[1]!=-1) + glDeleteTextures(1, (GLuint*)&texname[1]); + if(texname[2]!=-1) + glDeleteTextures(1, (GLuint*)&texname[2]); +} +void RAS_2DFilterManager::SetupTextures(bool depth, bool luminance) +{ + FreeTextures(); + + glGenTextures(1, (GLuint*)&texname[0]); glBindTexture(GL_TEXTURE_2D, texname[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texturewidth, textureheight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); @@ -226,23 +268,29 @@ void RAS_2DFilterManager::SetupTexture() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glBindTexture(GL_TEXTURE_2D, texname[1]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, texturewidth,textureheight, 0, GL_DEPTH_COMPONENT, - GL_FLOAT,NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, + if(depth){ + glGenTextures(1, (GLuint*)&texname[1]); + glBindTexture(GL_TEXTURE_2D, texname[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, texturewidth,textureheight, + 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE,NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - - glBindTexture(GL_TEXTURE_2D, texname[2]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE16, texturewidth, textureheight, 0, GL_LUMINANCE, - GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + } + + if(luminance){ + glGenTextures(1, (GLuint*)&texname[2]); + glBindTexture(GL_TEXTURE_2D, texname[2]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE16, texturewidth, textureheight, + 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + } } void RAS_2DFilterManager::UpdateOffsetMatrix(int width, int height) @@ -273,62 +321,72 @@ void RAS_2DFilterManager::UpdateOffsetMatrix(int width, int height) textureoffsets[(((i*3)+j)*2)+1] = (-1.0f * yInc) + ((GLfloat)j * yInc); } } - - SetupTexture(); } void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) { + bool need_depth=false; + bool need_luminance=false; + int num_filters = 0; + + int passindex; + if(!isshadersupported) return; + for(passindex =0; passindex<MAX_RENDER_PASS; passindex++) + { + if(m_filters[passindex] && m_enabled[passindex]){ + num_filters ++; + if(texflag[passindex] & 0x1) + need_depth = true; + if(texflag[passindex] & 0x2) + need_luminance = true; + if(need_depth && need_luminance) + break; + } + } + + if(num_filters <= 0) + return; + if(canvaswidth != canvas->GetWidth() || canvasheight != canvas->GetHeight()) { UpdateOffsetMatrix(canvas->GetWidth(), canvas->GetHeight()); + SetupTextures(need_depth, need_luminance); } GLuint viewport[4]={0}; - int passindex; - bool first = true; + if(need_depth){ + glActiveTextureARB(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, texname[1]); + glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0,0, texturewidth,textureheight, 0); + } + + if(need_luminance){ + glActiveTextureARB(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, texname[2]); + glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, 0,0, texturewidth,textureheight, 0); + } + + glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); + glViewport(0, 0, texturewidth, textureheight); + + glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); for(passindex =0; passindex<MAX_RENDER_PASS; passindex++) { if(m_filters[passindex] && m_enabled[passindex]) { - if(first) - { - /* this pass needs depth texture*/ - if(texflag[passindex] & 0x1){ - glActiveTextureARB(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, texname[1]); - glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0,0, texturewidth,textureheight, 0); - } - - /* this pass needs luminance texture*/ - if(texflag[passindex] & 0x2){ - glActiveTextureARB(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, texname[2]); - glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, 0,0, texturewidth,textureheight, 0); - } - - glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); - glViewport(0, 0, texturewidth, textureheight); - - glDisable(GL_DEPTH_TEST); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - first = false; - } - StartShaderProgram(passindex); - glActiveTextureARB(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texname[0]); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, texturewidth, textureheight, 0); - glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_QUADS); @@ -341,15 +399,12 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) } } - if(!first) - { - glEnable(GL_DEPTH_TEST); - glViewport(viewport[0],viewport[1],viewport[2],viewport[3]); - EndShaderProgram(); - } + glEnable(GL_DEPTH_TEST); + glViewport(viewport[0],viewport[1],viewport[2],viewport[3]); + EndShaderProgram(); } -void RAS_2DFilterManager::EnableFilter(RAS_2DFILTER_MODE mode, int pass, STR_String& text, short tflag) +void RAS_2DFilterManager::EnableFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFILTER_MODE mode, int pass, STR_String& text) { if(!isshadersupported) return; @@ -374,16 +429,19 @@ void RAS_2DFilterManager::EnableFilter(RAS_2DFILTER_MODE mode, int pass, STR_Str glDeleteObjectARB(m_filters[pass]); m_enabled[pass] = 0; m_filters[pass] = 0; + m_gameObjects[pass] = NULL; + m_properties[pass].clear(); texflag[pass] = 0; return; } if(mode == RAS_2DFILTER_CUSTOMFILTER) { - texflag[pass] = tflag; if(m_filters[pass]) glDeleteObjectARB(m_filters[pass]); m_filters[pass] = CreateShaderProgram(text.Ptr()); + m_gameObjects[pass] = gameObj; + AnalyseShader(pass, propNames); m_enabled[pass] = 1; return; } diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.h b/source/gameengine/Rasterizer/RAS_2DFilterManager.h index faf7c652388..9d8326b96de 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.h +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.h @@ -28,8 +28,6 @@ #ifndef __RAS_I2DFILTER #define __RAS_I2DFILTER - - #define MAX_RENDER_PASS 100 class RAS_2DFilterManager @@ -37,9 +35,15 @@ class RAS_2DFilterManager private: unsigned int CreateShaderProgram(char* shadersource); unsigned int CreateShaderProgram(int filtermode); + void AnalyseShader(int passindex, vector<STR_String>& propNames); void StartShaderProgram(int passindex); void EndShaderProgram(); + void SetupTextures(bool depth, bool luminance); + void FreeTextures(); + + void UpdateOffsetMatrix(int width, int height); + float textureoffsets[18]; float view[4]; /* texname[0] contains render to texture, texname[1] contains depth texture, texname[2] contains luminance texture*/ @@ -54,6 +58,13 @@ private: short texflag[MAX_RENDER_PASS]; bool isshadersupported; + + unsigned int m_filters[MAX_RENDER_PASS]; + short m_enabled[MAX_RENDER_PASS]; + + // stores object properties to send to shaders in each pass + vector<STR_String> m_properties[MAX_RENDER_PASS]; + void* m_gameObjects[MAX_RENDER_PASS]; public: enum RAS_2DFILTER_MODE { RAS_2DFILTER_ENABLED = -2, @@ -74,19 +85,12 @@ public: RAS_2DFILTER_NUMBER_OF_FILTERS }; - unsigned int m_filters[MAX_RENDER_PASS]; - short m_enabled[MAX_RENDER_PASS]; - RAS_2DFilterManager(); ~RAS_2DFilterManager(); - void SetupTexture(); - - void UpdateOffsetMatrix(int width, int height); - void RenderFilters(RAS_ICanvas* canvas); - void EnableFilter(RAS_2DFILTER_MODE mode, int pass, STR_String& text, short tflag); + void EnableFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFILTER_MODE mode, int pass, STR_String& text); }; #endif diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h index 781f90d4124..54a663ba111 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.h +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h @@ -185,7 +185,7 @@ public: virtual void - Update2DFilter(RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text, short textureflag)=0; + Update2DFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text)=0; virtual void diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript index f077833b850..e6bc657ed6d 100644 --- a/source/gameengine/Rasterizer/SConscript +++ b/source/gameengine/Rasterizer/SConscript @@ -7,7 +7,8 @@ if env['WITH_BF_GLEXT'] == 1: env['CPPFLAGS'].append('-DWITH_GLEXT') -incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include' +incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions' +incs += ' ' + env['BF_PYTHON_INC'] if env['OURPLATFORM']=='win32-vc': cflags = [] diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp index c347bbc6d9a..d0bdac5c8f0 100644 --- a/source/gameengine/SceneGraph/SG_IObject.cpp +++ b/source/gameengine/SceneGraph/SG_IObject.cpp @@ -104,7 +104,7 @@ SetSGClientObject( } - void + bool SG_IObject:: ActivateReplicationCallback( SG_IObject *replica @@ -112,8 +112,10 @@ ActivateReplicationCallback( if (m_callbacks.m_replicafunc) { // Call client provided replication func - m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo); + if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL) + return false; } + return true; }; void diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h index 438ab48c556..7f6bdfbbb1c 100644 --- a/source/gameengine/SceneGraph/SG_IObject.h +++ b/source/gameengine/SceneGraph/SG_IObject.h @@ -202,7 +202,7 @@ public: protected : - void + bool ActivateReplicationCallback( SG_IObject *replica ); diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp index 4e90d7c4653..8de7ac83477 100644 --- a/source/gameengine/SceneGraph/SG_Node.cpp +++ b/source/gameengine/SceneGraph/SG_Node.cpp @@ -68,7 +68,7 @@ SG_Node* SG_Node::GetSGReplica() SG_Node* replica = new SG_Node(*this); if (replica == NULL) return NULL; - ProcessSGReplica(replica); + ProcessSGReplica(&replica); return replica; } @@ -76,25 +76,42 @@ SG_Node* SG_Node::GetSGReplica() void SG_Node:: ProcessSGReplica( - SG_Node* replica + SG_Node** replica ){ // Apply the replication call back function. - ActivateReplicationCallback(replica); + if (!ActivateReplicationCallback(*replica)) + { + delete (*replica); + *replica = NULL; + return; + } // clear the replica node of it's parent. - static_cast<SG_Node*>(replica)->m_SGparent = NULL; + static_cast<SG_Node*>(*replica)->m_SGparent = NULL; if (m_children.begin() != m_children.end()) { // if this node has children, the replica has too, so clear and clone children - replica->ClearSGChildren(); + (*replica)->ClearSGChildren(); NodeList::iterator childit; for (childit = m_children.begin();childit!=m_children.end();++childit) { - replica->AddChild((*childit)->GetSGReplica()); + SG_Node* childnode = (*childit)->GetSGReplica(); + if (childnode) + (*replica)->AddChild(childnode); } } + // Nodes without children and without client object are + // not worth to keep, they will just take up CPU + // This can happen in partial replication of hierarchy + // during group duplication. + if ((*replica)->m_children.empty() && + (*replica)->GetSGClientObject() == NULL) + { + delete (*replica); + *replica = NULL; + } } diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h index f86e3046d93..ffaaad861e2 100644 --- a/source/gameengine/SceneGraph/SG_Node.h +++ b/source/gameengine/SceneGraph/SG_Node.h @@ -205,7 +205,7 @@ private: void ProcessSGReplica( - SG_Node* replica + SG_Node** replica ); /** |