svn merge -r 16320:16369 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Fri, 5 Sep 2008 00:12:01 +0000 (00:12 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Fri, 5 Sep 2008 00:12:01 +0000 (00:12 +0000)
320 files changed:
blenderplayer/CMakeLists.txt
config/darwin-config.py
extern/glew/SConscript
extern/glew/include/GL/glew.h
extern/glew/src/glew.c
intern/ghost/intern/GHOST_SystemWin32.cpp
intern/guardedalloc/MEM_guardedalloc.h
intern/guardedalloc/intern/mallocn.c
intern/memutil/MEM_Allocator.h
intern/memutil/MEM_CacheLimiter.h
intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
intern/moto/include/GEN_Map.h
intern/moto/include/MT_Matrix4x4.h
intern/moto/include/MT_Matrix4x4.inl
intern/opennl/superlu/BLO_sys_types.h
projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj
projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj
release/datafiles/blenderbuttons
release/scripts/bpymodules/BPyTextPlugin.py [new file with mode: 0644]
release/scripts/mesh_cleanup.py
release/scripts/scripttemplate_text_plugin.py [new file with mode: 0644]
release/scripts/sysinfo.py
release/scripts/textplugin_functiondocs.py [new file with mode: 0644]
release/scripts/textplugin_imports.py [new file with mode: 0644]
release/scripts/textplugin_membersuggest.py [new file with mode: 0644]
release/scripts/textplugin_outliner.py [new file with mode: 0644]
release/scripts/textplugin_suggest.py [new file with mode: 0644]
release/scripts/textplugin_templates.py [new file with mode: 0644]
source/Makefile
source/blender/CMakeLists.txt
source/blender/Makefile
source/blender/SConscript
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_bad_level_calls.h
source/blender/blenkernel/BKE_colortools.h
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_suggestions.h [new file with mode: 0644]
source/blender/blenkernel/BKE_text.h
source/blender/blenkernel/BKE_texture.h
source/blender/blenkernel/BKE_utildefines.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/SConscript
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/Makefile
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/colortools.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenkernel/intern/suggestions.c [new file with mode: 0644]
source/blender/blenkernel/intern/text.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/BLI_blenlib.h
source/blender/blenlib/intern/arithb.c
source/blender/blenloader/BLO_sys_types.h
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/gpu/CMakeLists.txt [new file with mode: 0644]
source/blender/gpu/GPU_draw.h [new file with mode: 0644]
source/blender/gpu/GPU_extensions.h [new file with mode: 0644]
source/blender/gpu/GPU_material.h [new file with mode: 0644]
source/blender/gpu/Makefile [new file with mode: 0644]
source/blender/gpu/SConscript [new file with mode: 0644]
source/blender/gpu/intern/Makefile [new file with mode: 0644]
source/blender/gpu/intern/gpu_codegen.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_codegen.h [new file with mode: 0644]
source/blender/gpu/intern/gpu_draw.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_extensions.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_material.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader_material.glsl [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader_material.glsl.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader_vertex.glsl [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader_vertex.glsl.c [new file with mode: 0644]
source/blender/include/BDR_drawmesh.h
source/blender/include/BDR_drawobject.h
source/blender/include/BDR_imagepaint.h
source/blender/include/BIF_drawtext.h
source/blender/include/BIF_gl.h
source/blender/include/BIF_keyval.h
source/blender/include/BIF_meshtools.h
source/blender/include/BIF_resources.h
source/blender/include/BIF_space.h
source/blender/include/BSE_drawview.h
source/blender/include/blendef.h
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesdna/DNA_brush_types.h
source/blender/makesdna/DNA_group_types.h
source/blender/makesdna/DNA_image_types.h
source/blender/makesdna/DNA_ipo_types.h
source/blender/makesdna/DNA_lamp_types.h
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_meshdata_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sensor_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_text_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/DNA_world_types.h
source/blender/nodes/CMakeLists.txt
source/blender/nodes/SConscript
source/blender/nodes/intern/CMP_nodes/Makefile
source/blender/nodes/intern/Makefile
source/blender/nodes/intern/SHD_nodes/Makefile
source/blender/nodes/intern/SHD_nodes/SHD_camera.c
source/blender/nodes/intern/SHD_nodes/SHD_curves.c
source/blender/nodes/intern/SHD_nodes/SHD_geom.c
source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c
source/blender/nodes/intern/SHD_nodes/SHD_invert.c
source/blender/nodes/intern/SHD_nodes/SHD_mapping.c
source/blender/nodes/intern/SHD_nodes/SHD_material.c
source/blender/nodes/intern/SHD_nodes/SHD_math.c
source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c
source/blender/nodes/intern/SHD_nodes/SHD_normal.c
source/blender/nodes/intern/SHD_nodes/SHD_output.c
source/blender/nodes/intern/SHD_nodes/SHD_rgb.c
source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c
source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c
source/blender/nodes/intern/SHD_nodes/SHD_texture.c
source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c
source/blender/nodes/intern/SHD_nodes/SHD_value.c
source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c
source/blender/nodes/intern/SHD_util.h
source/blender/python/BPY_extern.h
source/blender/python/BPY_interface.c
source/blender/python/BPY_menus.c
source/blender/python/BPY_menus.h
source/blender/python/CMakeLists.txt
source/blender/python/SConscript
source/blender/python/api2_2x/Blender.c
source/blender/python/api2_2x/Group.c
source/blender/python/api2_2x/Image.c
source/blender/python/api2_2x/Lamp.c
source/blender/python/api2_2x/MTex.c
source/blender/python/api2_2x/Makefile
source/blender/python/api2_2x/Material.c
source/blender/python/api2_2x/Text.c
source/blender/python/api2_2x/Text.h
source/blender/python/api2_2x/doc/Draw.py
source/blender/python/api2_2x/doc/Group.py
source/blender/python/api2_2x/doc/Text.py
source/blender/radiosity/CMakeLists.txt
source/blender/radiosity/SConscript
source/blender/radiosity/intern/source/Makefile
source/blender/render/intern/include/render_types.h
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/shadbuf.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/zbuf.c
source/blender/src/CMakeLists.txt
source/blender/src/Makefile
source/blender/src/SConscript
source/blender/src/blenderbuttons.c
source/blender/src/buttons_logic.c
source/blender/src/buttons_object.c
source/blender/src/buttons_shading.c
source/blender/src/drawarmature.c
source/blender/src/drawmesh.c
source/blender/src/drawobject.c
source/blender/src/drawtext.c
source/blender/src/drawview.c
source/blender/src/editdeform.c
source/blender/src/editface.c
source/blender/src/editipo_lib.c
source/blender/src/editlattice.c
source/blender/src/editmesh.c
source/blender/src/editmode_undo.c
source/blender/src/editnode.c
source/blender/src/editview.c
source/blender/src/header_image.c
source/blender/src/header_info.c
source/blender/src/header_text.c
source/blender/src/header_view3d.c
source/blender/src/headerbuttons.c
source/blender/src/imagepaint.c
source/blender/src/keyval.c
source/blender/src/meshtools.c
source/blender/src/playanim.c
source/blender/src/previewrender.c
source/blender/src/renderwin.c
source/blender/src/sculptmode.c
source/blender/src/sequence.c
source/blender/src/space.c
source/blender/src/toets.c
source/blender/src/toolbox.c
source/blender/src/usiblender.c
source/blender/src/verse_image.c
source/blender/yafray/intern/export_File.cpp
source/blender/yafray/intern/export_Plugin.cpp
source/creator/CMakeLists.txt
source/creator/Makefile
source/creator/SConscript
source/creator/creator.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/BlenderRoutines/CMakeLists.txt
source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
source/gameengine/BlenderRoutines/KX_BlenderGL.h
source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
source/gameengine/BlenderRoutines/Makefile
source/gameengine/BlenderRoutines/SConscript
source/gameengine/Converter/BL_ArmatureObject.cpp
source/gameengine/Converter/BL_ArmatureObject.h
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/BL_DeformableGameObject.cpp
source/gameengine/Converter/BL_MeshDeformer.cpp
source/gameengine/Converter/BL_MeshDeformer.h
source/gameengine/Converter/BL_ShapeActionActuator.cpp
source/gameengine/Converter/BL_ShapeDeformer.cpp
source/gameengine/Converter/BL_ShapeDeformer.h
source/gameengine/Converter/BL_SkinDeformer.cpp
source/gameengine/Converter/BL_SkinDeformer.h
source/gameengine/Converter/BL_SkinMeshObject.cpp
source/gameengine/Converter/BL_SkinMeshObject.h
source/gameengine/Converter/CMakeLists.txt
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Converter/Makefile
source/gameengine/Converter/SConscript
source/gameengine/Expressions/PyObjectPlus.cpp
source/gameengine/Expressions/Value.cpp
source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
source/gameengine/GameLogic/Joystick/SCA_Joystick.h
source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h
source/gameengine/GameLogic/SCA_ISensor.cpp
source/gameengine/GameLogic/SCA_JoystickManager.cpp
source/gameengine/GameLogic/SCA_JoystickSensor.cpp
source/gameengine/GameLogic/SCA_JoystickSensor.h
source/gameengine/GamePlayer/common/CMakeLists.txt
source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
source/gameengine/GamePlayer/common/GPC_RenderTools.h
source/gameengine/GamePlayer/common/Makefile
source/gameengine/GamePlayer/common/SConscript
source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h
source/gameengine/GamePlayer/ghost/CMakeLists.txt
source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/GamePlayer/ghost/GPG_Application.h
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
source/gameengine/GamePlayer/ghost/Makefile
source/gameengine/GamePlayer/ghost/SConscript
source/gameengine/Ketsji/BL_BlenderShader.cpp
source/gameengine/Ketsji/BL_BlenderShader.h
source/gameengine/Ketsji/BL_Material.h
source/gameengine/Ketsji/BL_Shader.cpp
source/gameengine/Ketsji/BL_Shader.h
source/gameengine/Ketsji/CMakeLists.txt
source/gameengine/Ketsji/KX_BlenderMaterial.cpp
source/gameengine/Ketsji/KX_BlenderMaterial.h
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_ISceneConverter.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_KetsjiEngine.h
source/gameengine/Ketsji/KX_Light.cpp
source/gameengine/Ketsji/KX_Light.h
source/gameengine/Ketsji/KX_MeshProxy.cpp
source/gameengine/Ketsji/KX_PolyProxy.cpp
source/gameengine/Ketsji/KX_PolygonMaterial.cpp
source/gameengine/Ketsji/KX_PolygonMaterial.h
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_PythonInit.h
source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_Scene.h
source/gameengine/Ketsji/KX_VertexProxy.cpp
source/gameengine/Ketsji/KX_VisibilityActuator.cpp
source/gameengine/Ketsji/Makefile
source/gameengine/Ketsji/SConscript
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/PyDoc/GameLogic.py
source/gameengine/PyDoc/KX_GameObject.py
source/gameengine/PyDoc/Rasterizer.py
source/gameengine/Rasterizer/Makefile
source/gameengine/Rasterizer/RAS_BucketManager.cpp
source/gameengine/Rasterizer/RAS_BucketManager.h
source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
source/gameengine/Rasterizer/RAS_IRasterizer.h
source/gameengine/Rasterizer/RAS_IRenderTools.cpp
source/gameengine/Rasterizer/RAS_IRenderTools.h
source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
source/gameengine/Rasterizer/RAS_MaterialBucket.h
source/gameengine/Rasterizer/RAS_MeshObject.cpp
source/gameengine/Rasterizer/RAS_MeshObject.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
source/gameengine/Rasterizer/RAS_Polygon.cpp
source/gameengine/Rasterizer/RAS_Polygon.h
source/gameengine/Rasterizer/RAS_TexVert.cpp
source/gameengine/Rasterizer/RAS_TexVert.h
source/gameengine/Rasterizer/SConscript
source/kernel/gen_system/GEN_Map.h
source/nan_definitions.mk
tools/btools.py

index d90639562d22ca21210f19c1b07360929cf2c63d..e32390466c757eaeeb2575c819cc1597f36f421c 100644 (file)
@@ -90,6 +90,7 @@ IF(UNIX)
     bf_soundsystem 
     bf_kernel 
     bf_nodes
+       bf_gpu
     bf_imbuf
     bf_avi 
     kx_network 
index 8fd6c3251ba64b46be82667cea44b90c0ac87f93..48455d2ce8cc739459da428a3a4747cad459885c 100644 (file)
@@ -143,7 +143,6 @@ BF_FTGL_LIB = 'extern_ftgl'
 
 WITH_BF_GAMEENGINE='true'
 WITH_BF_PLAYER='true'
-WITH_BF_GLEXT= '1'
 
 WITH_BF_ODE = 'false'
 BF_ODE = LIBDIR + '/ode'
index 32b3b478113f22cf2e3eb8ef59e28cd39ed4e199..3badbeb040ef080559903506c4d9279d3ea3a77e 100644 (file)
@@ -9,4 +9,4 @@ sources = ['src/glew.c']
 defs = ''
 incs = 'include'
 
-env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['intern', 'player'], priority=[25, 50])
+env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['blender', 'player'], priority=[50, 50])
index fd3fe10b93822efc3b322ad58bd8a6ba1bfcb32d..6b88e6eb4c91b69d0c06efad6d865f4ea89cfa46 100644 (file)
 ** version 1.2.1 Specification.
 */
 
-/* added this here for blender, should be moved elsewhere */
+#define BLENDER_CHANGES
+
+#ifdef BLENDER_CHANGES
 #define GLEW_STATIC
+#endif
 
 #ifndef __glew_h__
 #define __glew_h__
@@ -1805,6 +1808,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuin
 typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v);
 typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
 
+#ifndef BLENDER_CHANGES
 #define glAttachShader GLEW_GET_FUN(__glewAttachShader)
 #define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation)
 #define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate)
@@ -1898,6 +1902,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint si
 #define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv)
 #define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv)
 #define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer)
+#endif
 
 #define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0)
 
index 593f0e58f7c32c0b880d80804da5319171fa0d09..f20463630dc13d312f9a45f322ba189036bc4128 100644 (file)
@@ -1836,6 +1836,7 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT)
 {
   GLboolean r = GL_FALSE;
 
+#ifndef BLENDER_CHANGES
   r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r;
   r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r;
   r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r;
@@ -1929,6 +1930,7 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT)
   r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r;
   r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r;
   r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r;
+#endif
 
   return r;
 }
index f5c7c08ebfe1d71ec5e68647413009b7485b65a5..7bc20d3873900efb007ec238ab3859a8bc8777dc 100644 (file)
@@ -917,8 +917,12 @@ GHOST_TUns8* GHOST_SystemWin32::getClipboard(int flag) const
        char *buffer;
        char *temp_buff;
        
-       if ( OpenClipboard(NULL) ) {
+       if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) {
                HANDLE hData = GetClipboardData( CF_TEXT );
+               if (hData == NULL) {
+                       CloseClipboard();
+                       return NULL;
+               }
                buffer = (char*)GlobalLock( hData );
                
                temp_buff = (char*) malloc(strlen(buffer)+1);
index d004e7952cc1f427ebe888f26a96732fb9b38b50..1d4c753802b7f3612579a58f774d3ddee54e8513 100644 (file)
@@ -58,8 +58,8 @@
 #ifndef MEM_MALLOCN_H
 #define MEM_MALLOCN_H
 
-/* Needed for FILE* */
-#include "stdio.h"
+#include "stdio.h" /* needed for FILE* */
+#include "BLO_sys_types.h" /* needed for uintptr_t */
 
 #ifdef __cplusplus
 extern "C" {
@@ -123,6 +123,12 @@ extern "C" {
        /** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */
        void MEM_set_memory_debug(void);
 
+       /* Memory usage stats
+        * - MEM_get_memory_in_use is all memory
+        * - MEM_get_mapped_memory_in_use is a subset of all memory */
+       uintptr_t MEM_get_memory_in_use(void);
+       uintptr_t MEM_get_mapped_memory_in_use(void);
+       int MEM_get_memory_blocks_in_use(void);
 
 #ifdef __cplusplus
 }
index a36549d0cc75eb779c61f025d4e78d46f7a89ee2..7bdca7339fcce39879c4adb7491e8e8d2b388dcf 100644 (file)
@@ -49,8 +49,6 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "BLO_sys_types.h" // needed for intptr_t
-
 /* --------------------------------------------------------------------- */
 /* Data definition                                                       */
 /* --------------------------------------------------------------------- */
@@ -113,8 +111,8 @@ static const char *check_memlist(MemHead *memh);
 /* --------------------------------------------------------------------- */
        
 
-volatile int totblock= 0;
-volatile uintptr_t mem_in_use= 0, mmap_in_use= 0;
+static volatile int totblock= 0;
+static volatile uintptr_t mem_in_use= 0, mmap_in_use= 0;
 
 static volatile struct localListBase _membase;
 static volatile struct localListBase *membase = &_membase;
@@ -698,4 +696,19 @@ static const char *check_memlist(MemHead *memh)
        return(name);
 }
 
+uintptr_t MEM_get_memory_in_use(void)
+{
+       return mem_in_use;
+}
+
+uintptr_t MEM_get_mapped_memory_in_use(void)
+{
+       return mmap_in_use;
+}
+
+int MEM_get_memory_blocks_in_use(void)
+{
+       return totblock;
+}
+
 /* eof */
index d5ae94cc6b868727e062f38c392080ca5b3e6453..b2c3c5e82e25544a0f71cd96e1b3dcbe68650b8f 100644 (file)
@@ -25,6 +25,7 @@
 #define __MEM_Allocator_h_included__ 1
 
 #include "guardedalloc/MEM_guardedalloc.h"
+#include "guardedalloc/BLO_sys_types.h"
 
 #ifdef _MSC_VER
 #if _MSC_VER < 1300 // 1200 == VC++ 6.0 according to boost
index cada06ae523f9c673d11610292d2d5c6662fa0ec..43149efc977b3652d5e62e2572cc68460ba5cd80 100644 (file)
@@ -61,11 +61,8 @@ class MEM_CacheLimiter;
 
 #ifndef __MEM_cache_limiter_c_api_h_included__
 extern "C" {
-       extern void MEM_CacheLimiter_set_maximum(int m);
-       extern int MEM_CacheLimiter_get_maximum();
-        // this is rather _ugly_!
-        extern int mem_in_use;
-       extern int mmap_in_use;
+       extern void MEM_CacheLimiter_set_maximum(intptr_t m);
+       extern intptr_t MEM_CacheLimiter_get_maximum();
 };
 #endif
 
@@ -141,7 +138,10 @@ public:
                delete handle;
        }
        void enforce_limits() {
-               int max = MEM_CacheLimiter_get_maximum();
+               intptr_t max = MEM_CacheLimiter_get_maximum();
+               intptr_t mem_in_use= MEM_get_memory_in_use();
+               intptr_t mmap_in_use= MEM_get_mapped_memory_in_use();
+
                if (max == 0) {
                        return;
                }
index 4cf0ef305d415a0353391a747ce368d4f36d5639..d998c9a3e80db05787c367a2d7811694ac80dd39 100644 (file)
 #include "MEM_CacheLimiter.h"
 #include "MEM_CacheLimiterC-Api.h"
 
-static int & get_max() 
+static intptr_t & get_max() 
 {
-       static int m = 32*1024*1024;
+       static intptr_t m = 32*1024*1024;
        return m;
 }
 
-void MEM_CacheLimiter_set_maximum(int m)
+void MEM_CacheLimiter_set_maximum(intptr_t m)
 {
        get_max() = m;
 }
 
-int MEM_CacheLimiter_get_maximum()
+intptr_t MEM_CacheLimiter_get_maximum()
 {
        return get_max();
 }
index 9f56924419ea32be776a65f4345e26d01a140841..d85e9af175b42f5eec446ec868dc84b1530885b6 100644 (file)
@@ -50,6 +50,19 @@ public:
             m_buckets[i] = 0;
         }
     }
+
+       GEN_Map(const GEN_Map& map)
+       {
+               m_num_buckets = map.m_num_buckets;
+               m_buckets = new Entry *[m_num_buckets];
+
+               for (int i = 0; i < m_num_buckets; ++i) {
+                       m_buckets[i] = 0;
+
+                       for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next)
+                               insert(entry->m_key, entry->m_value);
+               }
+       }
     
     int size() { 
         int count=0;
index 823541347b747f57123b5ed8b1f7240bdc7cc1d8..b4ee84a718b5a081a2cfc30ddafd6da93243f982 100644 (file)
@@ -212,6 +212,7 @@ public:
        MT_Matrix4x4 transposed() const; 
        void         transpose();
 
+       MT_Matrix4x4 inverse() const;
        void         invert();
   
 protected:
index a2aa893a6b3045f11bc89a746e55c5b1292d9cd5..074bd6e4b05e66d981c480c85fa192c47bb7009e 100644 (file)
@@ -52,14 +52,14 @@ GEN_INLINE void MT_Matrix4x4::invert()  {
                }
 }
 
-/* We do things slightly different here, because the invert() modifies
- * the buffer itself. This makes it impossible to make this op right
- * away. Like other, still missing facilities, I will repair this
- * later. */
-/* GEN_INLINE T_Matrix4x4 MT_Matrix4x4::inverse() const */
-/*  { */
-/*  } */
+GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::inverse() const
+{
+       MT_Matrix4x4 invmat = *this;
+
+       invmat.invert();
 
+       return invmat;
+}
 
 GEN_INLINE MT_Matrix4x4& MT_Matrix4x4::operator*=(const MT_Matrix4x4& m)
 {
index 5ed3117c8906103134f4b1b3d411a20c5124bfdd..411a8582f9617a5feb9be9bcff2232e3b02622c6 100644 (file)
@@ -54,6 +54,7 @@ extern "C" {
 /* The __intXX are built-in types of the visual complier! So we don't
  * need to include anything else here. */
 
+
 typedef signed __int8  int8_t;
 typedef signed __int16 int16_t;
 typedef signed __int32 int32_t;
@@ -102,6 +103,7 @@ typedef unsigned long uintptr_t;
 
 #endif /* ifdef platform for types */
 
+
 #ifdef _WIN32
 #ifndef htonl
 #define htonl(x) correctByteOrder(x)
index 42dcc843091592263c3db2e00ec4e6974d388159..69db0a950060a73670a6e4187b4d356f09801ee4 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\intern\subsurf_ccg.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\intern\suggestions.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\intern\text.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_subsurf.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\BKE_suggestions.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_text.h">
                        </File>
index 4e362faed69edcf3631ec2314e1a80dd92b07fb6..a358a868143c98c535afa555cb5e3dcd5b5137a4 100644 (file)
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\solid\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x"
+                               AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\solid\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x"
                                PreprocessorDefinitions="JANCODEPANCO;WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG;USE_SUMO_SOLID;WITH_GLEXT"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="1"
                        <Tool
                                Name="VCCLCompilerTool"
                                InlineFunctionExpansion="1"
-                               AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\solid\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x"
+                               AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\solid\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x"
                                PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT"
                                StringPooling="TRUE"
                                RuntimeLibrary="0"
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\solid\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x"
+                               AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\solid\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x"
                                PreprocessorDefinitions="JANCODEPANCO;WIN32;_LIB;EXP_PYTHON_EMBEDDING;_DEBUG;USE_SUMO_SOLID;WITH_GLEXT"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="1"
                        <Tool
                                Name="VCCLCompilerTool"
                                InlineFunctionExpansion="1"
-                               AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\solid\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x"
+                               AdditionalIncludeDirectories="..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\solid\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\sdl\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\python;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\physics;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\network;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\physics\sumo;..\..\..\source\gameengine\physics\dummy;..\..\..\source\gameengine\physics\BlOde;..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\source\gameengine\physics\common;..\..\..\source\gameengine\physics\sumo\include;..\..\..\source\gameengine\physics\common\dummy;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\physics\sumo\fuzzics\include;..\..\..\source\sumo\include;..\..\..\source\sumo\fuzzics\include;..\..\..\source\gameengine\physics\bullet;..\..\..\source\blender\python\api2_2x"
                                PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT"
                                StringPooling="TRUE"
                                RuntimeLibrary="0"
index a4834091692c0cc61b50ad4c1604350d12622b2e..8ae492bcd1facec2ff72e18382550f977d2506a3 100644 (file)
Binary files a/release/datafiles/blenderbuttons and b/release/datafiles/blenderbuttons differ
diff --git a/release/scripts/bpymodules/BPyTextPlugin.py b/release/scripts/bpymodules/BPyTextPlugin.py
new file mode 100644 (file)
index 0000000..5e5c9f5
--- /dev/null
@@ -0,0 +1,814 @@
+"""The BPyTextPlugin Module
+
+Use get_cached_descriptor(txt) to retrieve information about the script held in
+the txt Text object.
+
+Use print_cache_for(txt) to print the information to the console.
+
+Use line, cursor = current_line(txt) to get the logical line and cursor position
+
+Use get_targets(line, cursor) to find out what precedes the cursor:
+       aaa.bbb.cc|c.ddd -> ['aaa', 'bbb', 'cc']
+
+Use resolve_targets(txt, targets) to turn a target list into a usable object if
+one is found to match.
+"""
+
+import bpy, sys, os
+import __builtin__, tokenize
+from Blender.sys import time
+from tokenize import generate_tokens, TokenError, \
+               COMMENT, DEDENT, INDENT, NAME, NEWLINE, NL, STRING, NUMBER
+
+class Definition():
+       """Describes a definition or defined object through its name, line number
+       and docstring. This is the base class for definition based descriptors.
+       """
+       
+       def __init__(self, name, lineno, doc=''):
+               self.name = name
+               self.lineno = lineno
+               self.doc = doc
+
+class ScriptDesc():
+       """Describes a script through lists of further descriptor objects (classes,
+       defs, vars) and dictionaries to built-in types (imports). If a script has
+       not been fully parsed, its incomplete flag will be set. The time of the last
+       parse is held by the time field and the name of the text object from which
+       it was parsed, the name field.
+       """
+       
+       def __init__(self, name, imports, classes, defs, vars, incomplete=False):
+               self.name = name
+               self.imports = imports
+               self.classes = classes
+               self.defs = defs
+               self.vars = vars
+               self.incomplete = incomplete
+               self.parse_due = 0
+       
+       def set_delay(self, delay):
+               self.parse_due = time() + delay
+
+class ClassDesc(Definition):
+       """Describes a class through lists of further descriptor objects (defs and
+       vars). The name of the class is held by the name field and the line on
+       which it is defined is held in lineno.
+       """
+       
+       def __init__(self, name, parents, defs, vars, lineno, doc=''):
+               Definition.__init__(self, name, lineno, doc)
+               self.parents = parents
+               self.defs = defs
+               self.vars = vars
+
+class FunctionDesc(Definition):
+       """Describes a function through its name and list of parameters (name,
+       params) and the line on which it is defined (lineno).
+       """
+       
+       def __init__(self, name, params, lineno, doc=''):
+               Definition.__init__(self, name, lineno, doc)
+               self.params = params
+
+class VarDesc(Definition):
+       """Describes a variable through its name and type (if ascertainable) and the
+       line on which it is defined (lineno). If no type can be determined, type
+       will equal None.
+       """
+       
+       def __init__(self, name, type, lineno):
+               Definition.__init__(self, name, lineno)
+               self.type = type # None for unknown (supports: dict/list/str)
+
+# Context types
+CTX_UNSET = -1
+CTX_NORMAL = 0
+CTX_SINGLE_QUOTE = 1
+CTX_DOUBLE_QUOTE = 2
+CTX_COMMENT = 3
+
+# Python keywords
+KEYWORDS = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global',
+                       'or', 'with', 'assert', 'else', 'if', 'pass', 'yield',
+                       'break', 'except', 'import', 'print', 'class', 'exec', 'in',
+                       'raise', 'continue', 'finally', 'is', 'return', 'def', 'for',
+                       'lambda', 'try' ]
+
+# Module file extensions
+MODULE_EXTS = ['.py', '.pyc', '.pyo', '.pyw', '.pyd']
+
+ModuleType = type(__builtin__)
+NoneScriptDesc = ScriptDesc('', dict(), dict(), dict(), dict(), True)
+
+_modules = {}
+_modules_updated = 0
+_parse_cache = dict()
+
+def _load_module_names():
+       """Searches the sys.path for module files and lists them, along with
+       sys.builtin_module_names, in the global dict _modules.
+       """
+       
+       global _modules
+       
+       for n in sys.builtin_module_names:
+               _modules[n] = None
+       for p in sys.path:
+               if p == '': p = os.curdir
+               if not os.path.isdir(p): continue
+               for f in os.listdir(p):
+                       for ext in MODULE_EXTS:
+                               if f.endswith(ext):
+                                       _modules[f[:-len(ext)]] = None
+                                       break
+
+_load_module_names()
+
+def _trim_doc(doc):
+       """Trims the quotes from a quoted STRING token (eg. "'''text'''" -> "text")
+       """
+       
+       l = len(doc)
+       i = 0
+       while i < l/2 and (doc[i] == "'" or doc[i] == '"'):
+               i += 1
+       return doc[i:-i]
+
+def resolve_targets(txt, targets):
+       """Attempts to return a useful object for the locally or externally defined
+       entity described by targets. If the object is local (defined in txt), a
+       Definition instance is returned. If the object is external (imported or
+       built in), the object itself is returned. If no object can be found, None is
+       returned.
+       """
+       
+       count = len(targets)
+       if count==0: return None
+       
+       obj = None
+       local = None
+       i = 1
+       
+       desc = get_cached_descriptor(txt)
+       b = targets[0].find('(')
+       if b==-1: b = None # Trick to let us use [:b] and get the whole string
+       
+       if desc.classes.has_key(targets[0][:b]):
+               local = desc.classes[targets[0][:b]]
+       elif desc.defs.has_key(targets[0]):
+               local = desc.defs[targets[0]]
+       elif desc.vars.has_key(targets[0]):
+               obj = desc.vars[targets[0]].type
+       
+       if local:
+               while i < count:
+                       b = targets[i].find('(')
+                       if b==-1: b = None
+                       if hasattr(local, 'classes') and local.classes.has_key(targets[i][:b]):
+                               local = local.classes[targets[i][:b]]
+                       elif hasattr(local, 'defs') and local.defs.has_key(targets[i]):
+                               local = local.defs[targets[i]]
+                       elif hasattr(local, 'vars') and local.vars.has_key(targets[i]):
+                               obj = local.vars[targets[i]].type
+                               local = None
+                               i += 1
+                               break
+                       else:
+                               local = None
+                               break
+                       i += 1
+       
+       if local: return local
+       
+       if not obj:
+               if desc.imports.has_key(targets[0]):
+                       obj = desc.imports[targets[0]]
+               else:
+                       builtins = get_builtins()
+                       if builtins.has_key(targets[0]):
+                               obj = builtins[targets[0]]
+       
+       while obj and i < count:
+               if hasattr(obj, targets[i]):
+                       obj = getattr(obj, targets[i])
+               else:
+                       obj = None
+                       break
+               i += 1
+       
+       return obj
+
+def get_cached_descriptor(txt, force_parse=0):
+       """Returns the cached ScriptDesc for the specified Text object 'txt'. If the
+       script has not been parsed in the last 'period' seconds it will be reparsed
+       to obtain this descriptor.
+       
+       Specifying TP_AUTO for the period (default) will choose a period based on the
+       size of the Text object. Larger texts are parsed less often.
+       """
+       
+       global _parse_cache
+       
+       parse = True
+       key = hash(txt)
+       if not force_parse and _parse_cache.has_key(key):
+               desc = _parse_cache[key]
+               if desc.parse_due > time():
+                       parse = desc.incomplete
+       
+       if parse:
+               desc = parse_text(txt)
+       
+       return desc
+
+def parse_text(txt):
+       """Parses an entire script's text and returns a ScriptDesc instance
+       containing information about the script.
+       
+       If the text is not a valid Python script (for example if brackets are left
+       open), parsing may fail to complete. However, if this occurs, no exception
+       is thrown. Instead the returned ScriptDesc instance will have its incomplete
+       flag set and information processed up to this point will still be accessible.
+       """
+       
+       start_time = time()
+       txt.reset()
+       tokens = generate_tokens(txt.readline) # Throws TokenError
+       
+       curl, cursor = txt.getCursorPos()
+       linen = curl + 1 # Token line numbers are one-based
+       
+       imports = dict()
+       imp_step = 0
+       
+       classes = dict()
+       cls_step = 0
+       
+       defs = dict()
+       def_step = 0
+       
+       vars = dict()
+       var1_step = 0
+       var2_step = 0
+       var3_step = 0
+       var_accum = dict()
+       var_forflag = False
+       
+       indent = 0
+       prev_type = -1
+       prev_text = ''
+       incomplete = False
+       
+       while True:
+               try:
+                       type, text, start, end, line = tokens.next()
+               except StopIteration:
+                       break
+               except (TokenError, IndentationError):
+                       incomplete = True
+                       break
+               
+               # Skip all comments and line joining characters
+               if type == COMMENT or type == NL:
+                       continue
+               
+               #################
+               ## Indentation ##
+               #################
+               
+               if type == INDENT:
+                       indent += 1
+               elif type == DEDENT:
+                       indent -= 1
+               
+               #########################
+               ## Module importing... ##
+               #########################
+               
+               imp_store = False
+               
+               # Default, look for 'from' or 'import' to start
+               if imp_step == 0:
+                       if text == 'from':
+                               imp_tmp = []
+                               imp_step = 1
+                       elif text == 'import':
+                               imp_from = None
+                               imp_tmp = []
+                               imp_step = 2
+               
+               # Found a 'from', create imp_from in form '???.???...'
+               elif imp_step == 1:
+                       if text == 'import':
+                               imp_from = '.'.join(imp_tmp)
+                               imp_tmp = []
+                               imp_step = 2
+                       elif type == NAME:
+                               imp_tmp.append(text)
+                       elif text != '.':
+                               imp_step = 0 # Invalid syntax
+               
+               # Found 'import', imp_from is populated or None, create imp_name
+               elif imp_step == 2:
+                       if text == 'as':
+                               imp_name = '.'.join(imp_tmp)
+                               imp_step = 3
+                       elif type == NAME or text == '*':
+                               imp_tmp.append(text)
+                       elif text != '.':
+                               imp_name = '.'.join(imp_tmp)
+                               imp_symb = imp_name
+                               imp_store = True
+               
+               # Found 'as', change imp_symb to this value and go back to step 2
+               elif imp_step == 3:
+                       if type == NAME:
+                               imp_symb = text
+                       else:
+                               imp_store = True
+               
+               # Both imp_name and imp_symb have now been populated so we can import
+               if imp_store:
+                       
+                       # Handle special case of 'import *'
+                       if imp_name == '*':
+                               parent = get_module(imp_from)
+                               imports.update(parent.__dict__)
+                               
+                       else:
+                               # Try importing the name as a module
+                               try:
+                                       if imp_from:
+                                               module = get_module(imp_from +'.'+ imp_name)
+                                       else:
+                                               module = get_module(imp_name)
+                               except (ImportError, ValueError, AttributeError, TypeError):
+                                       # Try importing name as an attribute of the parent
+                                       try:
+                                               module = __import__(imp_from, globals(), locals(), [imp_name])
+                                               imports[imp_symb] = getattr(module, imp_name)
+                                       except (ImportError, ValueError, AttributeError, TypeError):
+                                               pass
+                               else:
+                                       imports[imp_symb] = module
+                       
+                       # More to import from the same module?
+                       if text == ',':
+                               imp_tmp = []
+                               imp_step = 2
+                       else:
+                               imp_step = 0
+               
+               ###################
+               ## Class parsing ##
+               ###################
+               
+               # If we are inside a class then def and variable parsing should be done
+               # for the class. Otherwise the definitions are considered global
+               
+               # Look for 'class'
+               if cls_step == 0:
+                       if text == 'class':
+                               cls_name = None
+                               cls_lineno = start[0]
+                               cls_indent = indent
+                               cls_step = 1
+               
+               # Found 'class', look for cls_name followed by '(' parents ')'
+               elif cls_step == 1:
+                       if not cls_name:
+                               if type == NAME:
+                                       cls_name = text
+                                       cls_sline = False
+                                       cls_parents = dict()
+                                       cls_defs = dict()
+                                       cls_vars = dict()
+                       elif type == NAME:
+                               if classes.has_key(text):
+                                       parent = classes[text]
+                                       cls_parents[text] = parent
+                                       cls_defs.update(parent.defs)
+                                       cls_vars.update(parent.vars)
+                       elif text == ':':
+                               cls_step = 2
+               
+               # Found 'class' name ... ':', now check if it's a single line statement
+               elif cls_step == 2:
+                       if type == NEWLINE:
+                               cls_sline = False
+                       else:
+                               cls_sline = True
+                       cls_doc = ''
+                       cls_step = 3
+               
+               elif cls_step == 3:
+                       if not cls_doc and type == STRING:
+                               cls_doc = _trim_doc(text)
+                       if cls_sline:
+                               if type == NEWLINE:
+                                       classes[cls_name] = ClassDesc(cls_name, cls_parents, cls_defs, cls_vars, cls_lineno, cls_doc)
+                                       cls_step = 0
+                       else:
+                               if type == DEDENT and indent <= cls_indent:
+                                       classes[cls_name] = ClassDesc(cls_name, cls_parents, cls_defs, cls_vars, cls_lineno, cls_doc)
+                                       cls_step = 0
+               
+               #################
+               ## Def parsing ##
+               #################
+               
+               # Look for 'def'
+               if def_step == 0:
+                       if text == 'def':
+                               def_name = None
+                               def_lineno = start[0]
+                               def_step = 1
+               
+               # Found 'def', look for def_name followed by '('
+               elif def_step == 1:
+                       if type == NAME:
+                               def_name = text
+                               def_params = []
+                       elif def_name and text == '(':
+                               def_step = 2
+               
+               # Found 'def' name '(', now identify the parameters upto ')'
+               # TODO: Handle ellipsis '...'
+               elif def_step == 2:
+                       if type == NAME:
+                               def_params.append(text)
+                       elif text == ':':
+                               def_step = 3
+               
+               # Found 'def' ... ':', now check if it's a single line statement
+               elif def_step == 3:
+                       if type == NEWLINE:
+                               def_sline = False
+                       else:
+                               def_sline = True
+                       def_doc = ''
+                       def_step = 4
+               
+               elif def_step == 4:
+                       if type == STRING:
+                               def_doc = _trim_doc(text)
+                       newdef = None
+                       if def_sline:
+                               if type == NEWLINE:
+                                       newdef = FunctionDesc(def_name, def_params, def_lineno, def_doc)
+                       else:
+                               if type == NAME:
+                                       newdef = FunctionDesc(def_name, def_params, def_lineno, def_doc)
+                       if newdef:
+                               if cls_step > 0: # Parsing a class
+                                       cls_defs[def_name] = newdef
+                               else:
+                                       defs[def_name] = newdef
+                               def_step = 0
+               
+               ##########################
+               ## Variable assignation ##
+               ##########################
+               
+               if cls_step > 0: # Parsing a class
+                       # Look for 'self.???'
+                       if var1_step == 0:
+                               if text == 'self':
+                                       var1_step = 1
+                       elif var1_step == 1:
+                               if text == '.':
+                                       var_name = None
+                                       var1_step = 2
+                               else:
+                                       var1_step = 0
+                       elif var1_step == 2:
+                               if type == NAME:
+                                       var_name = text
+                                       if cls_vars.has_key(var_name):
+                                               var_step = 0
+                                       else:
+                                               var1_step = 3
+                       elif var1_step == 3:
+                               if text == '=':
+                                       var1_step = 4
+                               elif text != ',':
+                                       var1_step = 0
+                       elif var1_step == 4:
+                               var_type = None
+                               if type == NUMBER:
+                                       close = end[1]
+                                       if text.find('.') != -1: var_type = float
+                                       else: var_type = int
+                               elif type == STRING:
+                                       close = end[1]
+                                       var_type = str
+                               elif text == '[':
+                                       close = line.find(']', end[1])
+                                       var_type = list
+                               elif text == '(':
+                                       close = line.find(')', end[1])
+                                       var_type = tuple
+                               elif text == '{':
+                                       close = line.find('}', end[1])
+                                       var_type = dict
+                               elif text == 'dict':
+                                       close = line.find(')', end[1])
+                                       var_type = dict
+                               if var_type and close+1 < len(line):
+                                       if line[close+1] != ' ' and line[close+1] != '\t':
+                                               var_type = None
+                               cls_vars[var_name] = VarDesc(var_name, var_type, start[0])
+                               var1_step = 0
+               
+               elif def_step > 0: # Parsing a def
+                       # Look for 'global ???[,???]'
+                       if var2_step == 0:
+                               if text == 'global':
+                                       var2_step = 1
+                       elif var2_step == 1:
+                               if type == NAME:
+                                       if not vars.has_key(text):
+                                               vars[text] = VarDesc(text, None, start[0])
+                               elif text != ',' and type != NL:
+                                       var2_step == 0
+               
+               else: # In global scope
+                       if var3_step == 0:
+                               # Look for names
+                               if text == 'for':
+                                       var_accum = dict()
+                                       var_forflag = True
+                               elif text == '=' or (var_forflag and text == 'in'):
+                                       var_forflag = False
+                                       var3_step = 1
+                               elif type == NAME:
+                                       if prev_text != '.' and not vars.has_key(text):
+                                               var_accum[text] = VarDesc(text, None, start[0])
+                               elif not text in [',', '(', ')', '[', ']']:
+                                       var_accum = dict()
+                                       var_forflag = False
+                       elif var3_step == 1:
+                               if len(var_accum) != 1:
+                                       var_type = None
+                                       vars.update(var_accum)
+                               else:
+                                       var_name = var_accum.keys()[0]
+                                       var_type = None
+                                       if type == NUMBER:
+                                               if text.find('.') != -1: var_type = float
+                                               else: var_type = int
+                                       elif type == STRING: var_type = str
+                                       elif text == '[': var_type = list
+                                       elif text == '(': var_type = tuple
+                                       elif text == '{': var_type = dict
+                                       vars[var_name] = VarDesc(var_name, var_type, start[0])
+                               var3_step = 0
+               
+               #######################
+               ## General utilities ##
+               #######################
+               
+               prev_type = type
+               prev_text = text
+       
+       desc = ScriptDesc(txt.name, imports, classes, defs, vars, incomplete)
+       desc.set_delay(10 * (time()-start_time) + 0.05)
+       
+       global _parse_cache
+       _parse_cache[hash(txt)] = desc
+       return desc
+
+def get_modules(since=1):
+       """Returns the set of built-in modules and any modules that have been
+       imported into the system upto 'since' seconds ago.
+       """
+       
+       global _modules, _modules_updated
+       
+       t = time()
+       if _modules_updated < t - since:
+               _modules.update(sys.modules)
+               _modules_updated = t
+       return _modules.keys()
+
+def suggest_cmp(x, y):
+       """Use this method when sorting a list of suggestions.
+       """
+       
+       return cmp(x[0].upper(), y[0].upper())
+
+def get_module(name):
+       """Returns the module specified by its name. The module itself is imported
+       by this method and, as such, any initialization code will be executed.
+       """
+       
+       mod = __import__(name)
+       components = name.split('.')
+       for comp in components[1:]:
+               mod = getattr(mod, comp)
+       return mod
+
+def type_char(v):
+       """Returns the character used to signify the type of a variable. Use this
+       method to identify the type character for an item in a suggestion list.
+       
+       The following values are returned:
+         'm' if the parameter is a module
+         'f' if the parameter is callable
+         'v' if the parameter is variable or otherwise indeterminable
+       
+       """
+       
+       if isinstance(v, ModuleType):
+               return 'm'
+       elif callable(v):
+               return 'f'
+       else: 
+               return 'v'
+
+def get_context(txt):
+       """Establishes the context of the cursor in the given Blender Text object
+       
+       Returns one of:
+         CTX_NORMAL - Cursor is in a normal context
+         CTX_SINGLE_QUOTE - Cursor is inside a single quoted string
+         CTX_DOUBLE_QUOTE - Cursor is inside a double quoted string
+         CTX_COMMENT - Cursor is inside a comment
+       
+       """
+       
+       l, cursor = txt.getCursorPos()
+       lines = txt.asLines(0, l+1)
+       
+       # FIXME: This method is too slow in large files for it to be called as often
+       # as it is. So for lines below the 1000th line we do this... (quorn)
+       if l > 1000: return CTX_NORMAL
+       
+       # Detect context (in string or comment)
+       in_str = CTX_NORMAL
+       for line in lines:
+               if l == 0:
+                       end = cursor
+               else:
+                       end = len(line)
+                       l -= 1
+               
+               # Comments end at new lines
+               if in_str == CTX_COMMENT:
+                       in_str = CTX_NORMAL
+               
+               for i in range(end):
+                       if in_str == 0:
+                               if line[i] == "'": in_str = CTX_SINGLE_QUOTE
+                               elif line[i] == '"': in_str = CTX_DOUBLE_QUOTE
+                               elif line[i] == '#': in_str = CTX_COMMENT
+                       else:
+                               if in_str == CTX_SINGLE_QUOTE:
+                                       if line[i] == "'":
+                                               in_str = CTX_NORMAL
+                                               # In again if ' escaped, out again if \ escaped, and so on
+                                               for a in range(i-1, -1, -1):
+                                                       if line[a] == '\\': in_str = 1-in_str
+                                                       else: break
+                               elif in_str == CTX_DOUBLE_QUOTE:
+                                       if line[i] == '"':
+                                               in_str = CTX_NORMAL
+                                               # In again if " escaped, out again if \ escaped, and so on
+                                               for a in range(i-1, -1, -1):
+                                                       if line[i-a] == '\\': in_str = 2-in_str
+                                                       else: break
+               
+       return in_str
+
+def current_line(txt):
+       """Extracts the Python script line at the cursor in the Blender Text object
+       provided and cursor position within this line as the tuple pair (line,
+       cursor).
+       """
+       
+       lineindex, cursor = txt.getCursorPos()
+       lines = txt.asLines()
+       line = lines[lineindex]
+       
+       # Join previous lines to this line if spanning
+       i = lineindex - 1
+       while i > 0:
+               earlier = lines[i].rstrip()
+               if earlier.endswith('\\'):
+                       line = earlier[:-1] + ' ' + line
+                       cursor += len(earlier)
+               i -= 1
+       
+       # Join later lines while there is an explicit joining character
+       i = lineindex
+       while i < len(lines)-1 and lines[i].rstrip().endswith('\\'):
+               later = lines[i+1].strip()
+               line = line + ' ' + later[:-1]
+               i += 1
+       
+       return line, cursor
+
+def get_targets(line, cursor):
+       """Parses a period separated string of valid names preceding the cursor and
+       returns them as a list in the same order.
+       """
+       
+       brk = 0
+       targets = []
+       j = cursor
+       i = j-1
+       while i >= 0:
+               if line[i] == ')': brk += 1
+               elif brk:
+                       if line[i] == '(': brk -= 1
+               else:
+                       if line[i] == '.':
+                               targets.insert(0, line[i+1:j]); j=i
+                       elif not (line[i].isalnum() or line[i] == '_' or line[i] == '.'):
+                               break
+               i -= 1
+       targets.insert(0, line[i+1:j])
+       return targets
+
+def get_defs(txt):
+       """Returns a dictionary which maps definition names in the source code to
+       a list of their parameter names.
+       
+       The line 'def doit(one, two, three): print one' for example, results in the
+       mapping 'doit' : [ 'one', 'two', 'three' ]
+       """
+       
+       return get_cached_descriptor(txt).defs
+
+def get_vars(txt):
+       """Returns a dictionary of variable names found in the specified Text
+       object. This method locates all names followed directly by an equal sign:
+       'a = ???' or indirectly as part of a tuple/list assignment or inside a
+       'for ??? in ???:' block.
+       """
+       
+       return get_cached_descriptor(txt).vars
+
+def get_imports(txt):
+       """Returns a dictionary which maps symbol names in the source code to their
+       respective modules.
+       
+       The line 'from Blender import Text as BText' for example, results in the
+       mapping 'BText' : <module 'Blender.Text' (built-in)>
+       
+       Note that this method imports the modules to provide this mapping as as such
+       will execute any initilization code found within.
+       """
+       
+       return get_cached_descriptor(txt).imports
+
+def get_builtins():
+       """Returns a dictionary of built-in modules, functions and variables."""
+       
+       return __builtin__.__dict__
+
+
+#################################
+## Debugging utility functions ##
+#################################
+
+def print_cache_for(txt, period=sys.maxint):
+       """Prints out the data cached for a given Text object. If no period is
+       given the text will not be reparsed and the cached version will be returned.
+       Otherwise if the period has expired the text will be reparsed.
+       """
+       
+       desc = get_cached_descriptor(txt, period)
+       print '================================================'
+       print 'Name:', desc.name, '('+str(hash(txt))+')'
+       print '------------------------------------------------'
+       print 'Defs:'
+       for name, ddesc in desc.defs.items():
+               print ' ', name, ddesc.params, ddesc.lineno
+               print '   ', ddesc.doc
+       print '------------------------------------------------'
+       print 'Vars:'
+       for name, vdesc in desc.vars.items():
+               print ' ', name, vdesc.type, vdesc.lineno
+       print '------------------------------------------------'
+       print 'Imports:'
+       for name, item in desc.imports.items():
+               print ' ', name.ljust(15), item
+       print '------------------------------------------------'
+       print 'Classes:'
+       for clsnme, clsdsc in desc.classes.items():
+               print '  *********************************'
+               print '  Name:', clsnme
+               print ' ', clsdsc.doc
+               print '  ---------------------------------'
+               print '  Defs:'
+               for name, ddesc in clsdsc.defs.items():
+                       print '   ', name, ddesc.params, ddesc.lineno
+                       print '     ', ddesc.doc
+               print '  ---------------------------------'
+               print '  Vars:'
+               for name, vdesc in clsdsc.vars.items():
+                       print '   ', name, vdesc.type, vdesc.lineno
+               print '  *********************************'
+       print '================================================'
index 608201acb98a78825baa5643e14e75166fb21a96..27adca335cb96d01e2b203bd730861d092625fdd 100644 (file)
@@ -121,25 +121,29 @@ def rem_unused_materials(me):
        material_users= dict( [(i,0) for i in xrange(len_materials)] )
        
        for f in me.faces:
+               f_mat = f.mat
                # Make sure the face index isnt too big. this happens sometimes.
-               if f.mat >= len_materials:
-                       f.mat=0
-               material_users[f.mat] += 1
+               if f_mat >= len_materials:
+                       f_mat = f.mat = 0
+               material_users[f_mat] += 1
        
-       mat_idx_subtract= 0
-       reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] )
-       i= len_materials
-       while i:
-               i-=1
-               
+       # mat_idx_subtract= 0
+       # reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] )
+       
+       reindex_mapping_ls = range(len_materials)
+       for i in range(len_materials-1, -1, -1):
                if material_users[i] == 0:
-                       mat_idx_subtract+=1
-                       reindex_mapping[i]= mat_idx_subtract
-                       materials.pop(i)
+                       del reindex_mapping_ls[i]
+                       del materials[i]
                        rem_materials+=1
        
+       reindex_mapping= {}
+       
+       for i, mat in enumerate(reindex_mapping_ls):
+               reindex_mapping[mat] = i                
+       
        for f in me.faces:
-               f.mat= f.mat - reindex_mapping[f.mat]
+               f.mat= reindex_mapping[f.mat]
        
        me.materials= materials
        return rem_materials
@@ -449,4 +453,4 @@ def main():
        
        
 if __name__ == '__main__':
-       main()
+       main()
\ No newline at end of file
diff --git a/release/scripts/scripttemplate_text_plugin.py b/release/scripts/scripttemplate_text_plugin.py
new file mode 100644 (file)
index 0000000..4ae5627
--- /dev/null
@@ -0,0 +1,69 @@
+#!BPY
+"""
+Name: 'Text Plugin'
+Blender: 246
+Group: 'ScriptTemplate'
+Tooltip: 'Add a new text for writing a text plugin'
+"""
+
+from Blender import Window
+import bpy
+
+script_data = \
+'''#!BPY
+"""
+Name: 'My Plugin Script'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: 'Ctrl+Alt+U'
+Tooltip: 'Put some useful info here'
+"""
+
+# Add a licence here if you wish to re-distribute, we recommend the GPL
+
+from Blender import Window, sys
+import BPyTextPlugin, bpy
+
+def my_script_util(txt):
+       # This function prints out statistical information about a script
+       
+       desc = BPyTextPlugin.get_cached_descriptor(txt)
+       print '---------------------------------------'
+       print 'Script Name:', desc.name
+       print 'Classes:', len(desc.classes)
+       print '  ', desc.classes.keys()
+       print 'Functions:', len(desc.defs)
+       print '  ', desc.defs.keys()
+       print 'Variables:', len(desc.vars)
+       print '  ', desc.vars.keys()
+
+def main():
+       
+       # Gets the active text object, there can be many in one blend file.
+       txt = bpy.data.texts.active
+       
+       # Silently return if the script has been run with no active text
+       if not txt:
+               return 
+       
+       # Text plug-ins should run quickly so we time it here
+       Window.WaitCursor(1)
+       t = sys.time()
+       
+       # Run our utility function
+       my_script_util(txt)
+       
+       # Timing the script is a good way to be aware on any speed hits when scripting
+       print 'Plugin script finished in %.2f seconds' % (sys.time()-t)
+       Window.WaitCursor(0)
+       
+
+# This lets you import the script without running it
+if __name__ == '__main__':
+       main()
+'''
+
+new_text = bpy.data.texts.new('textplugin_template.py')
+new_text.write(script_data)
+bpy.data.texts.active = new_text
+Window.RedrawAll()
index 9f24885829c76c4107b1340fe6526f0d8faca6bc..3a671e7221e49cb58d1b5c469be1794b3e3ef335 100644 (file)
@@ -94,6 +94,8 @@ output = Blender.Text.New(output_filename)
 
 output.write(header + "\n\n")
 
+output.write("%s\n\n" % Blender.Get('buildinfo'))
+
 output.write("Platform: %s\n========\n\n" % sys.platform)
 
 output.write("Python:\n======\n\n")
diff --git a/release/scripts/textplugin_functiondocs.py b/release/scripts/textplugin_functiondocs.py
new file mode 100644 (file)
index 0000000..41c8d48
--- /dev/null
@@ -0,0 +1,64 @@
+#!BPY
+"""
+Name: 'Function Documentation | Ctrl I'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: 'Ctrl+I'
+Tooltip: 'Attempts to display documentation about the function preceding the cursor.'
+"""
+
+# Only run if we have the required modules
+try:
+       import bpy
+       from BPyTextPlugin import *
+except ImportError:
+       OK = False
+else:
+       OK = True
+
+def main():
+       txt = bpy.data.texts.active
+       if not txt:
+               return
+       
+       (line, c) = current_line(txt)
+       
+       # Check we are in a normal context
+       if get_context(txt) != CTX_NORMAL:
+               return
+       
+       # Identify the name under the cursor
+       llen = len(line)
+       while c<llen and (line[c].isalnum() or line[c]=='_'):
+               c += 1
+       
+       targets = get_targets(line, c)
+       
+       # If no name under cursor, look backward to see if we're in function parens
+       if len(targets) == 0 or targets[0] == '':
+               # Look backwards for first '(' without ')'
+               b = 0
+               found = False
+               for i in range(c-1, -1, -1):
+                       if line[i] == ')': b += 1
+                       elif line[i] == '(':
+                               b -= 1
+                               if b < 0:
+                                       found = True
+                                       c = i
+                                       break
+               if found: targets = get_targets(line, c)
+               if len(targets) == 0 or targets[0] == '':
+                       return
+       
+       obj = resolve_targets(txt, targets)
+       if not obj: return
+       
+       if isinstance(obj, Definition): # Local definition
+               txt.showDocs(obj.doc)
+       elif hasattr(obj, '__doc__') and obj.__doc__:
+               txt.showDocs(obj.__doc__)
+
+# Check we are running as a script and not imported as a module
+if __name__ == "__main__" and OK:
+       main()
diff --git a/release/scripts/textplugin_imports.py b/release/scripts/textplugin_imports.py
new file mode 100644 (file)
index 0000000..ec60824
--- /dev/null
@@ -0,0 +1,91 @@
+#!BPY
+"""
+Name: 'Import Complete|Space'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: 'Space'
+Tooltip: 'Lists modules when import or from is typed'
+"""
+
+# Only run if we have the required modules
+try:
+       import bpy, sys
+       from BPyTextPlugin import *
+except ImportError:
+       OK = False
+else:
+       OK = True
+
+def main():
+       txt = bpy.data.texts.active
+       if not txt:
+               return
+       
+       line, c = current_line(txt)
+       
+       # Check we are in a normal context
+       if get_context(txt) != CTX_NORMAL:
+               return
+       
+       pos = line.rfind('from ', 0, c)
+       
+       # No 'from' found
+       if pos == -1:
+               # Check instead for straight 'import xxxx'
+               pos2 = line.rfind('import ', 0, c)
+               if pos2 != -1:
+                       pos2 += 7
+                       for i in range(pos2, c):
+                               if line[i]==',' or (line[i]==' ' and line[i-1]==','):
+                                       pos2 = i+1
+                               elif not line[i].isalnum() and line[i] != '_':
+                                       return
+                       items = [(m, 'm') for m in get_modules()]
+                       items.sort(cmp = suggest_cmp)
+                       txt.suggest(items, line[pos2:c].strip())
+               return
+       
+       # Found 'from xxxxx' before cursor
+       immediate = True
+       pos += 5
+       for i in range(pos, c):
+               if not line[i].isalnum() and line[i] != '_' and line[i] != '.':
+                       immediate = False
+                       break
+       
+       # Immediate 'from' followed by at most a module name
+       if immediate:
+               items = [(m, 'm') for m in get_modules()]
+               items.sort(cmp = suggest_cmp)
+               txt.suggest(items, line[pos:c])
+               return
+       
+       # Found 'from' earlier, suggest import if not already there
+       pos2 = line.rfind('import ', pos, c)
+       
+       # No 'import' found after 'from' so suggest it
+       if pos2 == -1:
+               txt.suggest([('import', 'k')], '')
+               return
+               
+       # Immediate 'import' before cursor and after 'from...'
+       for i in range(pos2+7, c):
+               if line[i]==',' or (line[i]==' ' and line[i-1]==','):
+                       pass
+               elif not line[i].isalnum() and line[i] != '_':
+                       return
+       between = line[pos:pos2-1].strip()
+       try:
+               mod = get_module(between)
+       except ImportError:
+               return
+       
+       items = [('*', 'k')]
+       for (k,v) in mod.__dict__.items():
+               items.append((k, type_char(v)))
+       items.sort(cmp = suggest_cmp)
+       txt.suggest(items, '')
+
+# Check we are running as a script and not imported as a module
+if __name__ == "__main__" and OK:
+       main()
diff --git a/release/scripts/textplugin_membersuggest.py b/release/scripts/textplugin_membersuggest.py
new file mode 100644 (file)
index 0000000..7c0de78
--- /dev/null
@@ -0,0 +1,90 @@
+#!BPY
+"""
+Name: 'Member Suggest | .'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: 'Period'
+Tooltip: 'Lists members of the object preceding the cursor in the current text space'
+"""
+
+# Only run if we have the required modules
+try:
+       import bpy
+       from BPyTextPlugin import *
+except ImportError:
+       OK = False
+else:
+       OK = True
+
+def main():
+       txt = bpy.data.texts.active
+       if not txt:
+               return
+       
+       (line, c) = current_line(txt)
+       
+       # Check we are in a normal context
+       if get_context(txt) != CTX_NORMAL:
+               return
+       
+       targets = get_targets(line, c)
+       
+       if targets[0] == '': # Check if we are looking at a constant [] {} '' etc.
+               i = c - len('.'.join(targets)) - 1
+               if i >= 0:
+                       if line[i] == '"' or line[i] == "'":
+                               targets[0] = 'str'
+                       elif line[i] == '}':
+                               targets[0] = 'dict'
+                       elif line[i] == ']': # Could be array elem x[y] or list [y]
+                               i = line.rfind('[', 0, i) - 1
+                               while i >= 0:
+                                       if line[i].isalnum() or line[i] == '_':
+                                               break
+                                       elif line[i] != ' ' and line[i] != '\t':
+                                               i = -1
+                                               break
+                                       i -= 1
+                               if i < 0: 
+                                       targets[0] = 'list'
+       
+       obj = resolve_targets(txt, targets[:-1])
+       if not obj:
+               return
+       
+       items = []
+       
+       if isinstance(obj, VarDesc):
+               obj = obj.type
+               
+       if isinstance(obj, Definition): # Locally defined
+               if hasattr(obj, 'classes'):
+                       items.extend([(s, 'f') for s in obj.classes.keys()])
+               if hasattr(obj, 'defs'):
+                       items.extend([(s, 'f') for s in obj.defs.keys()])
+               if hasattr(obj, 'vars'):
+                       items.extend([(s, 'v') for s in obj.vars.keys()])
+       
+       else: # Otherwise we have an imported or builtin object
+               try:
+                       attr = obj.__dict__.keys()
+               except AttributeError:
+                       attr = dir(obj)
+               else:
+                       if not attr: attr = dir(obj)
+               
+               for k in attr:
+                       try:
+                               v = getattr(obj, k)
+                       except (AttributeError, TypeError): # Some attributes are not readable
+                               pass
+                       else:
+                               items.append((k, type_char(v)))
+       
+       if items != []:
+               items.sort(cmp = suggest_cmp)
+               txt.suggest(items, targets[-1])
+
+# Check we are running as a script and not imported as a module
+if __name__ == "__main__" and OK:
+       main()
diff --git a/release/scripts/textplugin_outliner.py b/release/scripts/textplugin_outliner.py
new file mode 100644 (file)
index 0000000..3879a28
--- /dev/null
@@ -0,0 +1,142 @@
+#!BPY
+"""
+Name: 'Code Outline | Ctrl T'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: 'Ctrl+T'
+Tooltip: 'Provides a menu for jumping to class and functions definitions.'
+"""
+
+# Only run if we have the required modules
+try:
+       import bpy
+       from BPyTextPlugin import *
+       from Blender import Draw
+except ImportError:
+       OK = False
+else:
+       OK = True
+
+def make_menu(items, eventoffs):
+       n = len(items)
+       if n < 20:
+               return [(items[i], i+1+eventoffs) for i in range(len(items))]
+       
+       letters = []
+       check = 'abcdefghijklmnopqrstuvwxyz_' # Names cannot start 0-9
+       for c in check:
+               for item in items:
+                       if item[0].lower() == c:
+                               letters.append(c)
+                               break
+       
+       entries = {}
+       i = 0
+       for item in items:
+               i += 1
+               c = item[0].lower()
+               entries.setdefault(c, []).append((item, i+eventoffs))
+       
+       subs = []
+       for c in letters:
+               subs.append((c, entries[c]))
+       
+       return subs
+
+def find_word(txt, word):
+       i = 0
+       txt.reset()
+       while True:
+               try:
+                       line = txt.readline()
+               except StopIteration:
+                       break
+               c = line.find(word)
+               if c != -1:
+                       txt.setCursorPos(i, c)
+                       break
+               i += 1
+
+def main():
+       txt = bpy.data.texts.active
+       if not txt:
+               return
+       
+       # Identify word under cursor
+       if get_context(txt) == CTX_NORMAL:
+               line, c = current_line(txt)
+               start = c-1
+               end = c
+               while start >= 0:
+                       if not line[start].lower() in 'abcdefghijklmnopqrstuvwxyz0123456789_':
+                               break
+                       start -= 1
+               while end < len(line):
+                       if not line[end].lower() in 'abcdefghijklmnopqrstuvwxyz0123456789_':
+                               break
+                       end += 1
+               word = line[start+1:end]
+               if word in KEYWORDS:
+                       word = None
+       else:
+               word = None
+       
+       script = get_cached_descriptor(txt)
+       items = []
+       desc = None
+       
+       tmp = script.classes.keys()
+       tmp.sort(cmp = suggest_cmp)
+       class_menu = make_menu(tmp, len(items))
+       class_menu_length = len(tmp)
+       items.extend(tmp)
+       
+       tmp = script.defs.keys()
+       tmp.sort(cmp = suggest_cmp)
+       defs_menu = make_menu(tmp, len(items))
+       defs_menu_length = len(tmp)
+       items.extend(tmp)
+       
+       tmp = script.vars.keys()
+       tmp.sort(cmp = suggest_cmp)
+       vars_menu = make_menu(tmp, len(items))
+       vars_menu_length = len(tmp)
+       items.extend(tmp)
+       
+       menu = [('Script %t', 0),
+                       ('Classes', class_menu),
+                       ('Functions', defs_menu),
+                       ('Variables', vars_menu)]
+       if word:
+               menu.extend([None, ('Locate', [(word, -10)])])
+       
+       i = Draw.PupTreeMenu(menu)
+       if i == -1:
+               return
+       
+       # Chosen to search for word under cursor
+       if i == -10:
+               if script.classes.has_key(word):
+                       desc = script.classes[word]
+               elif script.defs.has_key(word):
+                       desc = script.defs[word]
+               elif script.vars.has_key(word):
+                       desc = script.vars[word]
+               else:
+                       find_word(txt, word)
+                       return
+       else:
+               i -= 1
+               if i < class_menu_length:
+                       desc = script.classes[items[i]]
+               elif i < class_menu_length + defs_menu_length:
+                       desc = script.defs[items[i]]
+               elif i < class_menu_length + defs_menu_length + vars_menu_length:
+                       desc = script.vars[items[i]]
+       
+       if desc:
+               txt.setCursorPos(desc.lineno-1, 0)
+
+# Check we are running as a script and not imported as a module
+if __name__ == "__main__" and OK:
+       main()
diff --git a/release/scripts/textplugin_suggest.py b/release/scripts/textplugin_suggest.py
new file mode 100644 (file)
index 0000000..d812221
--- /dev/null
@@ -0,0 +1,94 @@
+#!BPY
+"""
+Name: 'Suggest All | Ctrl Space'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: 'Ctrl+Space'
+Tooltip: 'Performs suggestions based on the context of the cursor'
+"""
+
+# Only run if we have the required modules
+try:
+       import bpy
+       from BPyTextPlugin import *
+except ImportError:
+       OK = False
+else:
+       OK = True
+
+def check_membersuggest(line, c):
+       pos = line.rfind('.', 0, c)
+       if pos == -1:
+               return False
+       for s in line[pos+1:c]:
+               if not s.isalnum() and s != '_':
+                       return False
+       return True
+
+def check_imports(line, c):
+       pos = line.rfind('import ', 0, c)
+       if pos > -1:
+               for s in line[pos+7:c]:
+                       if not s.isalnum() and s != '_':
+                               return False
+               return True
+       pos = line.rfind('from ', 0, c)
+       if pos > -1:
+               for s in line[pos+5:c]:
+                       if not s.isalnum() and s != '_':
+                               return False
+               return True
+       return False
+
+def main():
+       txt = bpy.data.texts.active
+       if not txt:
+               return
+       
+       line, c = current_line(txt)
+       
+       # Check we are in a normal context
+       if get_context(txt) != CTX_NORMAL:
+               return
+       
+       # Check the character preceding the cursor and execute the corresponding script
+       
+       if check_membersuggest(line, c):
+               import textplugin_membersuggest
+               textplugin_membersuggest.main()
+               return
+       
+       elif check_imports(line, c):
+               import textplugin_imports
+               textplugin_imports.main()
+               return
+       
+       # Otherwise we suggest globals, keywords, etc.
+       list = []
+       targets = get_targets(line, c)
+       desc = get_cached_descriptor(txt)
+       
+       for k in KEYWORDS:
+               list.append((k, 'k'))
+       
+       for k, v in get_builtins().items():
+               list.append((k, type_char(v)))
+       
+       for k, v in desc.imports.items():
+               list.append((k, type_char(v)))
+       
+       for k, v in desc.classes.items():
+               list.append((k, 'f'))
+       
+       for k, v in desc.defs.items():
+               list.append((k, 'f'))
+       
+       for k, v in desc.vars.items():
+               list.append((k, 'v'))
+       
+       list.sort(cmp = suggest_cmp)
+       txt.suggest(list, targets[-1])
+
+# Check we are running as a script and not imported as a module
+if __name__ == "__main__" and OK:
+       main()
diff --git a/release/scripts/textplugin_templates.py b/release/scripts/textplugin_templates.py
new file mode 100644 (file)
index 0000000..8f94956
--- /dev/null
@@ -0,0 +1,123 @@
+#!BPY
+"""
+Name: 'Template Completion | Tab'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: 'Tab'
+Tooltip: 'Completes templates based on the text preceding the cursor'
+"""
+
+# Only run if we have the required modules
+try:
+       import bpy
+       from BPyTextPlugin import *
+       from Blender import Text
+except ImportError:
+       OK = False
+else:
+       OK = True
+
+templates = {
+       'ie':
+               'if ${1:cond}:\n'
+               '\t${2}\n'
+               'else:\n'
+               '\t${3}\n',
+       'iei':
+               'if ${1:cond}:\n'
+               '\t${2}\n'
+               'elif:\n'
+               '\t${3}\n'
+               'else:\n'
+               '\t${4}\n',
+       'def':
+               'def ${1:name}(${2:params}):\n'
+               '\t"""(${2}) - ${3:comment}"""\n'
+               '\t${4}',
+       'cls':
+               'class ${1:name}(${2:parent}):\n'
+               '\t"""${3:docs}"""\n'
+               '\t\n'
+               '\tdef __init__(self, ${4:params}):\n'
+               '\t\t"""Creates a new ${1}"""\n'
+               '\t\t${5}',
+       'class':
+               'class ${1:name}(${2:parent}):\n'
+               '\t"""${3:docs}"""\n'
+               '\t\n'
+               '\tdef __init__(self, ${4:params}):\n'
+               '\t\t"""Creates a new ${1}"""\n'
+               '\t\t${5}'
+}
+
+def main():
+       txt = bpy.data.texts.active
+       if not txt:
+               return
+       
+       row, c = txt.getCursorPos()
+       line = txt.asLines(row, row+1)[0]
+       indent=0
+       while indent<c and (line[indent]==' ' or line[indent]=='\t'):
+               indent += 1
+       
+       # Check we are in a normal context
+       if get_context(txt) != CTX_NORMAL:
+               return
+       
+       targets = get_targets(line, c-1);
+       if len(targets) != 1: return
+       
+       color = (0, 192, 32)
+       
+       for trigger, template in templates.items():
+               if trigger != targets[0]: continue
+               inserts = {}
+               txt.delete(-len(trigger)-1)
+               y, x = txt.getCursorPos()
+               first = None
+               
+               # Insert template text and parse for insertion points
+               count = len(template); i = 0
+               while i < count:
+                       if i<count-1 and template[i]=='$' and template[i+1]=='{':
+                               i += 2
+                               e = template.find('}', i)
+                               item = template[i:e].split(':')
+                               if len(item)<2: item.append('')
+                               if not inserts.has_key(item[0]):
+                                       inserts[item[0]] = (item[1], [(x, y)])
+                               else:
+                                       inserts[item[0]][1].append((x, y))
+                                       item[1] = inserts[item[0]][0]
+                               if not first: first = (item[1], x, y)
+                               txt.insert(item[1])
+                               x += len(item[1])
+                               i = e
+                       else:
+                               txt.insert(template[i])
+                               if template[i] == '\n':
+                                       txt.insert(line[:indent])
+                                       y += 1
+                                       x = indent
+                               else:
+                                       x += 1
+                       i += 1
+               
+               # Insert markers at insertion points
+               for id, (text, points) in inserts.items():
+                       for x, y in points:
+                               txt.setCursorPos(y, x)
+                               txt.setSelectPos(y, x+len(text))
+                               txt.markSelection((hash(text)+int(id)) & 0xFFFF, color,
+                                               Text.TMARK_TEMP | Text.TMARK_EDITALL)
+               if first:
+                       text, x, y = first
+                       txt.setCursorPos(y, x)
+                       txt.setSelectPos(y, x+len(text))
+               break
+               
+
+# Check we are running as a script and not imported as a module
+if __name__ == "__main__" and OK:
+       main()
index 91dd17d73dd49d211789e65b8e62dc6b26fe674e..aebeb8f30c2dd47e677bbc14b6508c498e5bbc8b 100644 (file)
@@ -104,6 +104,8 @@ COMLIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a
 COMLIB += $(NAN_SUPERLU)/lib/$(DEBUG_DIR)libsuperlu.a  
 COMLIB += $(OCGDIR)/blender/avi/$(DEBUG_DIR)libavi.a
 COMLIB += $(NAN_JPEG)/lib/libjpeg.a
+COMLIB += $(OCGDIR)/blender/gpu/$(DEBUG_DIR)libgpu.a
+COMLIB += $(NAN_GLEW)/lib/libglew.a
 
 ifneq ($(NAN_NO_KETSJI),true)
     COMLIB += $(OCGDIR)/gameengine/bloutines/$(DEBUG_DIR)libbloutines.a
@@ -157,7 +159,6 @@ COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a
 COMLIB += $(NAN_PNG)/lib/libpng.a
 COMLIB += $(OCGDIR)/blender/yafray/$(DEBUG_DIR)libyafrayexport.a
 COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
-COMLIB += $(NAN_GLEW)/lib/libglew.a
 
 ifeq ($(WITH_QUICKTIME), true)
     COMLIB += $(OCGDIR)/blender/blenderqt/$(DEBUG_DIR)libblenderqt.a
index 966bf5f7be4231b80eecb63d831a93aa3a50be58..a21eadf15fa830432af8bc39c74aa00a7dafb849 100644 (file)
@@ -24,7 +24,7 @@
 #
 # ***** END GPL LICENSE BLOCK *****
 
-SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon makesdna python radiosity readblenfile render src yafray)
+SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon gpu makesdna python radiosity readblenfile render src yafray)
 
 IF(WITH_INTERNATIONAL)
   SUBDIRS(ftfont)
index 937512f34bd65a3d423262d186e2799ad9928c27..52abd2cdddb60ee06ee013dbd1e63f91c8370a6f 100644 (file)
@@ -33,7 +33,7 @@ include nan_definitions.mk
 DIRS = blenloader readblenfile
 DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi
 DIRS += makesdna src yafray
-DIRS += python nodes
+DIRS += python nodes gpu
 
 ifeq ($(WITH_FREETYPE2), true)
        DIRS += ftfont
index 56a661238f810756e48650907e36b7ed2dd5f953..25745c0e51a2c399449aef4929c030badeab47d2 100644 (file)
@@ -7,6 +7,7 @@ SConscript(['avi/SConscript',
             'blenlib/SConscript',
             'blenloader/SConscript',
             'blenpluginapi/SConscript',
+            'gpu/SConscript',
             'imbuf/SConscript',
             'imbuf/intern/cineon/SConscript',
             'makesdna/SConscript',
index c68c5838bab3ecd60ba86578c339ea35c87ebf4b..5a1e266adeb204520c15be8b66850e49d445cf9e 100644 (file)
@@ -55,6 +55,7 @@ struct EditMesh;
 struct ModifierData;
 struct MCol;
 struct ColorBand;
+struct GPUVertexAttribs;
 
 /* number of sub-elements each mesh element has (for interpolation) */
 #define SUB_ELEMS_VERT 0
@@ -198,7 +199,8 @@ struct DerivedMesh {
         *
         * Also called for *final* editmode DerivedMeshes
         */
-       void (*drawFacesSolid)(DerivedMesh *dm, int (*setMaterial)(int));
+       void (*drawFacesSolid)(DerivedMesh *dm,
+                              int (*setMaterial)(int, void *attribs));
 
        /* Draw all faces
         *  o If useTwoSided, draw front and back using col arrays
@@ -215,6 +217,13 @@ struct DerivedMesh {
                             int (*setDrawOptions)(struct MTFace *tface,
                             struct MCol *mcol, int matnr));
 
+       /* Draw all faces with GLSL materials
+        *  o setMaterial is called for every different material nr
+        *  o Only if setMaterial returns true
+        */
+       void (*drawFacesGLSL)(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs));
+
        /* Draw mapped faces (no color, or texture)
         *  o Only if !setDrawOptions or
         *    setDrawOptions(userData, mapped-face-index, drawSmooth_r)
@@ -241,6 +250,15 @@ struct DerivedMesh {
                                                         int index),
                                   void *userData);
 
+       /* Draw mapped faces with GLSL materials
+        *  o setMaterial is called for every different material nr
+        *  o setDrawOptions is called for every face
+        *  o Only if setMaterial and setDrawOptions return true
+        */
+       void (*drawMappedFacesGLSL)(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs),
+               int (*setDrawOptions)(void *userData, int index), void *userData);
+
        /* Draw mapped edges as lines
         *  o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge)
         *    returns true
@@ -440,6 +458,35 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb);
 /* determines required DerivedMesh data according to view and edit modes */
 CustomDataMask get_viewedit_datamask();
 
+/* convert layers requested by a GLSL material to actually available layers in
+ * the DerivedMesh, with both a pointer for arrays and an offset for editmesh */
+typedef struct DMVertexAttribs {
+       struct {
+               struct MTFace *array;
+               int emOffset, glIndex;
+       } tface[MAX_MTFACE];
+
+       struct {
+               struct MCol *array;
+               int emOffset, glIndex;
+       } mcol[MAX_MCOL];
+
+       struct {
+               float (*array)[3];
+               int emOffset, glIndex;
+       } tang;
+
+       struct {
+               float (*array)[3];
+               int emOffset, glIndex;
+       } orco;
+
+       int tottface, totmcol, tottang, totorco;
+} DMVertexAttribs;
+
+void DM_vertex_attributes_from_gpu(DerivedMesh *dm,
+       struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
+
 void DM_add_tangent_layer(DerivedMesh *dm);
 
 #endif
index 3e45749c26abacb9f629d7100fc704888d48d4f1..8dee9a27f49cba1ea1ed4cabaa9b680efd4453d8 100644 (file)
@@ -115,10 +115,6 @@ void free_editArmature(void);
 void docenter_new(void);
 int saveover(char *str);
 
-/* image.c */
-#include "DNA_image_types.h"
-void free_realtime_image(Image *ima); // has to become a callback, opengl stuff
-
 /* ipo.c */
 void copy_view3d_lock(short val);      // was a hack, to make scene layer ipo's possible
 
index e78882220a9264ee4e0578ed9d9b63a1cfd28ae3..555b467b1d6ae44a91be12fd381803f117185461 100644 (file)
@@ -57,6 +57,7 @@ void                          curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf);
 void                           curvemapping_premultiply(struct CurveMapping *cumap, int restore);
 int                                    curvemapping_RGBA_does_something(struct CurveMapping *cumap);
 void                           curvemapping_initialize(struct CurveMapping *cumap);
+void                           curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size);
 
 #endif
 
index 8c9634cba06051e5df877e3be8ef539bc14497ec..1cc336db69e640be86dabada852f7bef973426ce 100644 (file)
@@ -218,8 +218,15 @@ typedef struct Global {
 #define G_FILE_NO_UI                    (1 << 10)
 #define G_FILE_GAME_TO_IPO              (1 << 11)
 #define G_FILE_GAME_MAT                         (1 << 12)
-#define G_FILE_DIAPLAY_LISTS    (1 << 13)
+#define G_FILE_DISPLAY_LISTS    (1 << 13)
 #define G_FILE_SHOW_PHYSICS             (1 << 14)
+#define G_FILE_GAME_MAT_GLSL    (1 << 15)
+#define G_FILE_GLSL_NO_LIGHTS   (1 << 16)
+#define G_FILE_GLSL_NO_SHADERS  (1 << 17)
+#define G_FILE_GLSL_NO_SHADOWS  (1 << 18)
+#define G_FILE_GLSL_NO_RAMPS    (1 << 19)
+#define G_FILE_GLSL_NO_NODES    (1 << 20)
+#define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21)
 
 /* G.windowstate */
 #define G_WINDOWSTATE_USERDEF          0
index d4ae76e89848066df2566dd6054f9f133717604b..2ca4b3aa39a3d9b1f07845d9e0303e33d2d99cb9 100644 (file)
@@ -68,7 +68,6 @@ void mball_to_mesh(struct ListBase *lb, struct Mesh *me);
 void nurbs_to_mesh(struct Object *ob);
 void free_dverts(struct MDeformVert *dvert, int totvert);
 void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
-int update_realtime_texture(struct MTFace *tface, double time);
 void mesh_delete_material_index(struct Mesh *me, int index);
 void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth);
 
index b3b68a9b3ff21c5c9bb04be75433909578957ecb..01c54663c6d9e34b43a62eecd9d7a09ad40448b7 100644 (file)
@@ -47,6 +47,9 @@ struct rctf;
 struct ListBase;
 struct RenderData;
 struct Scene;
+struct GPUMaterial;
+struct GPUNode;
+struct GPUNodeStack;
 
 #define SOCK_IN                1
 #define SOCK_OUT       2
@@ -91,6 +94,9 @@ typedef struct bNodeType {
        void *pynode; /* holds pointer to python script */
        void *pydict; /* holds pointer to python script dictionary (scope)*/
 
+       /* gpu */
+       int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out);
+
 } bNodeType;
 
 /* node->exec, now in use for composites (#define for break is same as ready yes) */
@@ -252,6 +258,8 @@ void                        nodeShaderSynchronizeID(struct bNode *node, int copyto);
 extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
 void                   set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *));
 
+void                   ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
+
 
 /* ************** COMPOSITE NODES *************** */
 
diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h
new file mode 100644 (file)
index 0000000..d58b8f5
--- /dev/null
@@ -0,0 +1,93 @@
+/**    
+ * $Id: $ 
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef BKE_SUGGESTIONS_H
+#define BKE_SUGGESTIONS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ****************************************************************************
+Suggestions should be added in sorted order although a linear sorting method is
+implemented. The list is then divided up based on the prefix provided by
+update_suggestions:
+
+Example:
+  Prefix: ab
+  aaa <-- first
+  aab
+  aba <-- firstmatch
+  abb <-- lastmatch
+  baa
+  bab <-- last
+**************************************************************************** */
+
+struct Text;
+
+typedef struct SuggItem {
+       struct SuggItem *prev, *next;
+       char *name;
+       char type;
+} SuggItem;
+
+typedef struct SuggList {
+       SuggItem *first, *last;
+       SuggItem *firstmatch, *lastmatch;
+       SuggItem *selected;
+       int top;
+} SuggList;
+
+/* Free all text tool memory */
+void free_texttools();
+
+/* Used to identify which Text object the current tools should appear against */
+void texttool_text_set_active(Text *text);
+void texttool_text_clear();
+short texttool_text_is_active(Text *text);
+
+/* Suggestions */
+void texttool_suggest_add(const char *name, char type);
+void texttool_suggest_prefix(const char *prefix);
+void texttool_suggest_clear();
+SuggItem *texttool_suggest_first();
+SuggItem *texttool_suggest_last();
+void texttool_suggest_select(SuggItem *sel);
+SuggItem *texttool_suggest_selected();
+int *texttool_suggest_top();
+
+/* Documentation */
+void texttool_docs_show(const char *docs);
+char *texttool_docs_get();
+void texttool_docs_clear();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index 6f891ab4887d7430e7c1ce77364d6342b5b7a32c..002c804f17fc308875bfaa688d24d5b28309fe67 100644 (file)
@@ -52,20 +52,24 @@ void        txt_free_cut_buffer     (void);
 char*  txt_to_buf                      (struct Text *text);
 void   txt_clean_text          (struct Text *text);
 void   txt_order_cursors       (struct Text *text);
-int            txt_find_string         (struct Text *text, char *findstr);
+int            txt_find_string         (struct Text *text, char *findstr, int wrap);
 int            txt_has_sel                     (struct Text *text);
 int            txt_get_span            (struct TextLine *from, struct TextLine *to);
 void   txt_move_up                     (struct Text *text, short sel);
 void   txt_move_down           (struct Text *text, short sel);
 void   txt_move_left           (struct Text *text, short sel);
 void   txt_move_right          (struct Text *text, short sel);
+void   txt_jump_left           (struct Text *text, short sel);
+void   txt_jump_right          (struct Text *text, short sel);
 void   txt_move_bof            (struct Text *text, short sel);
 void   txt_move_eof            (struct Text *text, short sel);
 void   txt_move_bol            (struct Text *text, short sel);
 void   txt_move_eol            (struct Text *text, short sel);
 void   txt_move_toline         (struct Text *text, unsigned int line, short sel);
+void   txt_move_to                     (struct Text *text, unsigned int line, unsigned int ch, short sel);
 void   txt_pop_sel                     (struct Text *text);
 void   txt_delete_char         (struct Text *text);
+void   txt_delete_word         (struct Text *text);
 void   txt_copy_sel            (struct Text *text);
 void   txt_sel_all                     (struct Text *text);
 void   txt_sel_line            (struct Text *text);
@@ -80,8 +84,10 @@ void txt_do_undo                     (struct Text *text);
 void   txt_do_redo                     (struct Text *text);
 void   txt_split_curline       (struct Text *text);
 void   txt_backspace_char      (struct Text *text);
+void   txt_backspace_word      (struct Text *text);
 int            txt_add_char            (struct Text *text, char add);
-void   txt_find_panel          (struct SpaceText *st, int again);
+int            txt_replace_char        (struct Text *text, char add);
+void   find_and_replace        (struct SpaceText *st, short mode);
 void   run_python_script       (struct SpaceText *st);
 int    jumptoline_interactive  (struct SpaceText *st);
 void   txt_export_to_object    (struct Text *text);
@@ -94,6 +100,17 @@ int setcurr_tab             (struct Text *text);
 void   convert_tabs            (struct SpaceText *st, int tab);
 void   txt_copy_clipboard      (struct Text *text);
 void   txt_paste_clipboard     (struct Text *text);
+
+void   txt_add_marker                                          (struct Text *text, struct TextLine *line, int start, int end, char color[4], int group, int flags);
+short  txt_clear_marker_region                         (struct Text *text, struct TextLine *line, int start, int end, int group, int flags);
+short  txt_clear_markers                                       (struct Text *text, int group, int flags);
+struct TextMarker      *txt_find_marker                (struct Text *text, struct TextLine *line, int curs, int group, int flags);
+struct TextMarker      *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags);
+struct TextMarker      *txt_prev_marker                (struct Text *text, struct TextMarker *marker);
+struct TextMarker      *txt_next_marker                (struct Text *text, struct TextMarker *marker);
+struct TextMarker      *txt_prev_marker_color  (struct Text *text, struct TextMarker *marker);
+struct TextMarker      *txt_next_marker_color  (struct Text *text, struct TextMarker *marker);
+
 /* Undo opcodes */
 
 /* Simple main cursor movement */
@@ -135,6 +152,14 @@ void       txt_paste_clipboard     (struct Text *text);
 #define UNDO_COMMENT           034
 #define UNDO_UNCOMMENT         035
 
+/* Find and replace flags */
+#define TXT_FIND_WRAP          0x01
+#define TXT_FIND_ALLTEXTS      0x02
+
+/* Marker flags */
+#define TMARK_TEMP             0x01    /* Remove on non-editing events, don't save */
+#define TMARK_EDITALL  0x02    /* Edit all markers of the same group as one */
+
 #ifdef __cplusplus
 }
 #endif
index c162a04e0557a7859302a0d69ec7e16890049ab5..cfcae3c44bc5a17a8932737c9a28cd5bbb4e63db 100644 (file)
@@ -53,6 +53,7 @@ void free_plugin_tex(struct PluginTex *pit);
 void init_colorband(struct ColorBand *coba, int rangetype);
 struct ColorBand *add_colorband(int rangetype);
 int do_colorband(struct ColorBand *coba, float in, float out[4]);
+void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size);
 
 void default_tex(struct Tex *tex);
 struct Tex *add_texture(char *name);
index f389521ffa0f0a9501be694a1105dfb3469d1d4b..d647a74c6e282f7b943c2f8cd98e990387b9a8fc 100644 (file)
@@ -55,6 +55,8 @@
 #define ELEM7(a, b, c, d, e, f, g, h)   ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) )
 #define ELEM8(a, b, c, d, e, f, g, h, i)        ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) )
 #define ELEM9(a, b, c, d, e, f, g, h, i, j)        ( ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) )
+#define ELEM10(a, b, c, d, e, f, g, h, i, j, k)        ( ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) )
+#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l)        ( ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) )
 
 /* shift around elements */
 #define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; }
index 9088b410e27abc6b7a3266757ba687725169fdf8..0345711c9c348ee474943443bd6e449759bc2882 100644 (file)
@@ -32,7 +32,7 @@ SET(INC
   ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
   ../../../intern/iksolver/extern ../blenloader ../quicktime
   ../../../intern/bmfont ../../../extern/bullet2/src
-  ../nodes
+  ../nodes ../../../extern/glew/include ../gpu
   ${SDL_INC}
   ${ZLIB_INC}
   ${PYTHON_INC}
index 1bb98239a6868b3bd19773b0bd63342bfdf48fd7..db67251f44efa9073478c33da20ad4251048d6ab 100644 (file)
@@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader ../quicktime'
 incs += ' #/extern/bullet2/src'
 incs += ' #/intern/bmfont'
 incs += ' #/intern/opennl/extern'
+incs += ' ../gpu #/extern/glew/include'
 
 incs += ' ' + env['BF_PYTHON_INC']
 incs += ' ' + env['BF_OPENGL_INC']
index 561d8d7c2a6bda1c843898f112ff3f971a776f71..4b6cb5e0999b1bd22ddd90789dbc317349e4bfac 100644 (file)
@@ -176,10 +176,6 @@ void free_editMesh(struct EditMesh *em){}
 void docenter_new(void){}
 int saveover(char *str){ return 0;}
 
-/* image.c */
-#include "DNA_image_types.h"
-void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff
-
 /* ipo.c */
 void copy_view3d_lock(short val){}     // was a hack, to make scene layer ipo's possible
 
index 03d45cce8887609c04dffb9052475be8834e5580..569229cb8abeff62dd88c9434934b84aa3c1c801 100644 (file)
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 ///////////////////////////////////
 ///////////////////////////////////
 
@@ -405,6 +409,8 @@ void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices)
        CustomData_swap(&dm->faceData, index, corner_indices);
 }
 
+///
+
 static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
 {
        DerivedMesh *dm = CDDM_from_mesh(me, ob);
@@ -868,6 +874,162 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
        emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
 }
 
+static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs),
+               int (*setDrawOptions)(void *userData, int index), void *userData) 
+{
+       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditMesh *em= emdm->em;
+       float (*vertexCos)[3]= emdm->vertexCos;
+       float (*vertexNos)[3]= emdm->vertexNos;
+       EditVert *eve;
+       EditFace *efa;
+       DMVertexAttribs attribs;
+       GPUVertexAttribs gattribs;
+       MTFace *tf;
+       int transp, new_transp, orig_transp, tfoffset;
+       int i, b, matnr, new_matnr, dodraw, layer;
+
+       dodraw = 0;
+       matnr = -1;
+
+       transp = GPU_get_material_blend_mode();
+       orig_transp = transp;
+       layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE);
+       tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset;
+
+       memset(&attribs, 0, sizeof(attribs));
+
+       /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+       glShadeModel(GL_SMOOTH);
+
+       for (i=0,eve=em->verts.first; eve; eve= eve->next)
+               eve->tmp.l = (long) i++;
+
+#define PASSATTRIB(efa, eve, vert) {                                                                                   \
+       if(attribs.totorco) {                                                                                                           \
+               float *orco = attribs.orco.array[eve->tmp.l];                                                   \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.tottface; b++) {                                                                         \
+               MTFace *tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset);   \
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.totmcol; b++) {                                                                          \
+               MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset);                \
+               GLubyte col[4];                                                                                                                 \
+               col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
+               glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
+       }                                                                                                                                                       \
+       if(attribs.tottang) {                                                                                                           \
+               float *tang = attribs.tang.array[i*4 + vert];                                                   \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
+       }                                                                                                                                                       \
+}
+
+       for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
+               int drawSmooth= (efa->flag & ME_SMOOTH);
+
+               if(setDrawOptions && !setDrawOptions(userData, i))
+                       continue;
+
+               new_matnr = efa->mat_nr + 1;
+               if(new_matnr != matnr) {
+                       dodraw = setMaterial(matnr = new_matnr, &gattribs);
+                       if(dodraw)
+                               DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+               }
+
+               if(tfoffset != -1) {
+                       tf = (MTFace*)((char*)efa->data)+tfoffset;
+                       new_transp = tf->transp;
+
+                       if(new_transp != transp) {
+                               if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+                                       GPU_set_material_blend_mode(orig_transp);
+                               else
+                                       GPU_set_material_blend_mode(new_transp);
+                               transp = new_transp;
+                       }
+               }
+
+               if(dodraw) {
+                       glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+                       if (!drawSmooth) {
+                               if(vertexCos) glNormal3fv(emdm->faceNos[i]);
+                               else glNormal3fv(efa->n);
+
+                               PASSATTRIB(efa, efa->v1, 0);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                               else glVertex3fv(efa->v1->co);
+
+                               PASSATTRIB(efa, efa->v2, 1);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                               else glVertex3fv(efa->v2->co);
+
+                               PASSATTRIB(efa, efa->v3, 2);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                               else glVertex3fv(efa->v3->co);
+
+                               if(efa->v4) {
+                                       PASSATTRIB(efa, efa->v4, 3);
+                                       if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                       else glVertex3fv(efa->v4->co);
+                               }
+                       } else {
+                               PASSATTRIB(efa, efa->v1, 0);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v1->no);
+                                       glVertex3fv(efa->v1->co);
+                               }
+
+                               PASSATTRIB(efa, efa->v2, 1);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v2->no);
+                                       glVertex3fv(efa->v2->co);
+                               }
+
+                               PASSATTRIB(efa, efa->v3, 2);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v3->no);
+                                       glVertex3fv(efa->v3->co);
+                               }
+
+                               if(efa->v4) {
+                                       PASSATTRIB(efa, efa->v4, 3);
+                                       if(vertexCos) {
+                                               glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
+                                               glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                       }
+                                       else {
+                                               glNormal3fv(efa->v4->no);
+                                               glVertex3fv(efa->v4->co);
+                                       }
+                               }
+                       }
+                       glEnd();
+               }
+       }
+}
+
+static void emDM_drawFacesGLSL(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs))
+{
+       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -1073,6 +1235,43 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
        }
 }
 
+static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
+{
+       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditMesh *em= emdm->em;
+       EditFace *efa;
+       char *data, *emdata;
+       void *datalayer;
+       int index, offset, size;
+
+       datalayer = DM_get_face_data_layer(dm, type);
+       if(datalayer)
+               return datalayer;
+
+       /* layers are store per face for editmesh, we convert to a temporary
+        * data layer array in the derivedmesh when these are requested */
+       if(type == CD_MTFACE || type == CD_MCOL) {
+               index = CustomData_get_layer_index(&em->fdata, type);
+
+               if(index != -1) {
+                       offset = em->fdata.layers[index].offset;
+                       size = CustomData_sizeof(type);
+
+                       DM_add_face_layer(dm, type, CD_CALLOC, NULL);
+                       index = CustomData_get_layer_index(&dm->faceData, type);
+                       dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
+
+                       data = datalayer = DM_get_face_data_layer(dm, type);
+                       for(efa=em->faces.first; efa; efa=efa->next, data+=size) {
+                               emdata = CustomData_em_get(&em->fdata, efa->data, type);
+                               memcpy(data, emdata, size);
+                       }
+               }
+       }
+
+       return datalayer;
+}
+
 static void emDM_release(DerivedMesh *dm)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -1108,6 +1307,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
        emdm->dm.copyVertArray = emDM_copyVertArray;
        emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
        emdm->dm.copyFaceArray = emDM_copyFaceArray;
+       emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
 
        emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
        emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
@@ -1118,7 +1318,9 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
        emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
        emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
        emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
+       emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
        emdm->dm.drawFacesTex = emDM_drawFacesTex;
+       emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
        emdm->dm.drawUVEdges = emDM_drawUVEdges;
 
        emdm->dm.release = emDM_release;
@@ -1548,7 +1750,7 @@ static void vDM_drawUVEdges(DerivedMesh *dm)
 }
 
 /* draw all VerseFaces */
-static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
 {
        VDerivedMesh *vdm = (VDerivedMesh*)dm;
        struct VerseFace *vface;
@@ -1648,6 +1850,8 @@ static void vDM_drawMappedFacesTex(
                int (*setDrawParams)(void *userData, int index),
                void *userData)
 {
+       /* not supported yet */
+       vDM_drawFacesTex(dm, NULL);
 }
 
 /**/
@@ -1789,19 +1993,23 @@ CustomDataMask get_viewedit_datamask()
        ScrArea *sa;
 
        /* check if we need tfaces & mcols due to face select or texture paint */
-       if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) {
+       if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT)
                mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
-       } else {
-               /* check if we need tfaces & mcols due to view mode */
-               for(sa = G.curscreen->areabase.first; sa; sa = sa->next) {
-                       if(sa->spacetype == SPACE_VIEW3D) {
-                               View3D *view = sa->spacedata.first;
-                               if(view->drawtype == OB_SHADED) {
-                                       /* this includes normals for mesh_create_shadedColors */
-                                       mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
-                               }
-                               if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
-                                       mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+
+       /* check if we need tfaces & mcols due to view mode */
+       for(sa = G.curscreen->areabase.first; sa; sa = sa->next) {
+               if(sa->spacetype == SPACE_VIEW3D) {
+                       View3D *view = sa->spacedata.first;
+                       if(view->drawtype == OB_SHADED) {
+                               /* this includes normals for mesh_create_shadedColors */
+                               mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
+                       }
+                       if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
+                               mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+
+                               if((G.fileflags & G_FILE_GAME_MAT) &&
+                                  (G.fileflags & G_FILE_GAME_MAT_GLSL)) {
+                                       mask |= CD_MASK_ORCO;
                                }
                        }
                }
@@ -1814,13 +2022,41 @@ CustomDataMask get_viewedit_datamask()
        return mask;
 }
 
-static DerivedMesh *create_orco_dm(Object *ob, Mesh *me)
+static float *get_editmesh_orco_verts(EditMesh *em)
+{
+       EditVert *eve;
+       float *orco;
+       int a, totvert;
+
+       /* these may not really be the orco's, but it's only for preview.
+        * could be solver better once, but isn't simple */
+
+       totvert= 0;
+       for(eve=em->verts.first; eve; eve=eve->next)
+               totvert++;
+       
+       orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco");
+
+       for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3)
+               VECCOPY(orco+a, eve->co);
+       
+       return orco;
+}
+
+static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em)
 {
        DerivedMesh *dm;
        float (*orco)[3];
 
-       dm= CDDM_from_mesh(me, ob);
-       orco= (float(*)[3])get_mesh_orco_verts(ob);
+       if(em) {
+               dm= CDDM_from_editmesh(em, me);
+               orco= (float(*)[3])get_editmesh_orco_verts(em);
+       }
+       else {
+               dm= CDDM_from_mesh(me, ob);
+               orco= (float(*)[3])get_mesh_orco_verts(ob);
+       }
+
        CDDM_apply_vert_coords(dm, orco);
        CDDM_calc_normals(dm);
        MEM_freeN(orco);
@@ -1828,7 +2064,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me)
        return dm;
 }
 
-static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
+static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm)
 {
        float (*orco)[3], (*layerorco)[3];
        int totvert;
@@ -1843,8 +2079,10 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
                else
                        dm->getVertCos(dm, orco);
        }
-       else
-               orco= (float(*)[3])get_mesh_orco_verts(ob);
+       else {
+               if(em) orco= (float(*)[3])get_editmesh_orco_verts(em);
+               else orco= (float(*)[3])get_mesh_orco_verts(ob);
+       }
 
        transform_mesh_orco_verts(ob->data, orco, totvert, 0);
 
@@ -1971,7 +2209,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                if(dm && mti->requiredDataMask) {
                        mask = mti->requiredDataMask(md);
                        if(mask & CD_MASK_ORCO)
-                               add_orco_dm(ob, dm, orcodm);
+                               add_orco_dm(ob, NULL, dm, orcodm);
                }
 
                /* How to apply modifier depends on (a) what we already have as
@@ -2024,7 +2262,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                        mask= (CustomDataMask)curr->link;
                        if(mask & CD_MASK_ORCO) {
                                if(!orcodm)
-                                       orcodm= create_orco_dm(ob, me);
+                                       orcodm= create_orco_dm(ob, me, NULL);
 
                                mask &= ~CD_MASK_ORCO;
                                DM_set_only_copy(orcodm, mask);
@@ -2105,10 +2343,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
 
        /* add an orco layer if needed */
        if(dataMask & CD_MASK_ORCO) {
-               add_orco_dm(ob, finaldm, orcodm);
+               add_orco_dm(ob, NULL, finaldm, orcodm);
 
                if(deform_r && *deform_r)
-                       add_orco_dm(ob, *deform_r, NULL);
+                       add_orco_dm(ob, NULL, *deform_r, NULL);
        }
 
        *final_r = finaldm;
@@ -2161,7 +2399,8 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
        EditMesh *em = G.editMesh;
        ModifierData *md;
        float (*deformedVerts)[3] = NULL;
-       DerivedMesh *dm;
+       CustomDataMask mask;
+       DerivedMesh *dm, *orcodm = NULL;
        int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
        LinkNode *datamasks, *curr;
 
@@ -2186,6 +2425,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
                if(!editmesh_modifier_is_enabled(md, dm))
                        continue;
 
+               /* add an orco layer if needed by this modifier */
+               if(dm && mti->requiredDataMask) {
+                       mask = mti->requiredDataMask(md);
+                       if(mask & CD_MASK_ORCO)
+                               add_orco_dm(ob, em, dm, orcodm);
+               }
+
                /* How to apply modifier depends on (a) what we already have as
                 * a result of previous modifiers (could be a DerivedMesh or just
                 * deformed vertices) and (b) what type the modifier is.
@@ -2236,6 +2482,23 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
                                }
                        }
 
+                       /* create an orco derivedmesh in parallel */
+                       mask= (CustomDataMask)curr->link;
+                       if(mask & CD_MASK_ORCO) {
+                               if(!orcodm)
+                                       orcodm= create_orco_dm(ob, ob->data, em);
+
+                               mask &= ~CD_MASK_ORCO;
+                               DM_set_only_copy(orcodm, mask);
+                               ndm = mti->applyModifierEM(md, ob, em, orcodm);
+
+                               if(ndm) {
+                                       /* if the modifier returned a new dm, release the old one */
+                                       if(orcodm && orcodm != ndm) orcodm->release(orcodm);
+                                       orcodm = ndm;
+                               }
+                       }
+
                        /* set the DerivedMesh to only copy needed data */
                        DM_set_only_copy(dm, (CustomDataMask)curr->link);
 
@@ -2294,6 +2557,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
                deformedVerts = NULL;
        }
 
+       /* add an orco layer if needed */
+       if(dataMask & CD_MASK_ORCO)
+               add_orco_dm(ob, em, *final_r, orcodm);
+
+       if(orcodm)
+               orcodm->release(orcodm);
+
        if(deformedVerts)
                MEM_freeN(deformedVerts);
 }
@@ -2588,7 +2858,7 @@ void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_c
                        old->release(old);
 
                        if(dataMask & CD_MASK_ORCO)
-                               add_orco_dm(ob, *dm, NULL);
+                               add_orco_dm(ob, NULL, *dm, NULL);
 
                        /* Restore the original verts */
                        me->mr->newlvl= BLI_countlist(&me->mr->levels);
@@ -2817,6 +3087,8 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo
        return numleft;
 }
 
+/* ******************* GLSL ******************** */
+
 void DM_add_tangent_layer(DerivedMesh *dm)
 {
        /* mesh vars */
@@ -2937,4 +3209,89 @@ void DM_add_tangent_layer(DerivedMesh *dm)
        MEM_freeN(vtangents);
 }
 
+void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
+{
+       CustomData *vdata, *fdata, *tfdata = NULL;
+       int a, b, layer;
+
+       /* From the layers requested by the GLSL shader, figure out which ones are
+        * actually available for this derivedmesh, and retrieve the pointers */
+
+       memset(attribs, 0, sizeof(DMVertexAttribs));
+
+       vdata = &dm->vertData;
+       fdata = &dm->faceData;
+
+       /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we
+        * can use offsets instead */
+       if(dm->release == emDM_release)
+               tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata;
+       else
+               tfdata = fdata;
+
+       /* add a tangent layer if necessary */
+       for(b = 0; b < gattribs->totlayer; b++)
+               if(gattribs->layer[b].type == CD_TANGENT)
+                       if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1)
+                               DM_add_tangent_layer(dm);
+
+       for(b = 0; b < gattribs->totlayer; b++) {
+               if(gattribs->layer[b].type == CD_MTFACE) {
+                       /* uv coordinates */
+                       if(gattribs->layer[b].name[0])
+                               layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
+                                       gattribs->layer[b].name);
+                       else
+                               layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
+
+                       if(layer != -1) {
+                               a = attribs->tottface++;
+
+                               attribs->tface[a].array = tfdata->layers[layer].data;
+                               attribs->tface[a].emOffset = tfdata->layers[layer].offset;
+                               attribs->tface[a].glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+               else if(gattribs->layer[b].type == CD_MCOL) {
+                       /* vertex colors */
+                       if(gattribs->layer[b].name[0])
+                               layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
+                                       gattribs->layer[b].name);
+                       else
+                               layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
+
+                       if(layer != -1) {
+                               a = attribs->totmcol++;
+
+                               attribs->mcol[a].array = tfdata->layers[layer].data;
+                               attribs->mcol[a].emOffset = tfdata->layers[layer].offset;
+                               attribs->mcol[a].glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+               else if(gattribs->layer[b].type == CD_TANGENT) {
+                       /* tangents */
+                       layer = CustomData_get_layer_index(fdata, CD_TANGENT);
+
+                       if(layer != -1) {
+                               attribs->tottang = 1;
+
+                               attribs->tang.array = fdata->layers[layer].data;
+                               attribs->tang.emOffset = fdata->layers[layer].offset;
+                               attribs->tang.glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+               else if(gattribs->layer[b].type == CD_ORCO) {
+                       /* original coordinates */
+                       layer = CustomData_get_layer_index(vdata, CD_ORCO);
+
+                       if(layer != -1) {
+                               attribs->totorco = 1;
+
+                               attribs->orco.array = vdata->layers[layer].data;
+                               attribs->orco.emOffset = vdata->layers[layer].offset;
+                               attribs->orco.glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+       }
+}
 
index 74c6c551a831eb58e2e39d4dfde25aa137fe8217..8921ea5d3b7b287297515b9efd68ddc11364d956 100644 (file)
@@ -36,6 +36,7 @@ include nan_compile.mk
 CFLAGS += $(LEVEL_1_C_WARNINGS)
 
 # OpenGL and Python
+CPPFLAGS += -I$(NAN_GLEW)/include
 CPPFLAGS += -I$(OPENGL_HEADERS)
 CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
 
@@ -74,6 +75,9 @@ CPPFLAGS += -I$(NAN_ZLIB)/include
 #path to nodes
 CPPFLAGS += -I../../nodes
 
+#path to gpu
+CPPFLAGS += -I../../gpu
+
 # path to our own external headerfiles
 CPPFLAGS += -I..
 
index 5b96bf110566cecceb0fb21dba124d84ec07a60e..2648233aca592e652870b4763c822dec4b60800b 100644 (file)
@@ -347,6 +347,8 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
        VECCOPY(pchan->loc, chan->loc);
        VECCOPY(pchan->size, chan->size);
        QUATCOPY(pchan->quat, chan->quat);
+       Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat);
+       Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat);
        pchan->flag= chan->flag;
        
        con= chan->constraints.first;
index 1592c3e55042b2289c41581fd87ddcde7c84155d..e2ce4b9f6f3a7892df20f6bf08665c60dba9a6d2 100644 (file)
@@ -303,7 +303,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated)
        DupliObject *dob;
        Group *group;
        GroupObject *go;
-       float mat[4][4];
+       float mat[4][4], tmat[4][4];
        
        if(ob->dup_group==NULL) return;
        group= ob->dup_group;
@@ -320,7 +320,15 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated)
                /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
                if(go->ob!=ob) {
                        
-                       Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
+                       /* Group Dupli Offset, should apply after everything else */
+                       if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) {
+                               Mat4CpyMat4(tmat, go->ob->obmat);
+                               VecSubf(tmat[3], tmat[3], group->dupli_ofs);
+                               Mat4MulMat4(mat, tmat, ob->obmat);
+                       } else {
+                               Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
+                       }
+                       
                        dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated);
                        dob->no_draw= (dob->origlay & group->layer)==0;
                        
@@ -1059,7 +1067,8 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist,
        }
 }
 
-/* note; group dupli's already set transform matrix. see note in group_duplilist() */
+/* Returns a list of DupliObject
+ * note; group dupli's already set transform matrix. see note in group_duplilist() */
 ListBase *object_duplilist(Scene *sce, Object *ob)
 {
        ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist");
index aca51e56c6e5363fd4d3cf84534abe0d5ce2a048..1fe6447752e72f37dd51c11d09663925e3b7cb19 100644 (file)
@@ -525,6 +525,7 @@ typedef struct UndoElem {
        char str[FILE_MAXDIR+FILE_MAXFILE];
        char name[MAXUNDONAME];
        MemFile memfile;
+       uintptr_t undosize;
 } UndoElem;
 
 static ListBase undobase={NULL, NULL};
@@ -555,6 +556,7 @@ static int read_undosave(UndoElem *uel)
 /* name can be a dynamic string */
 void BKE_write_undo(char *name)
 {
+       uintptr_t maxmem, totmem, memused;
        int nr, success;
        UndoElem *uel;
        
@@ -616,8 +618,36 @@ void BKE_write_undo(char *name)
                
                if(curundo->prev) prevfile= &(curundo->prev->memfile);
                
+               memused= MEM_get_memory_in_use();
                success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err);
-               
+               curundo->undosize= MEM_get_memory_in_use() - memused;
+       }
+
+       if(U.undomemory != 0) {
+               /* limit to maximum memory (afterwards, we can't know in advance) */
+               totmem= 0;
+               maxmem= ((uintptr_t)U.undomemory)*1024*1024;
+
+               /* keep at least two (original + other) */
+               uel= undobase.last;
+               while(uel && uel->prev) {
+                       totmem+= uel->undosize;
+                       if(totmem>maxmem) break;
+                       uel= uel->prev;
+               }
+
+               if(uel) {
+                       if(uel->prev && uel->prev->prev)
+                               uel= uel->prev;
+
+                       while(undobase.first!=uel) {
+                               UndoElem *first= undobase.first;
+                               BLI_remlink(&undobase, first);
+                               /* the merge is because of compression */
+                               BLO_merge_memfile(&first->memfile, &first->next->memfile);
+                               MEM_freeN(first);
+                       }
+               }
        }
 }
 
@@ -683,14 +713,14 @@ char *BKE_undo_menu_string(void)
        UndoElem *uel;
        DynStr *ds= BLI_dynstr_new();
        char *menu;
-       
+
        BLI_dynstr_append(ds, "Global Undo History %t");
        
        for(uel= undobase.first; uel; uel= uel->next) {
                BLI_dynstr_append(ds, "|");
                BLI_dynstr_append(ds, uel->name);
        }
-       
+
        menu= BLI_dynstr_get_cstring(ds);
        BLI_dynstr_free(ds);
 
index 4bc3c3a388336b9cb0e37a176fa2356a84f868f3..c30d86431b13354921e8312830f53413683718d7 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 #include <string.h>
 #include <limits.h>
 
@@ -243,7 +247,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm)
        glEnd();
 }
 
-static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
 {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
        MVert *mvert = cddm->mvert;
@@ -271,7 +275,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
                   || new_shademodel != shademodel) {
                        glEnd();
 
-                       drawCurrentMat = setMaterial(matnr = new_matnr);
+                       drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
 
                        glShadeModel(shademodel = new_shademodel);
                        glBegin(glmode = new_glmode);
@@ -556,6 +560,134 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
        cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
 }
 
+static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+       CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
+       GPUVertexAttribs gattribs;
+       DMVertexAttribs attribs;
+       MVert *mvert = cddm->mvert;
+       MFace *mface = cddm->mface;
+       MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
+       float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
+       int a, b, dodraw, smoothnormal, matnr, new_matnr;
+       int transp, new_transp, orig_transp;
+       int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+
+       matnr = -1;
+       smoothnormal = 0;
+       dodraw = 0;
+       transp = GPU_get_material_blend_mode();
+       orig_transp = transp;
+
+       memset(&attribs, 0, sizeof(attribs));
+
+       glShadeModel(GL_SMOOTH);
+       glBegin(GL_QUADS);
+
+       for(a = 0; a < dm->numFaceData; a++, mface++) {
+               new_matnr = mface->mat_nr + 1;
+
+               if(new_matnr != matnr) {
+                       glEnd();
+
+                       dodraw = setMaterial(matnr = new_matnr, &gattribs);
+                       if(dodraw)
+                               DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+
+                       glBegin(GL_QUADS);
+               }
+
+               if(!dodraw) {
+                       continue;
+               }
+               else if(setDrawOptions) {
+                       orig = index[a];
+
+                       if(orig == ORIGINDEX_NONE)
+                               continue;
+                       else if(!setDrawOptions(userData, orig))
+                               continue;
+               }
+
+               if(tf) {
+                       new_transp = tf[a].transp;
+
+                       if(new_transp != transp) {
+                               glEnd();
+
+                               if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+                                       GPU_set_material_blend_mode(orig_transp);
+                               else
+                                       GPU_set_material_blend_mode(new_transp);
+                               transp = new_transp;
+
+                               glBegin(GL_QUADS);
+                       }
+               }
+
+               smoothnormal = (mface->flag & ME_SMOOTH);
+
+               if(!smoothnormal) {
+                       if(nors) {
+                               glNormal3fv(nors[a]);
+                       }
+                       else {
+                               /* TODO ideally a normal layer should always be available */
+                               float nor[3];
+                               if(mface->v4) {
+                                       CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
+                                                                  mvert[mface->v3].co, mvert[mface->v4].co,
+                                                                  nor);
+                               } else {
+                                       CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
+                                                                 mvert[mface->v3].co, nor);
+                               }
+                               glNormal3fv(nor);
+                       }
+               }
+
+#define PASSVERT(index, vert) {                                                                                                        \
+       if(attribs.totorco)                                                                                                                     \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
+       for(b = 0; b < attribs.tottface; b++) {                                                                         \
+               MTFace *tf = &attribs.tface[b].array[a];                                                                \
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.totmcol; b++) {                                                                          \
+               MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
+               GLubyte col[4];                                                                                                                 \
+               col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
+               glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
+       }                                                                                                                                                       \
+       if(attribs.tottang) {                                                                                                           \
+               float *tang = attribs.tang.array[a*4 + vert];                                                   \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
+       }                                                                                                                                                       \
+       if(smoothnormal)                                                                                                                        \
+               glNormal3sv(mvert[index].no);                                                                                   \
+       glVertex3fv(mvert[index].co);                                                                                           \
+}
+
+               PASSVERT(mface->v1, 0);
+               PASSVERT(mface->v2, 1);
+               PASSVERT(mface->v3, 2);
+               if(mface->v4)
+                       PASSVERT(mface->v4, 3)
+               else
+                       PASSVERT(mface->v3, 2)
+
+#undef PASSVERT
+       }
+       glEnd();
+
+       glShadeModel(GL_FLAT);
+}
+
+static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
+{
+       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
 {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@ -713,8 +845,10 @@ static CDDerivedMesh *cdDM_create(const char *desc)
        dm->drawFacesSolid = cdDM_drawFacesSolid;
        dm->drawFacesColored = cdDM_drawFacesColored;
        dm->drawFacesTex = cdDM_drawFacesTex;
+       dm->drawFacesGLSL = cdDM_drawFacesGLSL;
        dm->drawMappedFaces = cdDM_drawMappedFaces;
        dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
+       dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
 
        dm->foreachMappedVert = cdDM_foreachMappedVert;
        dm->foreachMappedEdge = cdDM_foreachMappedEdge;
index 295b8fe3552fadfa7b7d871cc38f7bbdea67dd99..45b8bb7935cbbf32a5b11da0d7cf98a699cc64de 100644 (file)
@@ -730,3 +730,24 @@ void curvemapping_initialize(CurveMapping *cumap)
                        curvemap_make_table(cumap->cm+a, &cumap->clipr);
        }
 }
+
+void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size)
+{
+       int a;
+       
+       *size = CM_TABLE+1;
+       *array = MEM_callocN(sizeof(float)*(*size)*4, "CurveMapping");
+       curvemapping_initialize(cumap);
+
+       for(a=0; a<*size; a++) {
+               if(cumap->cm[0].table)
+                       (*array)[a*4+0]= cumap->cm[0].table[a].y;
+               if(cumap->cm[1].table)
+                       (*array)[a*4+1]= cumap->cm[1].table[a].y;
+               if(cumap->cm[2].table)
+                       (*array)[a*4+2]= cumap->cm[2].table[a].y;
+               if(cumap->cm[3].table)
+                       (*array)[a*4+3]= cumap->cm[3].table[a].y;
+       }
+}
+
index 07537e3a81c6b4fa8cafbb6b5809e15d4021d74f..27fa00ac239b1b8ce693f82cfb54c07ff7cf026c 100644 (file)
@@ -53,6 +53,7 @@
 #include "DNA_packedFile_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_sequence_types.h"
 #include "DNA_texture_types.h"
 #include "DNA_userdef_types.h"
 
 
 #include "RE_pipeline.h"
 
-/* bad level; call to free_realtime_image */
-#include "BKE_bad_level_calls.h"       
-
 /* for stamp drawing to an image */
 #include "BMF_Api.h"
 
 #include "blendef.h"
 #include "BSE_time.h"
 
+#include "GPU_extensions.h"
+#include "GPU_draw.h"
+
 #include "BLO_sys_types.h" // for intptr_t support
 
 /* max int, to indicate we don't store sequences in ibuf */
@@ -240,7 +241,7 @@ static void image_free_buffers(Image *ima)
                ima->rr= NULL;
        }       
        
-       free_realtime_image(ima);
+       GPU_free_image(ima);
        
        ima->ok= IMA_OK;
 }
@@ -620,7 +621,7 @@ void free_old_images()
                           This gives textures a "second chance" to be used before dying.
                        */
                        if(ima->bindcode || ima->repbind) {
-                               free_realtime_image(ima);
+                               GPU_free_image(ima);
                                ima->lastused = ctime;
                        }
                        /* Otherwise, just kill the buffers */
index 800775eb2b3ce4db0f3c997bc89b1884b81b94ef..1448ff8e41723ba37e904a9ba203e7076e074859 100644 (file)
@@ -1392,6 +1392,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
                        else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7];
                        else if(icu->adrcode & MA_MAP9) mtex= ma->mtex[8];
                        else if(icu->adrcode & MA_MAP10) mtex= ma->mtex[9];
+                       else if(icu->adrcode & MA_MAP12) mtex= ma->mtex[11];
+                       else if(icu->adrcode & MA_MAP11) mtex= ma->mtex[10];
+                       else if(icu->adrcode & MA_MAP13) mtex= ma->mtex[12];
+                       else if(icu->adrcode & MA_MAP14) mtex= ma->mtex[13];
+                       else if(icu->adrcode & MA_MAP15) mtex= ma->mtex[14];
+                       else if(icu->adrcode & MA_MAP16) mtex= ma->mtex[15];
+                       else if(icu->adrcode & MA_MAP17) mtex= ma->mtex[16];
+                       else if(icu->adrcode & MA_MAP18) mtex= ma->mtex[17];
                        
                        if(mtex) {
                                poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
@@ -1481,7 +1489,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
                        else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7];
                        else if(icu->adrcode & MA_MAP9) mtex= wo->mtex[8];
                        else if(icu->adrcode & MA_MAP10) mtex= wo->mtex[9];
-                       
+                       else if(icu->adrcode & MA_MAP11) mtex= wo->mtex[10];
+                       else if(icu->adrcode & MA_MAP12) mtex= wo->mtex[11];
+                       else if(icu->adrcode & MA_MAP13) mtex= wo->mtex[12];
+                       else if(icu->adrcode & MA_MAP14) mtex= wo->mtex[13];
+                       else if(icu->adrcode & MA_MAP15) mtex= wo->mtex[14];
+                       else if(icu->adrcode & MA_MAP16) mtex= wo->mtex[15];
+                       else if(icu->adrcode & MA_MAP17) mtex= wo->mtex[16];
+                       else if(icu->adrcode & MA_MAP18) mtex= wo->mtex[17];
                        if(mtex) {
                                poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
                        }
@@ -1526,6 +1541,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
                        else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7];
                        else if(icu->adrcode & MA_MAP9) mtex= la->mtex[8];
                        else if(icu->adrcode & MA_MAP10) mtex= la->mtex[9];
+                       else if(icu->adrcode & MA_MAP11) mtex= la->mtex[10];
+                       else if(icu->adrcode & MA_MAP12) mtex= la->mtex[11];
+                       else if(icu->adrcode & MA_MAP13) mtex= la->mtex[12];
+                       else if(icu->adrcode & MA_MAP14) mtex= la->mtex[13];
+                       else if(icu->adrcode & MA_MAP15) mtex= la->mtex[14];
+                       else if(icu->adrcode & MA_MAP16) mtex= la->mtex[15];
+                       else if(icu->adrcode & MA_MAP17) mtex= la->mtex[16];
+                       else if(icu->adrcode & MA_MAP18) mtex= la->mtex[17];
                        
                        if(mtex) {
                                poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
index 3983eecdaba5b39d6bf0f379d2da0657346c20df..f05b84f6e90ddc8727c9af9467fbbd015feb17a5 100644 (file)
@@ -61,6 +61,8 @@
 
 #include "BPY_extern.h"
 
+#include "GPU_material.h"
+
 /* used in UI and render */
 Material defmaterial;
 
@@ -96,6 +98,9 @@ void free_material(Material *ma)
                ntreeFreeTree(ma->nodetree);
                MEM_freeN(ma->nodetree);
        }
+
+       if(ma->gpumaterial.first)
+               GPU_material_free(ma);
 }
 
 void init_material(Material *ma)
@@ -207,6 +212,8 @@ Material *copy_material(Material *ma)
        if(ma->nodetree) {
                man->nodetree= ntreeCopyTree(ma->nodetree, 0);  /* 0 == full new tree */
        }
+
+       man->gpumaterial.first= man->gpumaterial.last= NULL;
        
        return man;
 }
index 43e48c3bacd377121366167e955127749a5e7f00..77b9ea4fa2dd3de99b9cf28a28c139cbe464c646 100644 (file)
 #include "BLI_editVert.h"
 #include "BLI_arithb.h"
 
-int update_realtime_texture(MTFace *tface, double time)
-{
-       Image *ima;
-       int     inc = 0;
-       float   diff;
-       int     newframe;
-
-       ima = tface->tpage;
-
-       if (!ima)
-               return 0;
-
-       if (ima->lastupdate<0)
-               ima->lastupdate = 0;
-
-       if (ima->lastupdate>time)
-               ima->lastupdate=(float)time;
-
-       if(ima->tpageflag & IMA_TWINANIM) {
-               if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
-               
-               /* check: is the bindcode not in the array? Then free. (still to do) */
-               
-               diff = (float)(time-ima->lastupdate);
-
-               inc = (int)(diff*(float)ima->animspeed);
-
-               ima->lastupdate+=((float)inc/(float)ima->animspeed);
-
-               newframe = ima->lastframe+inc;
-
-               if (newframe > (int)ima->twend)
-                       newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
-
-               ima->lastframe = newframe;
-       }
-       return inc;
-}
-
 void mesh_update_customdata_pointers(Mesh *me)
 {
        me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
index 4e36df35a1492022a66b1cce81ddd856241e2076..4dfe651c01fafcc617341a20d61375d77d172b78 100644 (file)
@@ -68,6 +68,9 @@
 
 #include "SHD_node.h"
 
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 static ListBase empty_list = {NULL, NULL};
 ListBase node_all_composit = {NULL, NULL};
 ListBase node_all_shaders = {NULL, NULL};
@@ -2352,6 +2355,117 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
        ntreeEndExecTree(ntree);
 }
 
+/* GPU material from shader nodes */
+
+static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+{
+       bNodeSocket *sock;
+       int i;
+
+       for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
+               memset(&gs[i], 0, sizeof(gs[i]));
+
+       QUATCOPY(gs[i].vec, ns[i]->vec);
+               gs[i].link= ns[i]->data;
+
+               if (sock->type == SOCK_VALUE)
+                       gs[i].type= GPU_FLOAT;
+               else if (sock->type == SOCK_VECTOR)
+                       gs[i].type= GPU_VEC3;
+               else if (sock->type == SOCK_RGBA)
+                       gs[i].type= GPU_VEC4;
+               else
+                       gs[i].type= GPU_NONE;
+
+               gs[i].name = "";
+               gs[i].hasinput= ns[i]->hasinput;
+               gs[i].hasoutput= ns[i]->hasinput;
+               gs[i].sockettype= ns[i]->sockettype;
+       }
+
+       gs[i].type= GPU_NONE;
+}
+
+static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+{
+       bNodeSocket *sock;
+       int i;
+
+       for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
+               ns[i]->data= gs[i].link;
+               ns[i]->hasinput= gs[i].hasinput;
+               ns[i]->hasoutput= gs[i].hasoutput;
+               ns[i]->sockettype= gs[i].sockettype;
+       }
+}
+
+static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out)
+{
+       bNode *node;
+       bNodeTree *ntree= (bNodeTree *)gnode->id;
+       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
+       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
+       GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+       int doit = 0;
+       
+       if(ntree==NULL) return;
+       
+       stack+= gnode->stack_index;
+               
+       for(node= ntree->nodes.first; node; node= node->next) {
+               if(node->typeinfo->gpufunc) {
+                       group_node_get_stack(node, stack, nsin, nsout, in, out);
+
+                       doit = 0;
+                       
+                       /* for groups, only execute outputs for edited group */
+                       if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+                               if(gnode->flag & NODE_GROUP_EDIT)
+                                       if(node->flag & NODE_DO_OUTPUT)
+                                               doit = 1;
+                       }
+                       else
+                               doit = 1;
+
+                       if(doit)  {
+                               gpu_from_node_stack(&node->inputs, nsin, gpuin);
+                               gpu_from_node_stack(&node->outputs, nsout, gpuout);
+                               if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
+                                       data_from_gpu_stack(&node->outputs, nsout, gpuout);
+                       }
+               }
+       }
+}
+
+void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
+{
+       bNode *node;
+       bNodeStack *stack;
+       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
+       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
+       GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+
+       if((ntree->init & NTREE_EXEC_INIT)==0)
+               ntreeBeginExecTree(ntree);
+
+       stack= ntree->stack;
+
+       for(node= ntree->nodes.first; node; node= node->next) {
+               if(node->typeinfo->gpufunc) {
+                       node_get_stack(node, stack, nsin, nsout);
+                       gpu_from_node_stack(&node->inputs, nsin, gpuin);
+                       gpu_from_node_stack(&node->outputs, nsout, gpuout);
+                       if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
+                               data_from_gpu_stack(&node->outputs, nsout, gpuout);
+               }
+        else if(node->type==NODE_GROUP && node->id) {
+                       node_get_stack(node, stack, nsin, nsout);
+                       gpu_node_group_execute(stack, mat, node, nsin, nsout);
+               }
+       }
+
+       ntreeEndExecTree(ntree);
+}
 
 /* **************** call to switch lamploop for material node ************ */
 
index 08845fb1a538ac6ecd2c200b29761921346889e4..3e43b7fb803551c9bff1144101b4f63acfbe494e 100644 (file)
 
 #include "BPY_extern.h"
 
+#include "GPU_material.h"
+
 #include "blendef.h"
 
 /* Local function protos */
@@ -267,6 +269,7 @@ void free_object(Object *ob)
                MEM_freeN(ob->pd);
        }
        if(ob->soft) sbFree(ob->soft);
+       if(ob->gpulamp.first) GPU_lamp_free(ob);
 }
 
 static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -917,7 +920,7 @@ Object *add_only_object(int type, char *name)
        QuatOne(ob->dquat);
 #endif 
 
-       ob->col[0]= ob->col[1]= ob->col[2]= 0.0;
+       ob->col[0]= ob->col[1]= ob->col[2]= 1.0;
        ob->col[3]= 1.0;
 
        ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0;
@@ -1216,6 +1219,7 @@ Object *copy_object(Object *ob)
        obn->vnode = NULL;
 #endif
 
+       obn->gpulamp.first = obn->gpulamp.last = NULL;
 
        return obn;
 }
index 4ec9f7a95de13177dc324ec58a9aec9e33db7ae9..e6f736659342aee39156279c320f73cd3fdf404d 100644 (file)
@@ -76,6 +76,8 @@
 #include "BKE_modifier.h"
 #include "BKE_scene.h"
 
+#include "PIL_time.h"
+
 #include "BSE_headerbuttons.h"
 
 #include "blendef.h"
index bba79bd6d287bf7f507e27ddf7abc7964c460b6e..f334fc39daa1c351ecb66c9e10ac69d404b64eaa 100644 (file)
 
 #include "BIF_gl.h"
 
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 #include "CCGSubSurf.h"
 
 typedef struct _VertData {
@@ -1599,7 +1603,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
 }
 
        /* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
+static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
@@ -1621,7 +1625,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
                        mat_nr= 0;
                }
                
-               if (!setMaterial(mat_nr+1))
+               if (!setMaterial(mat_nr+1, NULL))
                        continue;
 
                glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
@@ -1666,6 +1670,168 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
 
        ccgFaceIterator_free(fi);
 }
+
+       /* Only used by non-editmesh types */
+static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
+       CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+       CCGSubSurf *ss = ccgdm->ss;
+       CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
+       GPUVertexAttribs gattribs;
+       DMVertexAttribs attribs;
+       MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
+       int gridSize = ccgSubSurf_getGridSize(ss);
+       int gridFaces = gridSize - 1;
+       int edgeSize = ccgSubSurf_getEdgeSize(ss);
+       int transp, orig_transp, new_transp;
+       char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS);
+       int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
+
+       doDraw = 0;
+       numVerts = 0;
+       matnr = -1;
+       transp = GPU_get_material_blend_mode();
+       orig_transp = transp;
+
+       memset(&attribs, 0, sizeof(attribs));
+
+#define PASSATTRIB(dx, dy, vert) {                                                                                             \
+       if(attribs.totorco) {                                                                                                           \
+               index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize);                 \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.tottface; b++) {                                                                         \
+               MTFace *tf = &attribs.tface[b].array[a];                                                                \
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.totmcol; b++) {                                                                          \
+               MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
+               GLubyte col[4];                                                                                                                 \
+               col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
+               glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
+       }                                                                                                                                                       \
+       if(attribs.tottang) {                                                                                                           \
+               float *tang = attribs.tang.array[a*4 + vert];                                                   \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
+       }                                                                                                                                                       \
+}
+
+       totface = ccgSubSurf_getNumFaces(ss);
+       for(a = 0, i = 0; i < totface; i++) {
+               CCGFace *f = ccgdm->faceMap[i].face;
+               int S, x, y, drawSmooth;
+               int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+               int origIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f);
+               
+               numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+               if(faceFlags) {
+                       drawSmooth = (faceFlags[index*4] & ME_SMOOTH);
+                       new_matnr= faceFlags[index*4 + 1] + 1;
+               }
+               else {
+                       drawSmooth = 1;
+                       new_matnr= 1;
+               }
+
+               if(new_matnr != matnr) {
+                       doDraw = setMaterial(matnr = new_matnr, &gattribs);
+                       if(doDraw)
+                               DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+               }
+
+               if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) {
+                       a += gridFaces*gridFaces*numVerts;
+                       continue;
+               }
+
+               if(tf) {
+                       new_transp = tf[i].transp;
+
+                       if(new_transp != transp) {
+                               if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+                                       GPU_set_material_blend_mode(orig_transp);
+                               else
+                                       GPU_set_material_blend_mode(new_transp);
+                               transp = new_transp;
+                       }
+               }
+
+               glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
+               for (S=0; S<numVerts; S++) {
+                       VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+                       VertData *vda, *vdb;
+
+                       if (drawSmooth) {
+                               for (y=0; y<gridFaces; y++) {
+                                       glBegin(GL_QUAD_STRIP);
+                                       for (x=0; x<gridFaces; x++) {
+                                               vda = &faceGridData[(y+0)*gridSize + x];
+                                               vdb = &faceGridData[(y+1)*gridSize + x];
+                                               
+                                               PASSATTRIB(0, 0, 0);
+                                               glNormal3fv(vda->no);
+                                               glVertex3fv(vda->co);
+
+                                               PASSATTRIB(0, 1, 1);
+                                               glNormal3fv(vdb->no);
+                                               glVertex3fv(vdb->co);
+
+                                               if(x != gridFaces-1)
+                                                       a++;
+                                       }
+
+                                       vda = &faceGridData[(y+0)*gridSize + x];
+                                       vdb = &faceGridData[(y+1)*gridSize + x];
+
+                                       PASSATTRIB(0, 0, 3);
+                                       glNormal3fv(vda->no);
+                                       glVertex3fv(vda->co);
+
+                                       PASSATTRIB(0, 1, 2);
+                                       glNormal3fv(vdb->no);
+                                       glVertex3fv(vdb->co);
+
+                                       glEnd();
+
+                                       a++;
+                               }
+                       } else {
+                               glBegin(GL_QUADS);
+                               for (y=0; y<gridFaces; y++) {
+                                       for (x=0; x<gridFaces; x++) {
+                                               float *aco = faceGridData[(y+0)*gridSize + x].co;
+                                               float *bco = faceGridData[(y+0)*gridSize + x + 1].co;
+                                               float *cco = faceGridData[(y+1)*gridSize + x + 1].co;
+                                               float *dco = faceGridData[(y+1)*gridSize + x].co;
+
+                                               ccgDM_glNormalFast(aco, bco, cco, dco);
+
+                                               PASSATTRIB(0, 1, 1);
+                                               glVertex3fv(dco);
+                                               PASSATTRIB(1, 1, 2);
+                                               glVertex3fv(cco);
+                                               PASSATTRIB(1, 0, 3);
+                                               glVertex3fv(bco);
+                                               PASSATTRIB(0, 0, 0);
+                                               glVertex3fv(aco);
+                                               
+                                               a++;
+                                       }
+                               }
+                               glEnd();
+                       }
+               }
+       }
+
+#undef PASSATTRIB
+
+       ccgFaceIterator_free(fi);
+}
+
+static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
+       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
 static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
@@ -2143,8 +2309,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
        ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
        ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
+       ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
        ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
        ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
+       ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
        ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
 
        ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c
new file mode 100644 (file)
index 0000000..54ce425
--- /dev/null
@@ -0,0 +1,254 @@
+/**
+ * $Id: $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Ian Thompson.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "DNA_text_types.h"
+#include "BKE_text.h"
+#include "BKE_suggestions.h"
+
+/**********************/
+/* Static definitions */
+/**********************/
+
+static Text *activeToolText = NULL;
+static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL};
+static char *documentation = NULL;
+static int doc_lines = 0;
+
+static int txttl_cmp(const char *first, const char *second, int len) { 
+       int cmp, i;
+       for (cmp=0, i=0; i<len; i++) {
+               if (cmp= toupper(first[i])-toupper(second[i])) {
+                       break;
+               }
+       }
+       return cmp;
+}
+
+static void txttl_free_suggest() {
+       SuggItem *item, *prev;
+       for (item = suggestions.last; item; item=prev) {
+               prev = item->prev;
+               MEM_freeN(item);
+       }
+       suggestions.first = suggestions.last = NULL;
+       suggestions.firstmatch = suggestions.lastmatch = NULL;
+       suggestions.selected = NULL;
+       suggestions.top = 0;
+}
+
+static void txttl_free_docs() {
+       if (documentation) {
+               MEM_freeN(documentation);
+               documentation = NULL;
+       }
+}
+
+/**************************/
+/* General tool functions */
+/**************************/
+
+void free_texttools() {
+       txttl_free_suggest();
+       txttl_free_docs();
+}
+
+void texttool_text_set_active(Text *text) {
+       if (activeToolText == text) return;
+       texttool_text_clear();
+       activeToolText = text;
+}
+
+void texttool_text_clear() {
+       free_texttools();
+       activeToolText = NULL;
+}
+
+short texttool_text_is_active(Text *text) {
+       return activeToolText==text ? 1 : 0;
+}
+
+/***************************/
+/* Suggestion list methods */
+/***************************/
+
+void texttool_suggest_add(const char *name, char type) {
+       SuggItem *newitem, *item;
+       int len, cmp;
+
+       newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem");
+       if (!newitem) {
+               printf("Failed to allocate memory for suggestion.\n");
+               return;
+       }
+
+       newitem->name = (char *) (newitem + 1);
+       len = strlen(name);
+       strncpy(newitem->name, name, len);
+       newitem->name[len] = '\0';
+       newitem->type = type;
+       newitem->prev = newitem->next = NULL;
+
+       /* Perform simple linear search for ordered storage */
+       if (!suggestions.first || !suggestions.last) {
+               suggestions.first = suggestions.last = newitem;
+       } else {
+               cmp = -1;
+               for (item=suggestions.last; item; item=item->prev) {
+                       cmp = txttl_cmp(name, item->name, len);
+
+                       /* Newitem comes after this item, insert here */
+                       if (cmp >= 0) {
+                               newitem->prev = item;
+                               if (item->next)
+                                       item->next->prev = newitem;
+                               newitem->next = item->next;
+                               item->next = newitem;
+
+                               /* At last item, set last pointer here */
+                               if (item == suggestions.last)
+                                       suggestions.last = newitem;
+                               break;
+                       }
+               }
+               /* Reached beginning of list, insert before first */
+               if (cmp < 0) {
+                       newitem->next = suggestions.first;
+                       suggestions.first->prev = newitem;
+                       suggestions.first = newitem;
+               }
+       }
+       suggestions.firstmatch = suggestions.lastmatch = suggestions.selected = NULL;
+       suggestions.top= 0;
+}
+
+void texttool_suggest_prefix(const char *prefix) {
+       SuggItem *match, *first, *last;
+       int cmp, len = strlen(prefix), top = 0;
+
+       if (!suggestions.first) return;
+       if (len==0) {
+               suggestions.selected = suggestions.firstmatch = suggestions.first;
+               suggestions.lastmatch = suggestions.last;
+               return;
+       }
+       
+       first = last = NULL;
+       for (match=suggestions.first; match; match=match->next) {
+               cmp = txttl_cmp(prefix, match->name, len);
+               if (cmp==0) {
+                       if (!first) {
+                               first = match;
+                               suggestions.top = top;
+                       }
+               } else if (cmp<0) {
+                       if (!last) {
+                               last = match->prev;
+                               break;
+                       }
+               }
+               top++;
+       }
+       if (first) {
+               if (!last) last = suggestions.last;
+               suggestions.firstmatch = first;
+               suggestions.lastmatch = last;
+               suggestions.selected = first;
+       } else {
+               suggestions.firstmatch = NULL;
+               suggestions.lastmatch = NULL;
+               suggestions.selected = NULL;
+               suggestions.top = 0;
+       }
+}
+
+void texttool_suggest_clear() {
+       txttl_free_suggest();
+}
+
+SuggItem *texttool_suggest_first() {
+       return suggestions.firstmatch;
+}
+
+SuggItem *texttool_suggest_last() {
+       return suggestions.lastmatch;
+}
+
+void texttool_suggest_select(SuggItem *sel) {
+       suggestions.selected = sel;
+}
+
+SuggItem *texttool_suggest_selected() {
+       return suggestions.selected;
+}
+
+int *texttool_suggest_top() {
+       return &suggestions.top;
+}
+
+/*************************/
+/* Documentation methods */
+/*************************/
+
+void texttool_docs_show(const char *docs) {
+       int len;
+
+       if (!docs) return;
+
+       len = strlen(docs);
+
+       if (documentation) {
+               MEM_freeN(documentation);
+               documentation = NULL;
+       }
+
+       /* Ensure documentation ends with a '\n' */
+       if (docs[len-1] != '\n') {
+               documentation = MEM_mallocN(len+2, "Documentation");
+               strncpy(documentation, docs, len);
+               documentation[len++] = '\n';
+       } else {
+               documentation = MEM_mallocN(len+1, "Documentation");
+               strncpy(documentation, docs, len);
+       }
+       documentation[len] = '\0';
+}
+
+char *texttool_docs_get() {
+       return documentation;
+}
+
+void texttool_docs_clear() {
+       txttl_free_docs();
+}
index 53b7bb975a3fac812709970cbbaf7587588dcd3e..12133fc4fff4aa583196bd7bf7cf0ddab1c55612 100644 (file)
@@ -30,6 +30,8 @@
  */
 
 #include <string.h> /* strstr */
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -81,12 +83,19 @@ The st->top determines at what line the top of the text is displayed.
 If the user moves the cursor the st containing that cursor should
 be popped ... other st's retain their own top location.
 
-*/ /***************/
-
+Markers
+--
+The mrk->flags define the behaviour and relationships between markers. The
+upper two bytes are used to hold a group ID, the lower two are normal flags. If
+TMARK_EDITALL is set the group ID defines which other markers should be edited.
 
-/****************/ /*
-       Undo
+The mrk->clr field is used to visually group markers where the flags may not
+match. A template system, for example, may allow editing of repeating tokens
+(in one group) but include other marked positions (in another group) all in the
+same template with the same colour.
 
+Undo
+--
 Undo/Redo works by storing
 events in a queue, and a pointer
 to the current position in the
@@ -145,6 +154,7 @@ void free_text(Text *text)
        }
        
        BLI_freelistN(&text->lines);
+       BLI_freelistN(&text->markers);
 
        if(text->name) MEM_freeN(text->name);
        MEM_freeN(text->undo_buf);
@@ -169,10 +179,11 @@ Text *add_empty_text(char *name)
        ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM;
 
        ta->lines.first= ta->lines.last= NULL;
+       ta->markers.first= ta->markers.last= NULL;
 
        tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
        tmp->line= (char*) MEM_mallocN(1, "textline_string");
-       tmp->format= (char*) MEM_mallocN(2, "Syntax_format");
+       tmp->format= NULL;
        
        tmp->line[0]=0;
        tmp->len= 0;
@@ -209,11 +220,12 @@ static void cleanup_textline(TextLine * tl)
 int reopen_text(Text *text)
 {
        FILE *fp;
-       int i, llen, len;
+       int i, llen, len, res;
        unsigned char *buffer;
        TextLine *tmp;
        char sfile[FILE_MAXFILE];
        char str[FILE_MAXDIR+FILE_MAXFILE];
+       struct stat st;
 
        if (!text || !text->name) return 0;
        
@@ -242,7 +254,7 @@ int reopen_text(Text *text)
        text->undo_len= TXT_INIT_UNDO;
        text->undo_buf= MEM_mallocN(text->undo_len, "undo buf");
        
-       text->flags= TXT_ISDIRTY | TXT_ISTMP; 
+       text->flags= TXT_ISTMP; 
        
        fseek(fp, 0L, SEEK_END);
        len= ftell(fp);
@@ -256,6 +268,9 @@ int reopen_text(Text *text)
        len = fread(buffer, 1, len, fp);
 
        fclose(fp);
+
+       res= stat(str, &st);
+       text->mtime= st.st_mtime;
        
        text->nlines=0;
        i=0;
@@ -264,7 +279,7 @@ int reopen_text(Text *text)
                if (buffer[i]=='\n') {
                        tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
                        tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
-                       tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
+                       tmp->format= NULL;
                        
                        if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
                        tmp->line[llen]=0;
@@ -284,7 +299,7 @@ int reopen_text(Text *text)
        if (llen!=0 || text->nlines==0) {
                tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
                tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
-               tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
+               tmp->format= NULL;
                
                if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
 
@@ -307,12 +322,13 @@ int reopen_text(Text *text)
 Text *add_text(char *file) 
 {
        FILE *fp;
-       int i, llen, len;
+       int i, llen, len, res;
        unsigned char *buffer;
        TextLine *tmp;
        Text *ta;
        char sfile[FILE_MAXFILE];
        char str[FILE_MAXDIR+FILE_MAXFILE];
+       struct stat st;
 
        BLI_strncpy(str, file, FILE_MAXDIR+FILE_MAXFILE);
        if (G.scene) /* can be NULL (bg mode) */
@@ -326,6 +342,7 @@ Text *add_text(char *file)
        ta->id.us= 1;
 
        ta->lines.first= ta->lines.last= NULL;
+       ta->markers.first= ta->markers.last= NULL;
        ta->curl= ta->sell= NULL;
 
 /*     ta->flags= TXT_ISTMP | TXT_ISEXT; */
@@ -348,6 +365,9 @@ Text *add_text(char *file)
        len = fread(buffer, 1, len, fp);
 
        fclose(fp);
+
+       res= stat(str, &st);
+       ta->mtime= st.st_mtime;
        
        ta->nlines=0;
        i=0;
@@ -356,7 +376,7 @@ Text *add_text(char *file)
                if (buffer[i]=='\n') {
                        tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
                        tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
-                       tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
+                       tmp->format= NULL;
                        
                        if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
                        tmp->line[llen]=0;
@@ -376,7 +396,7 @@ Text *add_text(char *file)
        if (llen!=0 || ta->nlines==0) {
                tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
                tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
-               tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
+               tmp->format= NULL;
                
                if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
 
@@ -410,6 +430,7 @@ Text *copy_text(Text *ta)
        tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP;
        
        tan->lines.first= tan->lines.last= NULL;
+       tan->markers.first= tan->markers.last= NULL;
        tan->curl= tan->sell= NULL;
        
        tan->nlines= ta->nlines;
@@ -419,7 +440,7 @@ Text *copy_text(Text *ta)
        while (line) {
                tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
                tmp->line= MEM_mallocN(line->len+1, "textline_string");
-               tmp->format= MEM_mallocN(line->len+2, "Syntax_format");
+               tmp->format= NULL;
                
                strcpy(tmp->line, line->line);
 
@@ -440,14 +461,14 @@ Text *copy_text(Text *ta)
 /* Editing utility functions */
 /*****************************/
 
-static void make_new_line (TextLine *line, char *newline, char *newformat
+static void make_new_line (TextLine *line, char *newline) 
 {
        if (line->line) MEM_freeN(line->line);
        if (line->format) MEM_freeN(line->format);
        
        line->line= newline;
        line->len= strlen(newline);
-       line->format= newformat;
+       line->format= NULL;
 }
 
 static TextLine *txt_new_line(char *str)
@@ -458,7 +479,7 @@ static TextLine *txt_new_line(char *str)
        
        tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
        tmp->line= MEM_mallocN(strlen(str)+1, "textline_string");
-       tmp->format= MEM_mallocN(strlen(str)+2, "Syntax_format");
+       tmp->format= NULL;
        
        strcpy(tmp->line, str);
        
@@ -476,7 +497,7 @@ static TextLine *txt_new_linen(char *str, int n)
        
        tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
        tmp->line= MEM_mallocN(n+1, "textline_string");
-       tmp->format= MEM_mallocN(n+2, "Syntax_format");
+       tmp->format= NULL;
        
        BLI_strncpy(tmp->line, str, n+1);
        
@@ -553,6 +574,19 @@ static void txt_make_dirty (Text *text)
        if (text->compiled) BPY_free_compiled_text(text);
 }
 
+/* 0:whitespace, 1:punct, 2:alphanumeric */
+static short txt_char_type (char ch)
+{
+       if (ch <= ' ') return 0;
+       if (ch <= '/') return 1;
+       if (ch <= '9') return 2;
+       if (ch <= '@') return 1;
+       if (ch <= 'Z') return 2;
+       if (ch <= '`') return 1;
+       if (ch <= 'z') return 2;
+       return 1;
+}
+
 /****************************/
 /* Cursor utility functions */
 /****************************/
@@ -606,8 +640,7 @@ void txt_move_up(Text *text, short sel)
                        if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
                }
        } else {
-               *charp= 0;
-               if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
+               txt_move_bol(text, sel);
        }
 
        if(!sel) txt_pop_sel(text);
@@ -632,8 +665,7 @@ void txt_move_down(Text *text, short sel)
                } else
                        if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);  
        } else {
-               *charp= (*linep)->len;
-               if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
+               txt_move_eol(text, sel);
        }
 
        if(!sel) txt_pop_sel(text);
@@ -689,6 +721,68 @@ void txt_move_right(Text *text, short sel)
        if(!sel) txt_pop_sel(text);
 }
 
+void txt_jump_left(Text *text, short sel)
+{
+       TextLine **linep, *oldl;
+       int *charp, oldc, count, i;
+       unsigned char oldu;
+
+       if (!text) return;
+       if(sel) txt_curs_sel(text, &linep, &charp);
+       else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
+       if (!*linep) return;
+
+       oldl= *linep;
+       oldc= *charp;
+       oldu= undoing;
+       undoing= 1; /* Don't push individual moves to undo stack */
+
+       count= 0;
+       for (i=0; i<3; i++) {
+               if (count < 2) {
+                       while (*charp>0 && txt_char_type((*linep)->line[*charp-1])==i) {
+                               txt_move_left(text, sel);
+                               count++;
+                       }
+               }
+       }
+       if (count==0) txt_move_left(text, sel);
+
+       undoing= oldu;
+       if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_jump_right(Text *text, short sel)
+{
+       TextLine **linep, *oldl;
+       int *charp, oldc, count, i;
+       unsigned char oldu;
+
+       if (!text) return;
+       if(sel) txt_curs_sel(text, &linep, &charp);
+       else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
+       if (!*linep) return;
+
+       oldl= *linep;
+       oldc= *charp;
+       oldu= undoing;
+       undoing= 1; /* Don't push individual moves to undo stack */
+
+       count= 0;
+       for (i=0; i<3; i++) {
+               if (count < 2) {
+                       while (*charp<(*linep)->len && txt_char_type((*linep)->line[*charp])==i) {
+                               txt_move_right(text, sel);
+                               count++;
+                       }
+               }
+       }
+       if (count==0) txt_move_right(text, sel);
+
+       undoing= oldu;
+       if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
 void txt_move_bol (Text *text, short sel) 
 {
        TextLine **linep;
@@ -760,6 +854,11 @@ void txt_move_eof (Text *text, short sel)
 }
 
 void txt_move_toline (Text *text, unsigned int line, short sel)
+{
+       txt_move_to(text, line, 0, sel);
+}
+
+void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel)
 {
        TextLine **linep, *oldl;
        int *charp, oldc;
@@ -777,10 +876,12 @@ void txt_move_toline (Text *text, unsigned int line, short sel)
                if ((*linep)->next) *linep= (*linep)->next;
                else break;
        }
-       *charp= 0;
+       if (ch>(*linep)->len)
+               ch= (*linep)->len;
+       *charp= ch;
        
        if(!sel) txt_pop_sel(text);
-       if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);      
+       if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
 }
 
 /****************************/
@@ -865,7 +966,9 @@ int txt_has_sel(Text *text)
 static void txt_delete_sel (Text *text)
 {
        TextLine *tmpl;
-       char *buf, *format;
+       TextMarker *mrk;
+       char *buf;
+       int move, lineno;
        
        if (!text) return;
        if (!text->curl) return;
@@ -882,13 +985,33 @@ static void txt_delete_sel (Text *text)
        }
 
        buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string");
-       format= MEM_mallocN(text->curc+(text->sell->len - text->selc)+2, "Syntax_format");
        
+       if (text->curl != text->sell) {
+               txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0);
+               move= txt_get_span(text->curl, text->sell);
+       } else {
+               mrk= txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0);
+               if (mrk && (mrk->start > text->curc || mrk->end < text->selc))
+                       txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0);
+               move= 0;
+       }
+
+       mrk= txt_find_marker_region(text, text->sell, text->selc-1, text->sell->len, 0, 0);
+       if (mrk) {
+               lineno= mrk->lineno;
+               do {
+                       mrk->lineno -= move;
+                       if (mrk->start > text->curc) mrk->start -= text->selc - text->curc;
+                       mrk->end -= text->selc - text->curc;
+                       mrk= mrk->next;
+               } while (mrk && mrk->lineno==lineno);
+       }
+
        strncpy(buf, text->curl->line, text->curc);
        strcpy(buf+text->curc, text->sell->line + text->selc);
        buf[text->curc+(text->sell->len - text->selc)]=0;
 
-       make_new_line(text->curl, buf, format);
+       make_new_line(text->curl, buf);
        
        tmpl= text->sell;
        while (tmpl != text->curl) {
@@ -995,22 +1118,31 @@ char *txt_to_buf (Text *text)
        return buf;
 }
 
-int txt_find_string(Text *text, char *findstr)
+int txt_find_string(Text *text, char *findstr, int wrap)
 {
        TextLine *tl, *startl;
        char *s= NULL;
+       int oldcl, oldsl, oldcc, oldsc;
 
        if (!text || !text->curl || !text->sell) return 0;
        
        txt_order_cursors(text);
 
+       oldcl= txt_get_span(text->lines.first, text->curl);
+       oldsl= txt_get_span(text->lines.first, text->sell);
        tl= startl= text->sell;
+       oldcc= text->curc;
+       oldsc= text->selc;
        
        s= strstr(&tl->line[text->selc], findstr);
        while (!s) {
                tl= tl->next;
-               if (!tl)
-                       tl= text->lines.first;
+               if (!tl) {
+                       if (wrap)
+                               tl= text->lines.first;
+                       else
+                               break;
+               }
 
                s= strstr(tl->line, findstr);
                if (tl==startl)
@@ -1018,10 +1150,10 @@ int txt_find_string(Text *text, char *findstr)
        }
        
        if (s) {
-               text->curl= text->sell= tl;
-               text->curc= (int) (s-tl->line);
-               text->selc= text->curc + strlen(findstr);
-               
+               int newl= txt_get_span(text->lines.first, tl);
+               int newc= (int)(s-tl->line);
+               txt_move_to(text, newl, newc, 0);
+               txt_move_to(text, newl, newc + strlen(findstr), 1);
                return 1;                               
        } else
                return 0;
@@ -1621,7 +1753,6 @@ void txt_do_undo(Text *text)
 
                case UNDO_SWAP:
                        txt_curs_swap(text);
-                       txt_do_undo(text); /* swaps should appear transparent */
                        break;
 
                case UNDO_DBLOCK:
@@ -1736,6 +1867,19 @@ void txt_do_undo(Text *text)
                        
                        break;
        }
+
+       /* next undo step may need evaluating */
+       if (text->undo_pos>=0) {
+               switch (text->undo_buf[text->undo_pos]) {
+                       case UNDO_STO:
+                               txt_do_undo(text);
+                               txt_do_redo(text); /* selections need restoring */
+                               break;
+                       case UNDO_SWAP:
+                               txt_do_undo(text); /* swaps should appear transparent */
+                               break;
+               }
+       }
        
        undoing= 0;     
 }
@@ -1810,7 +1954,7 @@ void txt_do_redo(Text *text)
 
                case UNDO_SWAP:
                        txt_curs_swap(text);
-                       txt_do_undo(text); /* swaps should appear transparent a*/
+                       txt_do_redo(text); /* swaps should appear transparent a*/
                        break;
                        
                case UNDO_CTO:
@@ -1947,22 +2091,37 @@ void txt_do_redo(Text *text)
 void txt_split_curline (Text *text) 
 {
        TextLine *ins;
-       char *left, *right, *fleft, *fright;
+       TextMarker *mrk;
+       char *left, *right;
+       int lineno= -1;
        
        if (!text) return;
        if (!text->curl) return;
 
-       txt_delete_sel(text);   
+       txt_delete_sel(text);
+
+       /* Move markers */
+
+       lineno= txt_get_span(text->lines.first, text->curl);
+       mrk= text->markers.first;
+       while (mrk) {
+               if (mrk->lineno==lineno && mrk->start>text->curc) {
+                       mrk->lineno++;
+                       mrk->start -= text->curc;
+                       mrk->end -= text->curc;
+               } else if (mrk->lineno > lineno) {
+                       mrk->lineno++;
+               }
+               mrk= mrk->next;
+       }
 
        /* Make the two half strings */
 
        left= MEM_mallocN(text->curc+1, "textline_string");
-       fleft= MEM_mallocN(text->curc+2, "Syntax_format");
        if (text->curc) memcpy(left, text->curl->line, text->curc);
        left[text->curc]=0;
        
        right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string");
-       fright= MEM_mallocN(text->curl->len - text->curc+2, "Syntax_format");
        if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc);
        right[text->curl->len - text->curc]=0;
 
@@ -1973,11 +2132,11 @@ void txt_split_curline (Text *text)
        
        ins= MEM_mallocN(sizeof(TextLine), "textline");
        ins->line= left;
-       ins->format= fleft;
+       ins->format= NULL;
        ins->len= text->curc;
        
        text->curl->line= right;
-       text->curl->format= fright;
+       text->curl->format= NULL;
        text->curl->len= text->curl->len - text->curc;
        
        BLI_insertlinkbefore(&text->lines, text->curl, ins);    
@@ -1993,9 +2152,23 @@ void txt_split_curline (Text *text)
 
 static void txt_delete_line (Text *text, TextLine *line) 
 {
+       TextMarker *mrk=NULL, *nxt;
+       int lineno= -1;
+
        if (!text) return;
        if (!text->curl) return;
 
+       lineno= txt_get_span(text->lines.first, line);
+       mrk= text->markers.first;
+       while (mrk) {
+               nxt= mrk->next;
+               if (mrk->lineno==lineno)
+                       BLI_freelinkN(&text->markers, mrk);
+               else if (mrk->lineno > lineno)
+                       mrk->lineno--;
+               mrk= nxt;
+       }
+
        BLI_remlink (&text->lines, line);
        
        if (line->line) MEM_freeN(line->line);
@@ -2009,21 +2182,35 @@ static void txt_delete_line (Text *text, TextLine *line)
 
 static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
 {
-       char *tmp, *format;
+       char *tmp;
+       TextMarker *mrk= NULL;
+       int lineno=-1;
        
        if (!text) return;
        
        if(!linea || !lineb) return;
+
+       mrk= txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0);
+       if (mrk) {
+               lineno= mrk->lineno;
+            &nbs