Merging r39948 through r39988 from trunk into vgroup_modifiers. vgroup_modifiers
authorBastien Montagne <montagne29@wanadoo.fr>
Wed, 7 Sep 2011 05:40:12 +0000 (05:40 +0000)
committerBastien Montagne <montagne29@wanadoo.fr>
Wed, 7 Sep 2011 05:40:12 +0000 (05:40 +0000)
63 files changed:
CMakeLists.txt
build_files/cmake/macros.cmake
build_files/scons/config/win32-mingw-config.py
doc/python_api/rst/bgl.rst
doc/python_api/rst/info_quickstart.rst
doc/python_api/rst/info_tips_and_tricks.rst
doc/python_api/sphinx_doc_gen.py
intern/guardedalloc/MEM_sys_types.h
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/intern/string.c
source/blender/blenloader/BLO_sys_types.h
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/collada/CMakeLists.txt
source/blender/collada/DocumentExporter.cpp
source/blender/collada/SceneExporter.cpp [new file with mode: 0644]
source/blender/collada/SceneExporter.h [new file with mode: 0644]
source/blender/editors/gpencil/CMakeLists.txt
source/blender/editors/gpencil/drawgpencil.c
source/blender/editors/gpencil/gpencil_edit.c
source/blender/editors/gpencil/gpencil_intern.h
source/blender/editors/gpencil/gpencil_ops.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/gpencil/gpencil_undo.c [new file with mode: 0644]
source/blender/editors/include/ED_gpencil.h
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_header.c
source/blender/editors/transform/transform.c
source/blender/editors/util/undo.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_screen.c
source/blender/makesrna/intern/rna_texture.c
source/blender/makesrna/intern/rna_texture_api.c
source/blender/makesrna/intern/rna_wm.c
source/blender/makesrna/intern/rna_world.c
source/blender/nodes/composite/node_composite_tree.c
source/blender/nodes/composite/nodes/node_composite_common.c
source/blender/nodes/intern/node_socket.c
source/blender/nodes/shader/node_shader_tree.c
source/blender/nodes/shader/nodes/node_shader_common.c
source/blender/nodes/texture/node_texture_tree.c
source/blender/nodes/texture/nodes/node_texture_common.c
source/blender/python/generic/bpy_internal_import.c
source/blender/python/intern/bpy_rna.c
source/blender/python/mathutils/mathutils_geometry.c
source/blender/render/intern/source/render_texture.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Expressions/ListValue.cpp
source/gameengine/Expressions/Value.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_SoundActuator.cpp

index b54b18aab379a34eee6966aa472b89b064ce26a6..8b5693fb1aaecfb84b5fa68bb323eca7b6223e75 100644 (file)
@@ -797,7 +797,7 @@ elseif(WIN32)
        else()
                # keep GCC spesific stuff here
                if(CMAKE_COMPILER_IS_GNUCC)
-                       set(PLATFORM_LINKLIBS "-lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid")
+                       set(PLATFORM_LINKLIBS "-lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32")
                        set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing")
 
                        add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
index 58938c8b0b02d57b30aa3b5b78a959a60e666b69..d09215d040df8a528c1e6fd11fa78a4df888487f 100644 (file)
@@ -392,6 +392,7 @@ macro(remove_strict_flags)
                remove_flag("-Wstrict-prototypes")
                remove_flag("-Wunused-parameter")
                remove_flag("-Wwrite-strings")
+               remove_flag("-Wundef")
                remove_flag("-Wshadow")
                remove_flag("-Werror=[^ ]+")
                remove_flag("-Werror")
index c815b76ef73ff4412080bb5ef5aa2c0675e99a0b..37d693db5609ed3dcde1cdb131ce4633082cfe3f 100644 (file)
@@ -174,7 +174,7 @@ C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wstrict-pro
 
 CC_WARN = [ '-Wall' ]
 
-LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid']
+LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32']
 
 PLATFORM_LINKFLAGS = ['--stack,2097152']
 
index 5f3158bf5dd2ec82d4bcd3dc5ae097ba01f7e7cc..61400351d166fd59ec4493e54025563f50887ccf 100644 (file)
@@ -56,9 +56,9 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type n: int
    :arg n: Specifies the number of textures to be queried.
-   :type textures: :class:`Buffer` object I{type GL_INT}
+   :type textures: :class:`bgl.Buffer` object I{type GL_INT}
    :arg textures: Specifies an array containing the names of the textures to be queried
-   :type residences: :class:`Buffer` object I{type GL_INT}(boolean)
+   :type residences: :class:`bgl.Buffer` object I{type GL_INT}(boolean)
    :arg residences: An array in which the texture residence status in returned.
       The residence status of a texture named by an element of textures is
       returned in the corresponding element of residences.
@@ -101,7 +101,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :type xmove, ymove: float
    :arg xmove, ymove: Specify the x and y offsets to be added to the current raster position after
       the bitmap is drawn.
-   :type bitmap: :class:`Buffer` object I{type GL_BYTE}
+   :type bitmap: :class:`bgl.Buffer` object I{type GL_BYTE}
    :arg bitmap: Specifies the address of the bitmap image.
 
 
@@ -139,7 +139,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg n: Specifies the number of display lists to be executed.
    :type type: Enumerated constant
    :arg type: Specifies the type of values in lists.
-   :type lists: :class:`Buffer` object
+   :type lists: :class:`bgl.Buffer` object
    :arg lists: Specifies the address of an array of name offsets in the display list.
       The pointer type is void because the offsets can be bytes, shorts, ints, or floats,
       depending on the value of type.
@@ -217,7 +217,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type plane: Enumerated constant
    :arg plane: Specifies which clipping plane is being positioned.
-   :type equation: :class:`Buffer` object I{type GL_FLOAT}(double)
+   :type equation: :class:`bgl.Buffer` object I{type GL_FLOAT}(double)
    :arg equation: Specifies the address of an array of four double- precision
       floating-point values. These values are interpreted as a plane equation.
 
@@ -340,7 +340,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type n: int
    :arg n: Specifies the number of textures to be deleted
-   :type textures: :class:`Buffer` I{GL_INT}
+   :type textures: :class:`bgl.Buffer` I{GL_INT}
    :arg textures: Specifies an array of textures to be deleted
 
 
@@ -413,7 +413,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg format: Specifies the format of the pixel data.
    :type type: Enumerated constant
    :arg type: Specifies the data type for pixels.
-   :type pixels: :class:`Buffer` object
+   :type pixels: :class:`bgl.Buffer` object
    :arg pixels: Specifies a pointer to the pixel data.
 
 
@@ -512,7 +512,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :type type: Enumerated constant
    :arg type: Specifies a symbolic constant that describes the information that
       will be returned for each vertex.
-   :type buffer: :class:`Buffer` object I{GL_FLOAT}
+   :type buffer: :class:`bgl.Buffer` object I{GL_FLOAT}
    :arg buffer: Returns the feedback data.
 
 
@@ -592,7 +592,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type n: int
    :arg n: Specifies the number of textures name to be generated.
-   :type textures: :class:`Buffer` object I{type GL_INT}
+   :type textures: :class:`bgl.Buffer` object I{type GL_INT}
    :arg textures: Specifies an array in which the generated textures names are stored.
 
 
@@ -620,7 +620,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg plane: Specifies a clipping plane. The number of clipping planes depends on the
       implementation, but at least six clipping planes are supported. They are identified by
       symbolic names of the form GL_CLIP_PLANEi where 0 < i < GL_MAX_CLIP_PLANES.
-   :type equation:  :class:`Buffer` object I{type GL_FLOAT}
+   :type equation:  :class:`bgl.Buffer` object I{type GL_FLOAT}
    :arg equation:  Returns four float (double)-precision values that are the coefficients of the
       plane equation of plane in eye coordinates. The initial value is (0, 0, 0, 0).
 
@@ -646,7 +646,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
       names of the form GL_LIGHTi where 0 < i < GL_MAX_LIGHTS.
    :type pname: Enumerated constant
    :arg pname: Specifies a light source parameter for light.
-   :type params:  :class:`Buffer` object. Depends on function prototype.
+   :type params:  :class:`bgl.Buffer` object. Depends on function prototype.
    :arg params: Returns the requested data.
 
 
@@ -662,7 +662,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg target: Specifies the symbolic name of a map.
    :type query: Enumerated constant
    :arg query: Specifies which parameter to return.
-   :type v: :class:`Buffer` object. Depends on function prototype.
+   :type v: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg v: Returns the requested data.
 
 
@@ -679,7 +679,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
       representing the front and back materials, respectively.
    :type pname: Enumerated constant
    :arg pname: Specifies the material parameter to return.
-   :type params: :class:`Buffer` object. Depends on function prototype.
+   :type params: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg params: Returns the requested data.
 
 
@@ -693,7 +693,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type map:  Enumerated constant
    :arg map: Specifies the name of the pixel map to return.
-   :type values: :class:`Buffer` object. Depends on function prototype.
+   :type values: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg values: Returns the pixel map contents.
 
 
@@ -703,7 +703,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    .. seealso:: `OpenGL Docs <http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getpolygonstipple.html>`_
 
-   :type mask: :class:`Buffer` object I{type GL_BYTE}
+   :type mask: :class:`bgl.Buffer` object I{type GL_BYTE}
    :arg mask: Returns the stipple pattern. The initial value is all 1's.
 
 
@@ -730,7 +730,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg target: Specifies a texture environment. Must be GL_TEXTURE_ENV.
    :type pname: Enumerated constant
    :arg pname: Specifies the symbolic name of a texture environment parameter.
-   :type params: :class:`Buffer` object. Depends on function prototype.
+   :type params: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg params: Returns the requested data.
 
 
@@ -746,7 +746,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg coord: Specifies a texture coordinate.
    :type pname: Enumerated constant
    :arg pname: Specifies the symbolic name of the value(s) to be returned.
-   :type params: :class:`Buffer` object. Depends on function prototype.
+   :type params: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg params: Returns the requested data.
 
 
@@ -765,7 +765,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg format: Specifies a pixel format for the returned data.
    :type type: Enumerated constant
    :arg type: Specifies a pixel type for the returned data.
-   :type pixels: :class:`Buffer` object.
+   :type pixels: :class:`bgl.Buffer` object.
    :arg pixels: Returns the texture image. Should be a pointer to an array of the
       type specified by type
 
@@ -785,7 +785,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
       Level 0 is the base image level. Level n is the nth mipmap reduction image.
    :type pname: Enumerated constant
    :arg pname: Specifies the symbolic name of a texture parameter.
-   :type params: :class:`Buffer` object. Depends on function prototype.
+   :type params: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg params: Returns the requested data.
 
 
@@ -801,7 +801,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg target: Specifies the symbolic name of the target texture.
    :type pname: Enumerated constant
    :arg pname: Specifies the symbolic name the target texture.
-   :type params: :class:`Buffer` object. Depends on function prototype.
+   :type params: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg params: Returns the texture parameters.
 
 
@@ -826,7 +826,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    .. seealso:: `OpenGL Docs <http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/index_.html>`_
 
-   :type c: :class:`Buffer` object. Depends on function prototype.
+   :type c: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg c: Specifies a pointer to a one element array that contains the new value for
       the current color index.
 
@@ -956,7 +956,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    .. seealso:: `OpenGL Docs <http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/loadmatrix.html>`_
 
-   :type m: :class:`Buffer` object. Depends on function prototype.
+   :type m: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg m: Specifies a pointer to 16 consecutive values, which are used as the elements
       of a 4x4 column-major matrix.
 
@@ -1002,7 +1002,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
       occupy contiguous memory locations.
    :type order: int
    :arg order: Specifies the number of control points. Must be positive.
-   :type points: :class:`Buffer` object. Depends on function prototype.
+   :type points: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg points: Specifies a pointer to the array of control points.
 
 
@@ -1043,7 +1043,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :type vorder: int
    :arg vorder: Specifies the dimension of the control point array in the v axis.
       Must be positive. The initial value is 1.
-   :type points: :class:`Buffer` object. Depends on function prototype.
+   :type points: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg points: Specifies a pointer to the array of control points.
 
 
@@ -1103,7 +1103,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    .. seealso:: `OpenGL Docs <http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/multmatrix.html>`_
 
-   :type m: :class:`Buffer` object. Depends on function prototype.
+   :type m: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg m: Points to 16 consecutive values that are used as the elements of a 4x4 column
       major matrix.
 
@@ -1132,7 +1132,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :type nx, ny, nz: Depends on function prototype. (non - 'v' prototypes only)
    :arg nx, ny, nz: Specify the x, y, and z coordinates of the new current normal.
       The initial value of the current normal is the unit vector, (0, 0, 1).
-   :type v: :class:`Buffer` object. Depends on function prototype. ('v' prototypes)
+   :type v: :class:`bgl.Buffer` object. Depends on function prototype. ('v' prototypes)
    :arg v: Specifies a pointer to an array of three elements: the x, y, and z coordinates
       of the new current normal.
 
@@ -1177,7 +1177,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg map: Specifies a symbolic map name.
    :type mapsize: int
    :arg mapsize: Specifies the size of the map being defined.
-   :type values: :class:`Buffer` object. Depends on function prototype.
+   :type values: :class:`bgl.Buffer` object. Depends on function prototype.
    :arg values: Specifies an array of mapsize values.
 
 
@@ -1266,7 +1266,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    .. seealso:: `OpenGL Docs <http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/polygonstipple.html>`_
 
-   :type mask: :class:`Buffer` object I{type GL_BYTE}
+   :type mask: :class:`bgl.Buffer` object I{type GL_BYTE}
    :arg mask: Specifies a pointer to a 32x32 stipple pattern that will be unpacked
       from memory in the same way that glDrawPixels unpacks pixels.
 
@@ -1307,9 +1307,9 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type n: int
    :arg n: Specifies the number of textures to be prioritized.
-   :type textures: :class:`Buffer` I{type GL_INT}
+   :type textures: :class:`bgl.Buffer` I{type GL_INT}
    :arg textures: Specifies an array containing the names of the textures to be prioritized.
-   :type priorities: :class:`Buffer` I{type GL_FLOAT}
+   :type priorities: :class:`bgl.Buffer` I{type GL_FLOAT}
    :arg priorities: Specifies an array containing the texture priorities.
       A priority given in an element of priorities applies to the texture named
       by the corresponding element of textures.
@@ -1417,7 +1417,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg format: Specifies the format of the pixel data.
    :type type: Enumerated constant
    :arg type: Specifies the data type of the pixel data.
-   :type pixels: :class:`Buffer` object
+   :type pixels: :class:`bgl.Buffer` object
    :arg pixels: Returns the pixel data.
 
 
@@ -1496,7 +1496,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type size: int
    :arg size: Specifies the size of buffer
-   :type buffer: :class:`Buffer` I{type GL_INT}
+   :type buffer: :class:`bgl.Buffer` I{type GL_INT}
    :arg buffer: Returns the selection data
 
 
@@ -1575,7 +1575,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :type s, t, r, q: Depends on function prototype. (r and q for '3' and '4' prototypes only)
    :arg s, t, r, q: Specify s, t, r, and q texture coordinates. Not all parameters are
       present in all forms of the command.
-   :type v: :class:`Buffer` object. Depends on function prototype. (for 'v' prototypes only)
+   :type v: :class:`bgl.Buffer` object. Depends on function prototype. (for 'v' prototypes only)
    :arg v: Specifies a pointer to an array of one, two, three, or four elements,
       which in turn specify the s, t, r, and q texture coordinates.
 
@@ -1642,7 +1642,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg format: Specifies the format of the pixel data.
    :type type: Enumerated constant
    :arg type: Specifies the data type of the pixel data.
-   :type pixels: :class:`Buffer` object.
+   :type pixels: :class:`bgl.Buffer` object.
    :arg pixels: Specifies a pointer to the image data in memory.
 
 
@@ -1673,7 +1673,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg format: Specifies the format of the pixel data.
    :type type: Enumerated constant
    :arg type: Specifies the data type of the pixel data.
-   :type pixels: :class:`Buffer` object.
+   :type pixels: :class:`bgl.Buffer` object.
    :arg pixels: Specifies a pointer to the image data in memory.
 
 
@@ -1720,7 +1720,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :type x, y, z, w: Depends on function prototype (z and w for '3' and '4' prototypes only)
    :arg x, y, z, w: Specify x, y, z, and w coordinates of a vertex. Not all parameters
       are present in all forms of the command.
-   :type v: :class:`Buffer` object. Depends of function prototype (for 'v'
+   :type v: :class:`bgl.Buffer` object. Depends of function prototype (for 'v'
       prototypes only)
    :arg v: Specifies a pointer to an array of two, three, or four elements. The
       elements of a two-element array are x and y; of a three-element array,
@@ -1795,7 +1795,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
    :arg x, y: Specify the center of a picking region in window coordinates.
    :type width, height: double
    :arg width, height: Specify the width and height, respectively, of the picking region in window coordinates.
-   :type viewport: :class:`Buffer` object. [int]
+   :type viewport: :class:`bgl.Buffer` object. [int]
    :arg viewport: Specifies the current viewport.
 
 
@@ -1807,13 +1807,13 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type objx, objy, objz: double
    :arg objx, objy, objz: Specify the object coordinates.
-   :type modelMatrix: :class:`Buffer` object. [double]
+   :type modelMatrix: :class:`bgl.Buffer` object. [double]
    :arg modelMatrix: Specifies the current modelview matrix (as from a glGetDoublev call).
-   :type projMatrix: :class:`Buffer` object. [double]
+   :type projMatrix: :class:`bgl.Buffer` object. [double]
    :arg projMatrix: Specifies the current projection matrix (as from a glGetDoublev call).
-   :type viewport: :class:`Buffer` object. [int]
+   :type viewport: :class:`bgl.Buffer` object. [int]
    :arg viewport: Specifies the current viewport (as from a glGetIntegerv call).
-   :type winx, winy, winz: :class:`Buffer` object. [double]
+   :type winx, winy, winz: :class:`bgl.Buffer` object. [double]
    :arg winx, winy, winz: Return the computed window coordinates.
 
 
@@ -1825,13 +1825,13 @@ OpenGL}" and the online NeHe tutorials are two of the best resources.
 
    :type winx, winy, winz: double
    :arg winx, winy, winz: Specify the window coordinates to be mapped.
-   :type modelMatrix: :class:`Buffer` object. [double]
+   :type modelMatrix: :class:`bgl.Buffer` object. [double]
    :arg modelMatrix: Specifies the current modelview matrix (as from a glGetDoublev call).
-   :type projMatrix: :class:`Buffer` object. [double]
+   :type projMatrix: :class:`bgl.Buffer` object. [double]
    :arg projMatrix: Specifies the current projection matrix (as from a glGetDoublev call).
-   :type viewport: :class:`Buffer` object. [int]
+   :type viewport: :class:`bgl.Buffer` object. [int]
    :arg viewport: Specifies the current viewport (as from a glGetIntegerv call).
-   :type objx, objy, objz: :class:`Buffer` object. [double]
+   :type objx, objy, objz: :class:`bgl.Buffer` object. [double]
    :arg objx, objy, objz: Return the computed object coordinates.
 
 
index e77e9a76d7f05cdd6f59adbe477bb5e0252e3a4f..751e5e1ec6191d47730620dcd5f1c0b2d9e6f2ca 100644 (file)
@@ -156,7 +156,7 @@ Note that these properties can only be assigned  basic Python types.
 
 * array of ints/floats
 
-* dictionary (only string keys types on this list)
+* dictionary (only string keys are supported, values must be basic types too)
 
 These properties are valid outside of Python. They can be animated by curves or used in driver paths.
 
index bd5faf000c862553aa5e73477fef7e1f147ad2fb..f4e68a4516c4c8e744733ec7ecc017761bce28ae 100644 (file)
-###############
+***************
 Tips and Tricks
-###############
+***************
 
 Some of these are just python features that scripters may not have thaught to use with blender.
 
 
-****************
 Use The Terminal
-****************
+================
+
+When writing python scripts, its useful to have a terminal open, this is not the built-in python console but a terminal application which is used to start blender.
+
+There are 3 main uses for the terminal, these are:
+
+* You can see the output of `print()` as you're script runs, which is useful to view debug info.
+
+* The error tracebacks are printed in full to the terminal which wont always generate an error popup in blenders user interface (depending on how the script is executed).
+
+* If the script runs for too long or you accidentally enter an infinate loop, Ctrl+C in the terminal (Ctrl+Break on Windows) will quit the script early.
+
+.. note::
+   For Linux and OSX users this means starting the terminal first, then running blender from within it. On Windows the terminal can be enabled from the help menu.
 
-For Linux and OSX users this means starting the terminal first, then running blender from within it. on Windows the terminal can be enabled from the help menu.
 
-********************
 Run External Scripts
-********************
+====================
+
+Blenders text editor is fine for edits and writing small tests but it is not a full featured editor so for larger projects you'll probably want to use an external editor.
+
+Editing a text file externally and having the same text open in blender does work but isn't that optimal so here are 2 ways you can easily use an external file from blender.
+
+
+Executing External Scripts
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This is the equivilent to running the script directly, referencing a scripts path from a 2 line textblock.
+
+.. code-block::
+
+   filename = "/full/path/to/myscript.py"
+   exec(compile(open(filename).read(), filename, 'exec'))
+
+
+You might also want to reference the file relative to the blend file.
+
+.. code-block::
+
+   filename = "/full/path/to/script.py"
+   exec(compile(open(filename).read(), filename, 'exec'))
+
+
+You might want to reference a script thats at the same location as the blend file.
+
+.. code-block::
+
+   import bpy
+   import os
+
+   filename = os.path.join(os.path.basename(bpy.data.filepath), "myscript.py")
+   exec(compile(open(filename).read(), filename, 'exec'))
+
+
+Executing Modules
+^^^^^^^^^^^^^^^^^
+
+This example shows loading a script in as a module and executing a module function.
+
+.. code-block::
+
+   import myscript
+   import imp
+
+   imp.reload(myscript)
+   myscript.main()
+
+
+Notice that the script is reloaded every time, this forces an update, normally the module stays cached in `sys.modules`.
+
+The main difference between this and executing the script directly is it has to call a function in the module, in this case `main()` but it can be any function, an advantage with this is you can pass argumnents to the function from this small script which is often useful for testing differnt settings quickly.
+
+The other issue with this is the script has to be in pythons module search path.
+While this is not best practice - for testing you can extend the search path, this example adds the current blend files directory to the search path, then loads the script as a module.
+
+.. code-block::
+
+   import sys
+   import os
+   impory bpy
+
+   blend_dir = os.path.basename(bpy.data.filepath)
+   if blend_dir not in sys.path:
+      sys.path.append(blend_dir)
+
+   import myscript
+   import imp
+   imp.reload(myscript)
+   myscript.main()
 
 
-******************
 Don't Use Blender!
-******************
+==================
 
 
-******************
 Use External Tools
-******************
+==================
 
 
-**************
 Bundled Python
-**************
+==============
 
 Blender from blender.org includes a compleate python installation on all platforms, this has the disadvantage that any extensions you have installed in you're systems python wont be found by blender.
 
@@ -38,20 +116,18 @@ There are 2 ways around this:
 
 * copy the extensions into blender's python subdirectry so blender can access them, you could also copy the entire python installation into blenders subdirectory, replacing the one blender comes with. This works as long as the python versions match and the paths are created in the same location relative locations. Doing this has the advantage that you can redistribute this bundle to others with blender and/or the game player, including any extensions you rely on.
 
-********
+
 Advanced
-********
+========
 
 
-===================
 Blender as a module
-===================
+-------------------
 
 
-============================
 Python Safety (Build Option)
-============================
+----------------------------
+
 
-=================
 CTypes in Blender
-=================
+-----------------
index e378dd19e733d7082397e63a8040c97c21b6459d..661d41af4ef77a8aecbb71798a06e933a442129c 100644 (file)
@@ -578,6 +578,7 @@ def pycontext2sphinx(BASEPATH):
         "sequences": ("Sequence", True),
         "smoke": ("SmokeModifier", False),
         "soft_body": ("SoftBodyModifier", False),
+        "speaker": ("Speaker", False),
         "texture": ("Texture", False),
         "texture_slot": ("MaterialTextureSlot", False),
         "vertex_paint_object": ("Object", False),
index 48230db23a339f126839afe4ed0e6612806b473f..4debb32b5c401499a5592f551d7b8a35d4c61f1e 100644 (file)
@@ -98,7 +98,8 @@ typedef unsigned long uintptr_t;
 #include <inttypes.h>
 
 #elif defined(FREE_WINDOWS)
-
+/* define htoln here, there must be a syntax error in winsock2.h in MinGW */
+unsigned long __attribute__((__stdcall__)) htonl(unsigned long);
 #include <stdint.h>
 
 #else
@@ -109,12 +110,14 @@ typedef unsigned long uintptr_t;
 #endif /* ifdef platform for types */
 
 #ifdef _WIN32
+#ifndef FREE_WINDOWS
 #ifndef htonl
 #define htonl(x) correctByteOrder(x)
 #endif
 #ifndef ntohl
 #define ntohl(x) correctByteOrder(x)
 #endif
+#endif
 #elif defined (__FreeBSD__) || defined (__OpenBSD__) 
 #include <sys/param.h>
 #elif defined (__APPLE__)
index b71593add961fbdb2ca5157b6cf89e19772c5d06..aa26cb43eed71fe4835013bb3c9c10eaa81e5162 100644 (file)
@@ -54,6 +54,9 @@ def draw_gpencil_tools(context, layout):
     row = col.row()
     row.operator("gpencil.draw", text="Draw").mode = 'DRAW'
     row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
+
+    row = col.row()
+    row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY'
     row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
 
     row = col.row()
index 17876c6ec9d3faea372b1ce8a89063bcad1f7601..0e48673f1b1c688399fc870858c1d95acedbe7aa 100644 (file)
@@ -111,7 +111,7 @@ typedef struct Global {
 #define G_SCRIPT_OVERRIDE_PREF (1 << 14) /* when this flag is set ignore the userprefs */
 
 /* #define G_NOFROZEN  (1 << 17) also removed */
-#define G_GREASEPENCIL         (1 << 17)
+/* #define G_GREASEPENCIL      (1 << 17)   also removed */
 
 /* #define G_AUTOMATKEYS       (1 << 30)   also removed */
 
index 7207fb7d0fbca3b94583ab256cbefbecc823f9ab..1de3c295f4da30af5b3640a50f245890960a40a5 100644 (file)
@@ -466,8 +466,8 @@ struct ShadeResult;
 
 /* API */
 
-struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
-void                   ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
+struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
+void                   ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
 void                   ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
 void                   ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode);
 void                   nodeShaderSynchronizeID(struct bNode *node, int copyto);
@@ -594,8 +594,8 @@ void                        ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
 
 /* API */
 struct CompBuf;
-struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree);
-void ntreeCompositEndExecTree(struct bNodeTreeExec *exec);
+struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
+void ntreeCompositEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
 void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int do_previews);
 void ntreeCompositTagRender(struct Scene *sce);
 int ntreeCompositTagAnimated(struct bNodeTree *ntree);
@@ -642,8 +642,8 @@ void ntreeTexSetPreviewFlag(int);
 void ntreeTexCheckCyclics(struct bNodeTree *ntree);
 char* ntreeTexOutputMenu(struct bNodeTree *ntree);
 
-struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree);
-void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
+struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
+void ntreeTexEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
 int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float *coord, float *dxt, float *dyt, int osatex, short thread, struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);
 
 
index 5f33059e117d7400cd2680891a8295c47884f57a..2d4354bdd9fc9141b56fcc770868a84d2f899a61 100644 (file)
@@ -324,17 +324,14 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
        MEM_freeN(bfd);
 }
 
-static int handle_subversion_warning(Main *main)
+static int handle_subversion_warning(Main *main, ReportList *reports)
 {
        if(main->minversionfile > BLENDER_VERSION ||
           (main->minversionfile == BLENDER_VERSION && 
                 main->minsubversionfile > BLENDER_SUBVERSION)) {
-               
-               char str[128];
-               
-               BLI_snprintf(str, sizeof(str), "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile);
-// XXX         error(str);
+               BKE_reportf(reports, RPT_ERROR, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile);
        }
+
        return 1;
 }
 
@@ -392,7 +389,7 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
        if (bfd) {
                if(bfd->user) retval= BKE_READ_FILE_OK_USERPREFS;
                
-               if(0==handle_subversion_warning(bfd->main)) {
+               if(0==handle_subversion_warning(bfd->main, reports)) {
                        free_main(bfd->main);
                        MEM_freeN(bfd);
                        bfd= NULL;
index 36631d5af90c9c78d58a14db215e93d5eb86175c..aab8e1abbeaa86908a6de0bdefc093f213a66cf0 100644 (file)
@@ -926,7 +926,7 @@ void init_render_material(Material *mat, int r_mode, float *amb)
                init_render_nodetree(mat->nodetree, mat, r_mode, amb);
                
                if (!mat->nodetree->execdata)
-                       mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree);
+                       mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1);
        }
 }
 
@@ -960,7 +960,7 @@ void end_render_material(Material *mat)
 {
        if(mat && mat->nodetree && mat->use_nodes) {
                if (mat->nodetree->execdata)
-                       ntreeShaderEndExecTree(mat->nodetree->execdata);
+                       ntreeShaderEndExecTree(mat->nodetree->execdata, 1);
        }
 }
 
index 481893b86a8e5b69de669aa4746591c5335c65f6..292f38b9472bd3d8e14f8796671c3c30cb2561fd 100644 (file)
@@ -897,13 +897,13 @@ void ntreeFreeTree(bNodeTree *ntree)
        if (ntree->execdata) {
                switch (ntree->type) {
                case NTREE_COMPOSIT:
-                       ntreeCompositEndExecTree(ntree->execdata);
+                       ntreeCompositEndExecTree(ntree->execdata, 1);
                        break;
                case NTREE_SHADER:
-                       ntreeShaderEndExecTree(ntree->execdata);
+                       ntreeShaderEndExecTree(ntree->execdata, 1);
                        break;
                case NTREE_TEXTURE:
-                       ntreeTexEndExecTree(ntree->execdata);
+                       ntreeTexEndExecTree(ntree->execdata, 1);
                        break;
                }
        }
@@ -1524,21 +1524,25 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node)
 {
        bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
        
-       if (ntreetype->update_node)
+       /* extra null pointer checks here because this is called when unlinking
+          unknown nodes on file load, so typeinfo pointers may not be set */
+       if (ntreetype && ntreetype->update_node)
                ntreetype->update_node(ntree, node);
-       else if (node->typeinfo->updatefunc)
+       else if (node->typeinfo && node->typeinfo->updatefunc)
                node->typeinfo->updatefunc(ntree, node);
 }
 
 int NodeTagIDChanged(bNodeTree *ntree, ID *id)
 {
-       bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
+       bNodeTreeType *ntreetype;
        bNode *node;
        int change = FALSE;
 
        if(ELEM(NULL, id, ntree))
                return change;
        
+       ntreetype = ntreeGetType(ntree->type);
+       
        if (ntreetype->update_node) {
                for(node= ntree->nodes.first; node; node= node->next) {
                        if(node->id==id) {
index 6119a8553667e71752964081eefd9142c9c70b7b..38165182d83beb13d09870f975373a2077d96483 100644 (file)
@@ -767,7 +767,7 @@ Tex *copy_texture(Tex *tex)
 
        if(tex->nodetree) {
                if (tex->nodetree->execdata) {
-                       ntreeTexEndExecTree(tex->nodetree->execdata);
+                       ntreeTexEndExecTree(tex->nodetree->execdata, 1);
                }
                texn->nodetree= ntreeCopyTree(tex->nodetree); 
        }
index c4ed44f0cdb01b260df4baf24a71b98f7692ff70..ae5fa40f3b9aec7e9dab22c8a5c1c0d2b7e6e9f2 100644 (file)
@@ -129,7 +129,7 @@ size_t BLI_strescape(char *dst, const char *src, const size_t maxlen)
        while(len < maxlen) {
                switch(*src) {
                        case '\0':
-                               break;
+                               goto escape_finish;
                        case '\\':
                        case '"':
 
@@ -154,6 +154,8 @@ size_t BLI_strescape(char *dst, const char *src, const size_t maxlen)
                len++;
        }
 
+escape_finish:
+
        *dst= '\0';
 
        return len;
index 2114fc34bf16ff8fe9ecb5ec2784afeb15ba41a2..4b3902dca43100d3c5cfac28e2daadd6353482b9 100644 (file)
@@ -93,7 +93,8 @@ typedef unsigned long uintptr_t;
 #include <inttypes.h>
 
 #elif defined(FREE_WINDOWS)
-
+/* define htoln here, there must be a syntax error in winsock2.h in MinGW */
+unsigned long __attribute__((__stdcall__)) htonl(unsigned long);
 #include <stdint.h>
 
 #else
@@ -105,8 +106,14 @@ typedef unsigned long uintptr_t;
 
 
 #ifdef _WIN32
+#ifndef FREE_WINDOWS
+#ifndef htonl
 #define htonl(x) correctByteOrder(x)
+#endif
+#ifndef ntohl
 #define ntohl(x) correctByteOrder(x)
+#endif
+#endif
 #elif defined (__FreeBSD__) || defined (__OpenBSD__) 
 #include <sys/param.h>
 #elif defined (__APPLE__)
index 5518e133daf3d9115964f331e0ff10b50f55e5a0..eb5d6a6fbcb0a5943555913d6e58aabfd0979c13 100644 (file)
@@ -2217,8 +2217,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                if(node->type == NODE_DYNAMIC) {
                        node->custom1= 0;
                        node->custom1= BSET(node->custom1, NODE_DYNAMIC_LOADED);
-                       node->typeinfo= NULL;
                }
+
+               node->typeinfo= NULL;
                
                link_list(fd, &node->inputs);
                link_list(fd, &node->outputs);
@@ -7022,6 +7023,15 @@ static void do_versions_nodetree_default_value(bNodeTree *ntree)
                do_versions_socket_default_value(sock);
 }
 
+static void do_versions_nodetree_dynamic_sockets(bNodeTree *ntree)
+{
+       bNodeSocket *sock;
+       for (sock=ntree->inputs.first; sock; sock=sock->next)
+               sock->flag |= SOCK_DYNAMIC;
+       for (sock=ntree->outputs.first; sock; sock=sock->next)
+               sock->flag |= SOCK_DYNAMIC;
+}
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -11979,6 +11989,27 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                tex->nodetree->update |= NTREE_UPDATE;
                        }
                }
+
+               /* add SOCK_DYNAMIC flag to existing group sockets */
+               {
+                       bNodeTree *ntree;
+                       /* only need to do this for trees in main, local trees are not used as groups */
+                       for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
+                               do_versions_nodetree_dynamic_sockets(ntree);
+                               ntree->update |= NTREE_UPDATE;
+                       }
+               }
+
+               {
+                       /* Initialize group tree nodetypes.
+                        * These are used to distinguish tree types and
+                        * associate them with specific node types for polling.
+                        */
+                       bNodeTree *ntree;
+                       /* all node trees in main->nodetree are considered groups */
+                       for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
+                               ntree->nodetype = NODE_GROUP;
+               }
        }
 
        /* put compatibility code here until next subversion bump */
index c3f51dc6ce48466eff891c66002541d5b8bc277a..3b736e8aeae0e5c59c4896ed1b32bcb33bbb341a 100644 (file)
@@ -135,6 +135,7 @@ Any case: direct data is ALWAYS after the lib block
 #include "BLI_blenlib.h"
 #include "BLI_linklist.h"
 #include "BLI_bpath.h"
+#include "BLI_math.h"
 #include "BLI_utildefines.h"
 
 #include "BKE_action.h"
@@ -645,6 +646,38 @@ static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
 static void write_node_socket(WriteData *wd, bNodeSocket *sock)
 {
        bNodeSocketType *stype= ntreeGetSocketType(sock->type);
+
+       /* forward compatibility code, so older blenders still open */
+       sock->stack_type = 1;
+
+       if(sock->default_value) {
+               bNodeSocketValueFloat *valfloat;
+               bNodeSocketValueVector *valvector;
+               bNodeSocketValueRGBA *valrgba;
+               
+               switch (sock->type) {
+               case SOCK_FLOAT:
+                       valfloat = sock->default_value;
+                       sock->ns.vec[0] = valfloat->value;
+                       sock->ns.min = valfloat->min;
+                       sock->ns.max = valfloat->max;
+                       break;
+               case SOCK_VECTOR:
+                       valvector = sock->default_value;
+                       copy_v3_v3(sock->ns.vec, valvector->value);
+                       sock->ns.min = valvector->min;
+                       sock->ns.max = valvector->max;
+                       break;
+               case SOCK_RGBA:
+                       valrgba = sock->default_value;
+                       copy_v4_v4(sock->ns.vec, valrgba->value);
+                       sock->ns.min = 0.0f;
+                       sock->ns.max = 1.0f;
+                       break;
+               }
+       }
+
+       /* actual socket writing */
        writestruct(wd, DATA, "bNodeSocket", 1, sock);
        if (sock->default_value)
                writestruct(wd, DATA, stype->value_structname, 1, sock->default_value);
index d73373aa901b2817b332da90ae59e96049d49601..cc7229383e36cc495adb0401f87110d130d793c1 100644 (file)
@@ -61,6 +61,7 @@ set(SRC
        MaterialExporter.cpp
        MeshImporter.cpp
        SkinInfo.cpp
+       SceneExporter.cpp
        TransformReader.cpp
        TransformWriter.cpp
        collada.cpp
@@ -85,6 +86,7 @@ set(SRC
        MaterialExporter.h
        MeshImporter.h
        SkinInfo.h
+       SceneExporter.h
        TransformReader.h
        TransformWriter.h
        collada.h
index 6e780889d16130d4dc98df4fee00e6d639d26bab..85f37d29f22ef5de1d9d3c3a25ea2d98ff9d4ac6 100644 (file)
@@ -34,6 +34,7 @@ extern "C"
 {
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
+#include "DNA_group_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_image_types.h"
@@ -104,6 +105,7 @@ extern char build_rev[];
 #include "COLLADASWConstants.h"
 #include "COLLADASWLibraryControllers.h"
 #include "COLLADASWInstanceController.h"
+#include "COLLADASWInstanceNode.h"
 #include "COLLADASWBaseInputElement.h"
 
 #include "collada_internal.h"
@@ -113,6 +115,7 @@ extern char build_rev[];
 #include "InstanceWriter.h"
 #include "TransformWriter.h"
 
+#include "SceneExporter.h"
 #include "ArmatureExporter.h"
 #include "AnimationExporter.h"
 #include "CameraExporter.h"
@@ -142,165 +145,6 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
        return data->layers[layer_index].name;
 }
 
-
-/*
-  Utilities to avoid code duplication.
-  Definition can take some time to understand, but they should be useful.
-*/
-
-
-template<class Functor>
-void forEachObjectInScene(Scene *sce, Functor &f)
-{
-       Base *base= (Base*) sce->base.first;
-       while(base) {
-               Object *ob = base->object;
-                       
-               f(ob);
-
-               base= base->next;
-       }
-}
-
-
-
-class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, protected InstanceWriter
-{
-       ArmatureExporter *arm_exporter;
-public:
-       SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm) : COLLADASW::LibraryVisualScenes(sw),
-                                                                                                                                               arm_exporter(arm) {}
-       
-       void exportScene(Scene *sce, bool export_selected) {
-               // <library_visual_scenes> <visual_scene>
-               std::string id_naming = id_name(sce);
-               openVisualScene(translate_id(id_naming), id_naming);
-
-               // write <node>s
-               //forEachMeshObjectInScene(sce, *this);
-               //forEachCameraObjectInScene(sce, *this);
-               //forEachLampObjectInScene(sce, *this);
-               exportHierarchy(sce, export_selected);
-
-               // </visual_scene> </library_visual_scenes>
-               closeVisualScene();
-
-               closeLibrary();
-       }
-
-       void exportHierarchy(Scene *sce, bool export_selected)
-       {
-               Base *base= (Base*) sce->base.first;
-               while(base) {
-                       Object *ob = base->object;
-
-                       if (!ob->parent) {
-                               if(sce->lay & ob->lay) {
-                               switch(ob->type) {
-                               case OB_MESH:
-                               case OB_CAMERA:
-                               case OB_LAMP:
-                               case OB_ARMATURE:
-                               case OB_EMPTY:
-                                       if (export_selected && !(ob->flag & SELECT)) {
-                                               break;
-                                       }
-                                       // write nodes....
-                                       writeNodes(ob, sce);
-                                       break;
-                               }
-                               }
-                       }
-
-                       base= base->next;
-               }
-       }
-
-
-       // called for each object
-       //void operator()(Object *ob) {
-       void writeNodes(Object *ob, Scene *sce)
-       {
-               COLLADASW::Node node(mSW);
-               node.setNodeId(translate_id(id_name(ob)));
-               node.setType(COLLADASW::Node::NODE);
-
-               node.start();
-
-               bool is_skinned_mesh = arm_exporter->is_skinned_mesh(ob);
-
-               if (ob->type == OB_MESH && is_skinned_mesh)
-                       // for skinned mesh we write obmat in <bind_shape_matrix>
-                       TransformWriter::add_node_transform_identity(node);
-               else
-                       TransformWriter::add_node_transform_ob(node, ob);
-               
-               // <instance_geometry>
-               if (ob->type == OB_MESH) {
-                       if (is_skinned_mesh) {
-                               arm_exporter->add_instance_controller(ob);
-                       }
-                       else {
-                               COLLADASW::InstanceGeometry instGeom(mSW);
-                               instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob)));
-
-                               InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob);
-                       
-                               instGeom.add();
-                       }
-               }
-
-               // <instance_controller>
-               else if (ob->type == OB_ARMATURE) {
-                       arm_exporter->add_armature_bones(ob, sce);
-
-                       // XXX this looks unstable...
-                       node.end();
-               }
-               
-               // <instance_camera>
-               else if (ob->type == OB_CAMERA) {
-                       COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob)));
-                       instCam.add();
-               }
-               
-               // <instance_light>
-               else if (ob->type == OB_LAMP) {
-                       COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob)));
-                       instLa.add();
-               }
-
-               // empty object
-               else if (ob->type == OB_EMPTY) {
-               }
-
-               // write nodes for child objects
-               Base *b = (Base*) sce->base.first;
-               while(b) {
-                       // cob - child object
-                       Object *cob = b->object;
-
-                       if (cob->parent == ob) {
-                               switch(cob->type) {
-                               case OB_MESH:
-                               case OB_CAMERA:
-                               case OB_LAMP:
-                               case OB_EMPTY:
-                               case OB_ARMATURE:
-                                       // write node...
-                                       writeNodes(cob, sce);
-                                       break;
-                               }
-                       }
-
-                       b = b->next;
-               }
-
-               if (ob->type != OB_ARMATURE)
-                       node.end();
-       }
-};
-
 // TODO: it would be better to instantiate animations rather than create a new one per object
 // COLLADA allows this through multiple <channel>s in <animation>.
 // For this to work, we need to know objects that use a certain action.
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
new file mode 100644 (file)
index 0000000..96f20ac
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/collada/SceneExporter.cpp
+ *  \ingroup collada
+ */
+
+#include "SceneExporter.h"
+
+SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm)
+       : COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm)
+{}
+       
+void SceneExporter::exportScene(Scene *sce, bool export_selected)
+{
+       // <library_visual_scenes> <visual_scene>
+       std::string id_naming = id_name(sce);
+       openVisualScene(translate_id(id_naming), id_naming);
+       exportHierarchy(sce, export_selected);
+       closeVisualScene();
+       closeLibrary();
+}
+
+void SceneExporter::exportHierarchy(Scene *sce, bool export_selected)
+{
+       Base *base= (Base*) sce->base.first;
+       while(base) {
+               Object *ob = base->object;
+
+               if (!ob->parent) {
+                       if(sce->lay & ob->lay) {
+                               switch(ob->type) {
+                                       case OB_MESH:
+                                       case OB_CAMERA:
+                                       case OB_LAMP:
+                                       case OB_ARMATURE:
+                                       case OB_EMPTY:
+                                               if (export_selected && !(ob->flag & SELECT)) {
+                                                       break;
+                                               }
+                                               // write nodes....
+                                               writeNodes(ob, sce);
+                                               break;
+                               }
+                       }
+               }
+
+               base= base->next;
+       }
+}
+
+void SceneExporter::writeNodes(Object *ob, Scene *sce)
+{
+       COLLADASW::Node node(mSW);
+       node.setNodeId(translate_id(id_name(ob)));
+       node.setType(COLLADASW::Node::NODE);
+
+       node.start();
+
+       bool is_skinned_mesh = arm_exporter->is_skinned_mesh(ob);
+
+       if (ob->type == OB_MESH && is_skinned_mesh)
+               // for skinned mesh we write obmat in <bind_shape_matrix>
+               TransformWriter::add_node_transform_identity(node);
+       else
+               TransformWriter::add_node_transform_ob(node, ob);
+
+       // <instance_geometry>
+       if (ob->type == OB_MESH) {
+               if (is_skinned_mesh) {
+                       arm_exporter->add_instance_controller(ob);
+               }
+               else {
+                       COLLADASW::InstanceGeometry instGeom(mSW);
+                       instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob)));
+
+                       InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob);
+
+                       instGeom.add();
+               }
+       }
+
+       // <instance_controller>
+       else if (ob->type == OB_ARMATURE) {
+               arm_exporter->add_armature_bones(ob, sce);
+
+               // XXX this looks unstable...
+               node.end();
+       }
+
+       // <instance_camera>
+       else if (ob->type == OB_CAMERA) {
+               COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob)));
+               instCam.add();
+       }
+
+       // <instance_light>
+       else if (ob->type == OB_LAMP) {
+               COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob)));
+               instLa.add();
+       }
+
+       // empty object
+       else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLIGROUP
+               if((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) {
+                       GroupObject *go = NULL;
+                       Group *gr = ob->dup_group;
+                       printf("group detected %u\n", gr);
+                       for(go = (GroupObject*)(gr->gobject.first); go; go=go->next) {
+                               printf("\t%s\n", go->ob->id.name);
+                       }
+               }
+       }
+
+       // write nodes for child objects
+       Base *b = (Base*) sce->base.first;
+       while(b) {
+               // cob - child object
+               Object *cob = b->object;
+
+               if (cob->parent == ob) {
+                       switch(cob->type) {
+                               case OB_MESH:
+                               case OB_CAMERA:
+                               case OB_LAMP:
+                               case OB_EMPTY:
+                               case OB_ARMATURE:
+                                       // write node...
+                                       writeNodes(cob, sce);
+                                       break;
+                       }
+               }
+
+               b = b->next;
+       }
+
+       if (ob->type != OB_ARMATURE)
+               node.end();
+}
+
diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h
new file mode 100644 (file)
index 0000000..30fef92
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file SceneExporter.h
+ *  \ingroup collada
+ */
+
+#ifndef __SCENEEXPORTER_H__
+#define __SCENEEXPORTER_H__
+
+extern "C" {
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_group_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_fcurve.h"
+#include "BKE_animsys.h"
+#include "BLI_path_util.h"
+#include "BLI_fileops.h"
+#include "ED_keyframing.h"
+}
+
+#include "COLLADASWAsset.h"
+#include "COLLADASWLibraryVisualScenes.h"
+#include "COLLADASWNode.h"
+#include "COLLADASWSource.h"
+#include "COLLADASWInstanceGeometry.h"
+#include "COLLADASWInputList.h"
+#include "COLLADASWPrimitves.h"
+#include "COLLADASWVertices.h"
+#include "COLLADASWLibraryAnimations.h"
+#include "COLLADASWLibraryImages.h"
+#include "COLLADASWLibraryEffects.h"
+#include "COLLADASWImage.h"
+#include "COLLADASWEffectProfile.h"
+#include "COLLADASWColorOrTexture.h"
+#include "COLLADASWParamTemplate.h"
+#include "COLLADASWParamBase.h"
+#include "COLLADASWSurfaceInitOption.h"
+#include "COLLADASWSampler.h"
+#include "COLLADASWScene.h"
+#include "COLLADASWTechnique.h"
+#include "COLLADASWTexture.h"
+#include "COLLADASWLibraryMaterials.h"
+#include "COLLADASWBindMaterial.h"
+#include "COLLADASWInstanceCamera.h"
+#include "COLLADASWInstanceLight.h"
+#include "COLLADASWConstants.h"
+#include "COLLADASWLibraryControllers.h"
+#include "COLLADASWInstanceController.h"
+#include "COLLADASWInstanceNode.h"
+#include "COLLADASWBaseInputElement.h"
+
+#include "ArmatureExporter.h"
+
+class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, protected InstanceWriter
+{
+       ArmatureExporter *arm_exporter;
+public:
+       SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm);
+       void exportScene(Scene *sce, bool export_selected);
+
+private:
+       void exportHierarchy(Scene *sce, bool export_selected);
+       void writeNodes(Object *ob, Scene *sce);
+};
+
+#endif
index 7a2f196fd6d314df5469d11e97a71264de057296..b312f39793936dfbd0ca93a8595ecf614d41001e 100644 (file)
@@ -42,6 +42,7 @@ set(SRC
        gpencil_edit.c
        gpencil_ops.c
        gpencil_paint.c
+       gpencil_undo.c
 
        gpencil_intern.h
 )
index 440d5ee7c4dd6c1e96bf88e3d733141e1ad307e8..cfa9585868e0179778df9e802cc77656ccd27897 100644 (file)
@@ -644,7 +644,7 @@ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy
                /* Check if may need to draw the active stroke cache, only if this layer is the active layer
                 * that is being edited. (Stroke buffer is currently stored in gp-data)
                 */
-               if ((G.f & G_GREASEPENCIL) && (gpl->flag & GP_LAYER_ACTIVE) &&
+               if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
                        (gpf->flag & GP_FRAME_PAINT)) 
                {
                        /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */
index 9dc764b7aac693bbc3b9b6ddfb405ed40391d494..1cd8b1f05db701ae2507f1acdd684fb22cd08023 100644 (file)
@@ -511,8 +511,8 @@ static void gp_stroke_to_bezier (bContext *C, bGPDlayer *gpl, bGPDstroke *gps, C
                copy_v3_v3(p3d_prev, p3d_cur);
                copy_v3_v3(p3d_cur, p3d_next);
 
-               if (i + 1 < tot) {
-                       gp_strokepoint_convertcoords(C, gps, pt+1, p3d_next, subrect);
+               if (i + 2 < tot) {
+                       gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
                }
        }
 
index c31de8d30a75353533f8146fa638137778f3b6f1..8000af54f53297ad5552f62c533415bdb268c54a 100644 (file)
@@ -37,6 +37,7 @@
 /* ***************************************************** */
 /* Operator Defines */
 
+struct bGPdata;
 struct wmOperatorType;
 
 /* drawing ---------- */
@@ -48,6 +49,7 @@ typedef enum eGPencil_PaintModes {
        GP_PAINTMODE_DRAW = 0,
        GP_PAINTMODE_ERASER,
        GP_PAINTMODE_DRAW_STRAIGHT,
+       GP_PAINTMODE_DRAW_POLY
 } eGPencil_PaintModes;
 
 /* buttons editing --- */
@@ -61,6 +63,11 @@ void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot);
 
 void GPENCIL_OT_convert(struct wmOperatorType *ot);
 
+/* undo stack ---------- */
+
+void gpencil_undo_init(struct bGPdata *gpd);
+void gpencil_undo_push(struct bGPdata *gpd);
+void gpencil_undo_finish(void);
 
 /******************************************************* */
 /* FILTERED ACTION DATA - TYPES  ---> XXX DEPRECEATED OLD ANIM SYSTEM CODE! */
index e1e4c8d545746c3800e924268edc4e8e4c5e9dd1..150e0ba90e4f4842b541c02155c84ca85b828be5 100644 (file)
@@ -59,6 +59,9 @@ void ED_keymap_gpencil(wmKeyConfig *keyconf)
                /* draw - straight lines */
        kmi=WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, DKEY);
                RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT);
+               /* draw - poly lines */
+       kmi=WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, KM_CTRL, DKEY);
+               RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY);
                /* erase */
        kmi=WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, 0, DKEY);
                RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
index 04565eab1551629521d8223203e08cb50134acd6..a23f2064a9e8906be2bfa2ee140e377221e5f895 100644 (file)
@@ -124,6 +124,7 @@ enum {
 /* Runtime flags */
 enum {
        GP_PAINTFLAG_FIRSTRUN           = (1<<0),       /* operator just started */
+       GP_PAINTFLAG_STROKEADDED        = (1<<1)        /* stroke was already added during draw session */
 };
 
 /* ------ */
@@ -152,7 +153,7 @@ static int gpencil_draw_poll (bContext *C)
                /* check if current context can support GPencil data */
                if (gpencil_data_get_pointers(C, NULL) != NULL) {
                        /* check if Grease Pencil isn't already running */
-                       if ((G.f & G_GREASEPENCIL) == 0)
+                       if (ED_gpencil_session_active() == 0)
                                return 1;
                        else
                                CTX_wm_operator_poll_msg_set(C, "Grease Pencil operator is already active");
@@ -375,6 +376,52 @@ static short gp_stroke_addpoint (tGPsdata *p, const int mval[2], float pressure)
                else
                        return GP_STROKEADD_NORMAL;
        }
+       else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
+               /* get pointer to destination point */
+               pt= (tGPspoint *)(gpd->sbuffer);
+
+               /* store settings */
+               pt->x= mval[0];
+               pt->y= mval[1];
+               pt->pressure= pressure;
+
+               /* if there's stroke fir this poly line session add (or replace last) point
+                  to stroke. This allows to draw lines more interactively (see new segment
+                  during mouse slide, i.e.) */
+               if (p->flags & GP_PAINTFLAG_STROKEADDED) {
+                       bGPDstroke *gps= p->gpf->strokes.last;
+                       bGPDspoint *pts;
+
+                       /* first time point is adding to temporary buffer -- need to allocate new point in stroke */
+                       if (gpd->sbuffer_size == 0) {
+                               gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint)*(gps->totpoints+1));
+                               gps->totpoints++;
+                       }
+
+                       pts = &gps->points[gps->totpoints-1];
+
+                       /* special case for poly lines: normally, depth is needed only when creating new stroke from buffer,
+                          but poly lines are converting to stroke instantly, so initialize depth buffer before converting coordinates */
+                       if (gpencil_project_check(p)) {
+                               View3D *v3d= p->sa->spacedata.first;
+
+                               view3d_region_operator_needs_opengl(p->win, p->ar);
+                               ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1:0);
+                       }
+
+                       /* convert screen-coordinates to appropriate coordinates (and store them) */
+                       gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
+
+                       /* copy pressure */
+                       pts->pressure= pt->pressure;
+               }
+
+               /* increment counters */
+               if (gpd->sbuffer_size == 0)
+                       gpd->sbuffer_size++;
+
+               return GP_STROKEADD_NORMAL;
+       }
        
        /* return invalid state for now... */
        return GP_STROKEADD_INVALID;
@@ -395,7 +442,7 @@ static void gp_stroke_smooth (tGPsdata *p)
        int i=0, cmx=gpd->sbuffer_size;
        
        /* only smooth if smoothing is enabled, and we're not doing a straight line */
-       if (!(U.gp_settings & GP_PAINT_DOSMOOTH) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT))
+       if (!(U.gp_settings & GP_PAINT_DOSMOOTH) || ELEM(p->paintmode, GP_PAINTMODE_DRAW_STRAIGHT, GP_PAINTMODE_DRAW_POLY))
                return;
        
        /* don't try if less than 2 points in buffer */
@@ -527,17 +574,28 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
                return;
        }
        
+       /* special case for poly line -- for already added stroke during session
+          coordinates are getting added to stroke immediatelly to allow more
+          interactive behavior */
+       if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
+               if (p->flags & GP_PAINTFLAG_STROKEADDED)
+                       return;
+       }
+
        /* allocate memory for a new stroke */
        gps= MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
        
-       /* allocate enough memory for a continuous array for storage points */
-       pt= gps->points= MEM_callocN(sizeof(bGPDspoint)*totelem, "gp_stroke_points");
-       
        /* copy appropriate settings for stroke */
        gps->totpoints= totelem;
        gps->thickness= p->gpl->thickness;
        gps->flag= gpd->sbuffer_sflag;
        
+       /* allocate enough memory for a continuous array for storage points */
+       gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points");
+
+       /* set pointer to first non-initialized point */
+       pt= gps->points + (gps->totpoints - totelem);
+
        /* copy points from the buffer to the stroke */
        if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
                /* straight lines only -> only endpoints */
@@ -565,6 +623,16 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
                        pt->pressure= ptc->pressure;
                }
        }
+       else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
+               /* first point */
+               ptc= gpd->sbuffer;
+
+               /* convert screen-coordinates to appropriate coordinates (and store them) */
+               gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+
+               /* copy pressure */
+               pt->pressure= ptc->pressure;
+       }
        else {
                float *depth_arr= NULL;
                
@@ -643,6 +711,8 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
                        MEM_freeN(depth_arr);
        }
        
+       p->flags |= GP_PAINTFLAG_STROKEADDED;
+
        /* add stroke to frame */
        BLI_addtail(&p->gpf->strokes, gps);
 }
@@ -891,10 +961,14 @@ static void gp_session_validatebuffer (tGPsdata *p)
        bGPdata *gpd= p->gpd;
        
        /* clear memory of buffer (or allocate it if starting a new session) */
-       if (gpd->sbuffer)
+       if (gpd->sbuffer) {
+               //printf("\t\tGP - reset sbuffer\n");
                memset(gpd->sbuffer, 0, sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX);
-       else
+       }
+       else {
+               //printf("\t\tGP - allocate sbuffer\n");
                gpd->sbuffer= MEM_callocN(sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
+       }
        
        /* reset indices */
        gpd->sbuffer_size = 0;
@@ -903,24 +977,21 @@ static void gp_session_validatebuffer (tGPsdata *p)
        gpd->sbuffer_sflag= 0;
 }
 
-/* init new painting session */
-static tGPsdata *gp_session_initpaint (bContext *C)
+/* (re)init new painting data */
+static int gp_session_initdata (bContext *C, tGPsdata *p)
 {
-       tGPsdata *p = NULL;
        bGPdata **gpd_ptr = NULL;
        ScrArea *curarea= CTX_wm_area(C);
        ARegion *ar= CTX_wm_region(C);
        
        /* make sure the active view (at the starting time) is a 3d-view */
        if (curarea == NULL) {
+               p->status= GP_STATUS_ERROR;
                if (G.f & G_DEBUG) 
                        printf("Error: No active view for painting \n");
-               return NULL;
+               return 0;
        }
        
-       /* create new context data */
-       p= MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
-       
        /* pass on current scene and window */
        p->scene= CTX_data_scene(C);
        p->win= CTX_wm_window(C);
@@ -942,7 +1013,7 @@ static tGPsdata *gp_session_initpaint (bContext *C)
                                p->status= GP_STATUS_ERROR;
                                if (G.f & G_DEBUG)
                                        printf("Error: 3D-View active region doesn't have any region data, so cannot be drawable \n");
-                               return p;
+                               return 0;
                        }
 
 #if 0 // XXX will this sort of antiquated stuff be restored?
@@ -951,7 +1022,7 @@ static tGPsdata *gp_session_initpaint (bContext *C)
                                p->status= GP_STATUS_ERROR;
                                if (G.f & G_DEBUG) 
                                        printf("Error: In active view, Grease Pencil not shown \n");
-                               return p;
+                               return 0;
                        }
 #endif
                }
@@ -972,7 +1043,7 @@ static tGPsdata *gp_session_initpaint (bContext *C)
                                p->status= GP_STATUS_ERROR;
                                if (G.f & G_DEBUG) 
                                        printf("Error: In active view, Grease Pencil not shown \n");
-                               return;
+                               return 0;
                        }
 #endif
                }
@@ -992,13 +1063,13 @@ static tGPsdata *gp_session_initpaint (bContext *C)
                                p->status= GP_STATUS_ERROR;
                                if (G.f & G_DEBUG) 
                                        printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil \n");
-                               return;
+                               return 0;
                        }
                        if ((sseq->flag & SEQ_DRAW_GPENCIL)==0) {
                                p->status= GP_STATUS_ERROR;
                                if (G.f & G_DEBUG) 
                                        printf("Error: In active view, Grease Pencil not shown \n");
-                               return;
+                               return 0;
                        }
                }
                        break;  
@@ -1019,7 +1090,7 @@ static tGPsdata *gp_session_initpaint (bContext *C)
                                p->status= GP_STATUS_ERROR;
                                if (G.f & G_DEBUG)
                                        printf("Error: In active view, Grease Pencil not shown \n");
-                               return p;
+                               return 0;
                        }
 #endif
                }
@@ -1031,7 +1102,7 @@ static tGPsdata *gp_session_initpaint (bContext *C)
                        p->status= GP_STATUS_ERROR;
                        if (G.f & G_DEBUG) 
                                printf("Error: Active view not appropriate for Grease Pencil drawing \n");
-                       return p;
+                       return 0;
                }
                        break;
        }
@@ -1042,7 +1113,7 @@ static tGPsdata *gp_session_initpaint (bContext *C)
                p->status= GP_STATUS_ERROR;
                if (G.f & G_DEBUG)
                        printf("Error: Current context doesn't allow for any Grease Pencil data \n");
-               return p;
+               return 0;
        }
        else {
                /* if no existing GPencil block exists, add one */
@@ -1051,8 +1122,11 @@ static tGPsdata *gp_session_initpaint (bContext *C)
                p->gpd= *gpd_ptr;
        }
        
-       /* set edit flags - so that buffer will get drawn */
-       G.f |= G_GREASEPENCIL;
+       if(ED_gpencil_session_active()==0) {
+               /* initialize undo stack,
+                  also, existing undo stack would make buffer drawn */
+               gpencil_undo_init(p->gpd);
+       }
        
        /* clear out buffer (stored in gp-data), in case something contaminated it */
        gp_session_validatebuffer(p);
@@ -1062,6 +1136,19 @@ static tGPsdata *gp_session_initpaint (bContext *C)
        p->im2d_settings.sizex= 1;
        p->im2d_settings.sizey= 1;
 #endif
+
+       return 1;
+}
+
+/* init new painting session */
+static tGPsdata *gp_session_initpaint (bContext *C)
+{
+       tGPsdata *p = NULL;
+
+       /* create new context data */
+       p= MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
+
+       gp_session_initdata(C, p);
        
        /* return context data for running paint operator */
        return p;
@@ -1078,6 +1165,7 @@ static void gp_session_cleanup (tGPsdata *p)
        
        /* free stroke buffer */
        if (gpd->sbuffer) {
+               //printf("\t\tGP - free sbuffer\n");
                MEM_freeN(gpd->sbuffer);
                gpd->sbuffer= NULL;
        }
@@ -1247,7 +1335,8 @@ static void gp_paint_strokeend (tGPsdata *p)
 static void gp_paint_cleanup (tGPsdata *p)
 {
        /* finish off a stroke */
-       gp_paint_strokeend(p);
+       if(p->gpd)
+               gp_paint_strokeend(p);
        
        /* "unlock" frame */
        if (p->gpf)
@@ -1260,8 +1349,8 @@ static void gpencil_draw_exit (bContext *C, wmOperator *op)
 {
        tGPsdata *p= op->customdata;
        
-       /* clear edit flags */
-       G.f &= ~G_GREASEPENCIL;
+       /* clear undo stack */
+       gpencil_undo_finish();
        
        /* restore cursor to indicate end of drawing */
        WM_cursor_restore(CTX_wm_window(C));
@@ -1592,6 +1681,7 @@ static int gpencil_draw_invoke (bContext *C, wmOperator *op, wmEvent *event)
                //printf("\tGP - hotkey invoked... waiting for click-drag\n");
        }
        
+       WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL, NULL);
        /* add a modal handler for this operator, so that we can then draw continuous strokes */
        WM_event_add_modal_handler(C, op);
        return OPERATOR_RUNNING_MODAL;
@@ -1609,16 +1699,57 @@ static int gpencil_area_exists(bContext *C, ScrArea *satest)
        return 0;
 }
 
+static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
+{
+       tGPsdata *p= op->customdata;
+
+       /* we must check that we're still within the area that we're set up to work from
+        * otherwise we could crash (see bug #20586)
+        */
+       if (CTX_wm_area(C) != p->sa) {
+               printf("\t\t\tGP - wrong area execution abort! \n");
+               p->status= GP_STATUS_ERROR;
+       }
+
+       //printf("\t\tGP - start stroke \n");
+
+       /* we may need to set up paint env again if we're resuming */
+       // XXX: watch it with the paintmode! in future, it'd be nice to allow changing paint-mode when in sketching-sessions
+       // XXX: with tablet events, we may event want to check for eraser here, for nicer tablet support
+
+       if (gp_session_initdata(C, p))
+               gp_paint_initstroke(p, p->paintmode);
+
+       p= op->customdata;
+
+       if(p->status != GP_STATUS_ERROR)
+               p->status= GP_STATUS_PAINTING;
+
+       return op->customdata;
+}
+
+static void gpencil_stroke_end(wmOperator *op)
+{
+       tGPsdata *p= op->customdata;
+
+       gp_paint_cleanup(p);
+
+       gpencil_undo_push(p->gpd);
+
+       gp_session_cleanup(p);
+
+       p->status= GP_STATUS_IDLING;
+
+       p->gpd= NULL;
+       p->gpl= NULL;
+       p->gpf= NULL;
+}
+
 /* events handling during interactive drawing part of operator */
 static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event)
 {
        tGPsdata *p= op->customdata;
-       //int estate = OPERATOR_PASS_THROUGH; /* default exit state - not handled, so let others have a share of the pie */
-       /* currently, grease pencil conflicts with such operators as undo and set object mode
-          which makes behavior of operator totally unpredictable and crash for some cases.
-          the only way to solve this proper is to ger rid of pointers to data which can
-          chage stored in operator custom data (sergey) */
-       int estate = OPERATOR_RUNNING_MODAL;
+       int estate = OPERATOR_PASS_THROUGH; /* default exit state - not handled, so let others have a share of the pie */
        
        // if (event->type == NDOF_MOTION)
        //      return OPERATOR_PASS_THROUGH;
@@ -1646,17 +1777,24 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event)
        if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE)) {
                /* if painting, end stroke */
                if (p->status == GP_STATUS_PAINTING) {
+                       int sketch= 0;
                        /* basically, this should be mouse-button up = end stroke 
                         * BUT what happens next depends on whether we 'painting sessions' is enabled
                         */
-                       if (GPENCIL_SKETCH_SESSIONS_ON(p->scene)) {
+                       sketch|= GPENCIL_SKETCH_SESSIONS_ON(p->scene);
+                       /* polyline drawig is also 'sketching' -- all knots should be added during one session */
+                       sketch|= p->paintmode == GP_PAINTMODE_DRAW_POLY;
+
+                       if (sketch) {
                                /* end stroke only, and then wait to resume painting soon */
                                //printf("\t\tGP - end stroke only\n");
-                               gp_paint_cleanup(p);
-                               p->status= GP_STATUS_IDLING;
+                               gpencil_stroke_end(op);
                                
                                /* we've just entered idling state, so this event was processed (but no others yet) */
                                estate = OPERATOR_RUNNING_MODAL;
+
+                               /* stroke could be smoothed, send notifier to refresh screen */
+                               WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL);
                        }
                        else {
                                //printf("\t\tGP - end of stroke + op\n");
@@ -1664,35 +1802,19 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event)
                                estate = OPERATOR_FINISHED;
                        }
                }
-               else {
+               else if (event->val == KM_PRESS) {
                        /* not painting, so start stroke (this should be mouse-button down) */
                        
-                       /* we must check that we're still within the area that we're set up to work from
-                        * otherwise we could crash (see bug #20586)
-                        */
-                       if (CTX_wm_area(C) != p->sa) {
-                               //printf("\t\t\tGP - wrong area execution abort! \n");
-                               p->status= GP_STATUS_ERROR;
+                       p= gpencil_stroke_begin(C, op);
+
+                       if (p->status == GP_STATUS_ERROR) {
                                estate = OPERATOR_CANCELLED;
                        }
-                       else {
-                               //printf("\t\tGP - start stroke \n");
-                               p->status= GP_STATUS_PAINTING;
-                               
-                               /* we may need to set up paint env again if we're resuming */
-                               // XXX: watch it with the paintmode! in future, it'd be nice to allow changing paint-mode when in sketching-sessions
-                               // XXX: with tablet events, we may event want to check for eraser here, for nicer tablet support
-                               gp_paint_initstroke(p, p->paintmode);
-                               
-                               if (p->status == GP_STATUS_ERROR) {
-                                       estate = OPERATOR_CANCELLED;
-                               }
-                       }
+               } else {
+                       p->status = GP_STATUS_IDLING;
                }
        }
        
-       
-       
        /* handle mode-specific events */
        if (p->status == GP_STATUS_PAINTING) {
                /* handle painting mouse-movements? */
@@ -1704,7 +1826,7 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event)
                        
                        /* finish painting operation if anything went wrong just now */
                        if (p->status == GP_STATUS_ERROR) {
-                               //printf("\t\t\t\tGP - add error done! \n");
+                               printf("\t\t\t\tGP - add error done! \n");
                                estate = OPERATOR_CANCELLED;
                        }
                        else {
@@ -1721,28 +1843,6 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event)
                        estate = OPERATOR_RUNNING_MODAL;
                }
        }
-       else if (p->status == GP_STATUS_IDLING) {
-               /* standard undo/redo shouldn't be allowed to execute or else it causes crashes, so catch it here */
-               // FIXME: this is a hardcoded hotkey that can't be changed
-               // TODO: catch redo as well, but how?
-               if (event->type == ZKEY && event->val == KM_RELEASE) {
-                       /* oskey = cmd key on macs as they seem to use cmd-z for undo as well? */
-                       if ((event->ctrl) || (event->oskey)) {
-                               /* just delete last stroke, which will look like undo to the end user */
-                               //printf("caught attempted undo event... deleting last stroke \n");
-                               gpencil_frame_delete_laststroke(p->gpl, p->gpf);
-                               /* undoing the last line can free p->gpf
-                                * note, could do this in a bit more of an elegant way then a search but it at least prevents a crash */
-                               if(BLI_findindex(&p->gpl->frames, p->gpf) == -1) {
-                                       p->gpf= NULL;
-                               }
-
-                               /* event handled, so force refresh */
-                               ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
-                               estate = OPERATOR_RUNNING_MODAL; 
-                       }
-               }
-       }
        
        /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
        if(0==gpencil_area_exists(C, p->sa))
@@ -1778,6 +1878,7 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event)
 static EnumPropertyItem prop_gpencil_drawmodes[] = {
        {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", ""},
        {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 0, "Draw Straight Lines", ""},
+       {GP_PAINTMODE_DRAW_POLY, "DRAW_POLY", 0, "Dtaw Poly Line", ""},
        {GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", ""},
        {0, NULL, 0, NULL, NULL}
 };
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
new file mode 100644 (file)
index 0000000..1154975
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation,
+ *                 Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_listBase.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+
+#include "BLI_listbase.h"
+
+#include "ED_gpencil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "gpencil_intern.h"
+
+#define MAXUNDONAME    64
+
+typedef struct bGPundonode {
+       struct bGPundonode *next, *prev;
+
+       char name[MAXUNDONAME];
+       struct bGPdata *gpd;
+} bGPundonode;
+
+static ListBase undo_nodes = {NULL, NULL};
+static bGPundonode *cur_node = NULL;
+
+int ED_gpencil_session_active(void)
+{
+       return undo_nodes.first != NULL;
+}
+
+int ED_undo_gpencil_step(bContext *C, int step, const char *name)
+{
+       bGPdata **gpd_ptr= NULL, *new_gpd= NULL;
+
+       gpd_ptr= gpencil_data_get_pointers(C, NULL);
+
+       if(step==1) {   /* undo */
+               //printf("\t\tGP - undo step\n");
+               if(cur_node->prev) {
+                       if(!name || strcmp(cur_node->name, name) == 0) {
+                               cur_node= cur_node->prev;
+                               new_gpd= cur_node->gpd;
+                       }
+               }
+       }
+       else if (step==-1) {
+               //printf("\t\tGP - redo step\n");
+               if(cur_node->next) {
+                       if(!name || strcmp(cur_node->name, name) == 0) {
+                               cur_node= cur_node->next;
+                               new_gpd= cur_node->gpd;
+                       }
+               }
+       }
+
+       if(new_gpd) {
+               if(gpd_ptr) {
+                       if(*gpd_ptr) {
+                               bGPdata *gpd= *gpd_ptr;
+                               bGPDlayer *gpl, *gpld;
+
+                               free_gpencil_layers(&gpd->layers);
+
+                               /* copy layers */
+                               gpd->layers.first= gpd->layers.last= NULL;
+
+                               for (gpl= new_gpd->layers.first; gpl; gpl= gpl->next) {
+                                       /* make a copy of source layer and its data */
+                                       gpld= gpencil_layer_duplicate(gpl);
+                                       BLI_addtail(&gpd->layers, gpld);
+                               }
+                       }
+               }
+       }
+
+       WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL);
+
+       return OPERATOR_FINISHED;
+}
+
+void gpencil_undo_init(bGPdata *gpd)
+{
+       gpencil_undo_push(gpd);
+}
+
+void gpencil_undo_push(bGPdata *gpd)
+{
+       bGPundonode *undo_node;
+
+       //printf("\t\tGP - undo push\n");
+
+       if(cur_node) {
+               /* remove all un-done nodes from stack */
+               undo_node= cur_node->next;
+
+               while(undo_node) {
+                       bGPundonode *next_node= undo_node->next;
+
+                       free_gpencil_data(undo_node->gpd);
+                       MEM_freeN(undo_node->gpd);
+
+                       BLI_freelinkN(&undo_nodes, undo_node);
+
+                       undo_node= next_node;
+               }
+       }
+
+       /* create new undo node */
+       undo_node= MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
+       undo_node->gpd= gpencil_data_duplicate(gpd);
+
+       cur_node= undo_node;
+
+       BLI_addtail(&undo_nodes, undo_node);
+}
+
+void gpencil_undo_finish(void)
+{
+       bGPundonode *undo_node= undo_nodes.first;
+
+       while(undo_node) {
+               free_gpencil_data(undo_node->gpd);
+               MEM_freeN(undo_node->gpd);
+
+               undo_node= undo_node->next;
+       }
+
+       BLI_freelistN(&undo_nodes);
+
+       cur_node= NULL;
+}
index 07dcc959e32c619fecc56550b7beed98d7aaf05f..bfd16487ae5e7dc71efdc652bf48f797220f16ba 100644 (file)
@@ -106,4 +106,8 @@ void paste_gpdata(void);
 void snap_gplayer_frames(struct bGPDlayer *gpl, short mode);
 void mirror_gplayer_frames(struct bGPDlayer *gpl, short mode);
 
+/* ------------ Grease-Pencil Undo System ------------------ */
+int ED_gpencil_session_active(void);
+int ED_undo_gpencil_step(struct bContext *C, int step, const char *name);
+
 #endif /*  ED_GPENCIL_H */
index 9539706468f4282bf76cf05a0a31864ac58413f8..79a3251cdf1c052453d5a907325fbc1e80d3240b 100644 (file)
@@ -4664,7 +4664,7 @@ static void paint_brush_init_tex(Brush *brush)
        if(brush) {
                MTex *mtex= &brush->mtex;
                if(mtex->tex && mtex->tex->nodetree)
-                       ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
+                       ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
        }
        
 }
@@ -4806,7 +4806,7 @@ static void paint_brush_exit_tex(Brush *brush)
        if(brush) {
                MTex *mtex= &brush->mtex;
                if(mtex->tex && mtex->tex->nodetree)
-                       ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
+                       ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
        }       
 }
 
index bf34a3b8c9f4ad139474218be487ba00da63a8af..ced3dd00a9cfc9a4dd710b61a23f27de1f1dbad3 100644 (file)
@@ -3274,7 +3274,7 @@ static void sculpt_brush_init_tex(Sculpt *sd, SculptSession *ss)
 
        /* init mtex nodes */
        if(mtex->tex && mtex->tex->nodetree)
-               ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
+               ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
 
        /* TODO: Shouldn't really have to do this at the start of every
           stroke, but sculpt would need some sort of notification when
@@ -3455,7 +3455,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
        MTex *mtex= &brush->mtex;
 
        if(mtex->tex && mtex->tex->nodetree)
-               ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
+               ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
 }
 
 static void sculpt_stroke_done(bContext *C, struct PaintStroke *UNUSED(stroke))
index 890b04dce9136a9a9b0fcb6779ae4cded96d6976..0d2ec7c646fe20e8d984697937d5a9862e58e708 100644 (file)
@@ -637,7 +637,7 @@ static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *nt
        float arrowbutw= 0.8f*UI_UNIT_X;
        /* layout stuff for buttons on group left frame */
        float colw= 0.6f*node_group_frame;
-       float col1= 6;
+       float col1= 6 - node_group_frame;
        float col2= col1 + colw+6;
        float col3= node_group_frame - arrowbutw - 6;
        /* layout stuff for buttons on group right frame */
index 5c921d403444cd787c74b4a3cea6a30c8987ebeb..7077f4a749757098d27a299b1bf554fec8d98462 100644 (file)
@@ -232,6 +232,7 @@ static void node_menu_add(const bContext *C, Menu *menu)
                uiItemMenuF(layout, "Convertor", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR));
                uiItemMenuF(layout, "Group", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
                uiItemMenuF(layout, "Dynamic", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_DYNAMIC));
+               uiItemMenuF(layout, "Layout", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
        }
        else if(snode->treetype==NTREE_COMPOSIT) {
                uiItemMenuF(layout, "Input", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT));
@@ -243,6 +244,7 @@ static void node_menu_add(const bContext *C, Menu *menu)
                uiItemMenuF(layout, "Matte", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_MATTE));
                uiItemMenuF(layout, "Distort", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_DISTORT));
                uiItemMenuF(layout, "Group", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
+               uiItemMenuF(layout, "Layout", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
        }
        else if(snode->treetype==NTREE_TEXTURE) {
                uiItemMenuF(layout, "Input", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT));
@@ -253,6 +255,7 @@ static void node_menu_add(const bContext *C, Menu *menu)
                uiItemMenuF(layout, "Convertor", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR));
                uiItemMenuF(layout, "Distort", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_DISTORT));
                uiItemMenuF(layout, "Group", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
+               uiItemMenuF(layout, "Layout", 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
        }
 }
 
index 09507194969b466fb6730c419ce3167cfb46d4d1..1796bd4e928fec91d1e6d503f7d92929faea01d7 100644 (file)
@@ -1678,7 +1678,14 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
        if (RNA_property_is_set(op->ptr, "value"))
        {
                float values[4]= {0}; /* incase value isn't length 4, avoid uninitialized memory  */
-               RNA_float_get_array(op->ptr, "value", values);
+               PropertyRNA *prop= RNA_struct_find_property(op->ptr, "value");
+
+               if(RNA_property_array_check(prop)) {
+                       RNA_float_get_array(op->ptr, "value", values);
+               } else {
+                       values[0]= RNA_float_get(op->ptr, "value");
+               }
+
                QUATCOPY(t->values, values);
                QUATCOPY(t->auto_values, values);
                t->flag |= T_AUTOVALUES;
index a2381a208ef015a452d0e73fa1eeb8a5a3ae62dd..c1aca61f7950e60e6401dd935d2348d9e7438c62 100644 (file)
@@ -54,6 +54,7 @@
 #include "ED_armature.h"
 #include "ED_particle.h"
 #include "ED_curve.h"
+#include "ED_gpencil.h"
 #include "ED_mball.h"
 #include "ED_mesh.h"
 #include "ED_object.h"
@@ -126,6 +127,11 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
        Object *obact= CTX_data_active_object(C);
        ScrArea *sa= CTX_wm_area(C);
 
+       /* grease pencil can be can be used in plenty of spaces, so check it first */
+       if(ED_gpencil_session_active()) {
+               return ED_undo_gpencil_step(C, step, undoname);
+       }
+
        if(sa && sa->spacetype==SPACE_IMAGE) {
                SpaceImage *sima= (SpaceImage *)sa->spacedata.first;
                
index 3a51a6a56a423f22a5cfb735c29efc374e0bc5a4..bac1e3cd8cac594d847cd3958a84e73902667c34 100644 (file)
@@ -84,7 +84,7 @@ typedef struct bNodeSocket {
        
        /* execution data */
        short stack_index;                      /* local stack index */
-       short pad2;
+       short stack_type;                       /* deprecated, kept for forward compatibility */
        int pad3;
        void *cache;                            /* cached data from execution */
        
@@ -198,8 +198,8 @@ typedef struct bNodeLink {
 } bNodeLink;
 
 /* link->flag */
-#define NODE_LINK_VALID                        1               /* link has been successfully validated */
-#define NODE_LINKFLAG_HILITE   2
+#define NODE_LINKFLAG_HILITE   1               /* link has been successfully validated */
+#define NODE_LINK_VALID                        2
 
 /* the basis for a Node tree, all links and nodes reside internal here */
 /* only re-usable node trees are in the library though, materials and textures allocate own tree struct */
index 936f2e5e40c3072183e65b1d4b98024a1df49b68..e7d0c5cdec2449267352fca0a884e7e420fc34a4 100644 (file)
@@ -4407,7 +4407,7 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
                buf= MEM_mallocN(sizeof(char)*(length+1), "RNA_property_as_string");
                buf_esc= MEM_mallocN(sizeof(char)*(length*2+1), "RNA_property_as_string esc");
                RNA_property_string_get(ptr, prop, buf);
-               BLI_strescape(buf_esc, buf, length*2);
+               BLI_strescape(buf_esc, buf, length*2+1);
                MEM_freeN(buf);
                BLI_dynstr_appendf(dynstr, "\"%s\"", buf_esc);
                MEM_freeN(buf_esc);
index 9e98f166875969ed7f7c3154ebd830321fcfc990..78b8c67d92c8bd2b792e3782f49ef810e602f0b1 100644 (file)
@@ -261,6 +261,7 @@ void RNA_api_wm(struct StructRNA *srna);
 void RNA_api_sensor(struct StructRNA *srna);
 void RNA_api_controller(struct StructRNA *srna);
 void RNA_api_actuator(struct StructRNA *srna);
+void RNA_api_texture(struct StructRNA *srna);
 void RNA_api_environment_map(struct StructRNA *srna);
 
 /* main collection functions */
index 59707f05e6f60f60f86c6614ad775fa668f0e289..bd1021f038afec3d5f4b06db06a5e2f267a99ef2 100644 (file)
@@ -68,13 +68,14 @@ static void rna_Screen_scene_set(PointerRNA *ptr, PointerRNA value)
        sc->newscene= value.data;
 }
 
-static void rna_Screen_scene_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Screen_scene_update(bContext *C, PointerRNA *ptr)
 {
        bScreen *sc= (bScreen*)ptr->data;
 
-       /* exception: can't set screens inside of area/region handers */
+       /* exception: can't set screens inside of area/region handers, and must
+          use context so notifier gets to the right window  */
        if(sc->newscene) {
-               WM_main_add_notifier(NC_SCENE|ND_SCENEBROWSE, sc->newscene);
+               WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, sc->newscene);
                sc->newscene= NULL;
        }
 }
@@ -231,6 +232,7 @@ static void rna_def_screen(BlenderRNA *brna)
        RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_NULL);
        RNA_def_property_pointer_funcs(prop, NULL, "rna_Screen_scene_set", NULL, NULL);
        RNA_def_property_ui_text(prop, "Scene", "Active scene to be edited in the screen");
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
        RNA_def_property_update(prop, 0, "rna_Screen_scene_update");
 
        /* collections */
index 503212201c41e2ddd3b40101687386e23d2b2569..890be76c49abe0d7d1ac61313b8d5118821a259b 100644 (file)
@@ -1820,6 +1820,8 @@ static void rna_def_texture(BlenderRNA *brna)
        rna_def_texture_pointdensity(brna);
        rna_def_texture_voxeldata(brna);
        /* XXX add more types here .. */
+
+       RNA_api_texture(srna);
 }
 
 void RNA_def_texture(BlenderRNA *brna)
index 8d4b73f1f0c7b525c72d8009275b603818ddaae1..8c63d5da8fd59d81c784f95589959d3cd6329c50 100644 (file)
@@ -43,6 +43,7 @@
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "RE_pipeline.h"
+#include "RE_shader_ext.h"
 
 void save_envmap(struct EnvMap *env, bContext *C, ReportList *reports, const char* filepath, struct Scene *scene, float layout[12])
 {
@@ -67,30 +68,59 @@ void clear_envmap(struct EnvMap *env, bContext *C)
                }
 }
 
+void texture_evaluate(struct Tex *tex, float value[3], float color_r[3])
+{
+       TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
+       multitex_ext(tex, value, NULL, NULL, 1, &texres);
+
+       color_r[0] = texres.tr;
+       color_r[1] = texres.tg;
+       color_r[2] = texres.tb;
+       color_r[3] = texres.tin;
+}
+
 #else
 
+void RNA_api_texture(StructRNA *srna)
+{
+       FunctionRNA *func;
+       PropertyRNA *parm;
+
+       func= RNA_def_function(srna, "evaluate", "texture_evaluate");
+       RNA_def_function_ui_description(func, "Evaluate the texture at the coordinates given");
+
+       parm= RNA_def_float_vector(func, "value", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+
+       /* return location and normal */
+       parm= RNA_def_float_vector(func, "result", 4, NULL, -FLT_MAX, FLT_MAX, "Result", NULL, -1e4, 1e4);
+       RNA_def_property_flag(parm, PROP_THICK_WRAP);
+       RNA_def_function_output(func, parm);
+
+}
+
 void RNA_api_environment_map(StructRNA *srna)
 {
        FunctionRNA *func;
        PropertyRNA *parm;
-       
+
        static const float default_layout[] = { 0,0, 1,0, 2,0, 0,1, 1,1, 2,1 };
-       
+
        func= RNA_def_function(srna, "clear", "clear_envmap");
-               RNA_def_function_ui_description(func, "Discard the environment map and free it from memory.");
-               RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+       RNA_def_function_ui_description(func, "Discard the environment map and free it from memory.");
+       RNA_def_function_flag(func, FUNC_USE_CONTEXT);
 
 
        func= RNA_def_function(srna,"save", "save_envmap");
-               RNA_def_function_ui_description(func, "Save the environment map to disc using the scene render settings.");
-               RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS);
-       
-               parm= RNA_def_string_file_name(func,"filepath","",FILE_MAX,"File path","Location of the output file");
-                       RNA_def_property_flag(parm, PROP_REQUIRED);
-       
-               RNA_def_pointer(func, "scene", "Scene", "", "Overrides the scene from which image parameters are taken.");
+       RNA_def_function_ui_description(func, "Save the environment map to disc using the scene render settings.");
+       RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS);
+
+       parm= RNA_def_string_file_name(func,"filepath","",FILE_MAX,"File path","Location of the output file");
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+
+       RNA_def_pointer(func, "scene", "Scene", "", "Overrides the scene from which image parameters are taken.");
 
-               parm = RNA_def_float_array(func, "layout", 12, default_layout, 0.0f, 0.0f, "File layout", "Flat array describing the X,Y position of each cube face in the output image, where 1 is the size of a face. Order is [+Z -Z +Y -X -Y +X]. Use -1 to skip a face.", 0.0f, 0.0f);
+       parm = RNA_def_float_array(func, "layout", 12, default_layout, 0.0f, 0.0f, "File layout", "Flat array describing the X,Y position of each cube face in the output image, where 1 is the size of a face. Order is [+Z -Z +Y -X -Y +X]. Use -1 to skip a face.", 0.0f, 0.0f);
 }
 
 #endif
index a595b121d1ae56defb86097ab515aabf6ce4f1c4..7ce1e1ab88f433056b4b002acececdd3868f04be 100644 (file)
@@ -482,13 +482,14 @@ static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
        win->newscreen= value.data;
 }
 
-static void rna_Window_screen_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Window_screen_update(bContext *C, PointerRNA *ptr)
 {
        wmWindow *win= (wmWindow*)ptr->data;
 
-       /* exception: can't set screens inside of area/region handers */
+       /* exception: can't set screens inside of area/region handers, and must
+          use context so notifier gets to the right window */
        if(win->newscreen) {
-               WM_main_add_notifier(NC_SCREEN|ND_SCREENBROWSE, win->newscreen);
+               WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, win->newscreen);
                win->newscreen= NULL;
        }
 }
@@ -1454,6 +1455,7 @@ static void rna_def_window(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Screen", "Active screen showing in the window");
        RNA_def_property_flag(prop, PROP_EDITABLE);
        RNA_def_property_pointer_funcs(prop, NULL, "rna_Window_screen_set", NULL, NULL);
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
        RNA_def_property_update(prop, 0, "rna_Window_screen_update");
 }
 
index 72b54dce47392ddb2adb4f6437642bfd2af963d5..11ec327c306d20bc952f85ab8a2439d1a8d8d23d 100644 (file)
@@ -360,7 +360,7 @@ static void rna_def_lighting(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "samples", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "aosamp");
-       RNA_def_property_range(prop, 1, 32);
+       RNA_def_property_range(prop, 1, 128);
        RNA_def_property_ui_text(prop, "Samples", "Amount of ray samples. Higher values give smoother results and longer rendering times");
        RNA_def_property_update(prop, 0, "rna_World_update");
 
index 0ea62b0aa5f57cc7554118bbdf2f1546a8ab658d..4fc5e23e26a223592aefa4ec05044b93e1cbc4a4 100644 (file)
@@ -200,17 +200,22 @@ bNodeTreeType ntreeType_Composite = {
 };
 
 
-struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree)
+/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
+ * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
+ */
+struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_data)
 {
        bNodeTreeExec *exec;
        bNode *node;
        bNodeSocket *sock;
        
-       /* XXX hack: prevent exec data from being generated twice.
-        * this should be handled by the renderer!
-        */
-       if (ntree->execdata)
-               return ntree->execdata;
+       if (use_tree_data) {
+               /* XXX hack: prevent exec data from being generated twice.
+                * this should be handled by the renderer!
+                */
+               if (ntree->execdata)
+                       return ntree->execdata;
+       }
        
        /* ensures only a single output node is enabled */
        ntreeSetOutput(ntree);
@@ -236,15 +241,20 @@ struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree)
                }
        }
        
-       /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
+       if (use_tree_data) {
+               /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
                 * which only store the ntree pointer. Should be fixed at some point!
                 */
-       ntree->execdata = exec;
+               ntree->execdata = exec;
+       }
        
        return exec;
 }
 
-void ntreeCompositEndExecTree(bNodeTreeExec *exec)
+/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
+ * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
+ */
+void ntreeCompositEndExecTree(bNodeTreeExec *exec, int use_tree_data)
 {
        if(exec) {
                bNodeTree *ntree= exec->nodetree;
@@ -269,8 +279,10 @@ void ntreeCompositEndExecTree(bNodeTreeExec *exec)
        
                ntree_exec_end(exec);
                
-               /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
-               ntree->execdata = NULL;
+               if (use_tree_data) {
+                       /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+                       ntree->execdata = NULL;
+               }
        }
 }
 
@@ -495,10 +507,10 @@ static  void ntree_composite_texnode(bNodeTree *ntree, int init)
                                /* has internal flag to detect it only does it once */
                                if(init) {
                                        if (!tex->nodetree->execdata)
-                                               tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree); 
+                                               tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree, 1); 
                                }
                                else
-                                       ntreeTexEndExecTree(tex->nodetree->execdata);
+                                       ntreeTexEndExecTree(tex->nodetree->execdata, 1);
                                        tex->nodetree->execdata = NULL;
                        }
                }
@@ -521,8 +533,10 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
        if(do_preview)
                ntreeInitPreview(ntree, 0, 0);
        
-       if (!ntree->execdata)
-               exec = ntreeCompositBeginExecTree(ntree);
+       if (!ntree->execdata) {
+               /* XXX this is the top-level tree, so we use the ntree->execdata pointer. */
+               exec = ntreeCompositBeginExecTree(ntree, 1);
+       }
        ntree_composite_texnode(ntree, 1);
        
        /* prevent unlucky accidents */
@@ -592,7 +606,8 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
        
        BLI_end_threads(&threads);
        
-       ntreeCompositEndExecTree(exec);
+       /* XXX top-level tree uses the ntree->execdata pointer */
+       ntreeCompositEndExecTree(exec, 1);
 }
 
 /* *********************************************** */
index fbff8198ddeab100a856d66c9d7ad728cde3f54d..d5ae442c25f422cda5cf944a4083555e2e109682 100644 (file)
@@ -122,7 +122,7 @@ static void *group_initexec(bNode *node)
        bNodeStack *ns;
        
        /* initialize the internal node tree execution */
-       exec = ntreeCompositBeginExecTree(ngroup);
+       exec = ntreeCompositBeginExecTree(ngroup, 0);
        
        /* tag group outputs as external to prevent freeing */
        for (sock=ngroup->outputs.first; sock; sock=sock->next) {
@@ -139,7 +139,7 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata)
 {
        bNodeTreeExec *gexec= (bNodeTreeExec*)nodedata;
        
-       ntreeCompositEndExecTree(gexec);
+       ntreeCompositEndExecTree(gexec, 0);
 }
 
 /* Copy inputs to the internal stack.
index 3ea34dd094a3769800b1777ea5692b68ceea0e2b..aabaf5b86dee669f6abd5ae09394aacb0028f58c 100644 (file)
@@ -422,7 +422,11 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou
 void node_verify_socket_templates(bNodeTree *ntree, bNode *node)
 {
        bNodeType *ntype= node->typeinfo;
-       if(ntype) {
+       /* XXX Small trick: don't try to match socket lists when there are no templates.
+        * This also prevents group node sockets from being removed, without the need to explicitly
+        * check the node type here.
+        */
+       if(ntype && ((ntype->inputs && ntype->inputs[0].type>=0) || (ntype->outputs && ntype->outputs[0].type>=0))) {
                verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs);
                verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
        }
index 8cb1ebeb15f50fff4076ff2fffb230ae7da4561a..642e4be10d7db9cbba879d861a7c832afe605c55 100644 (file)
@@ -108,11 +108,11 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
        bNodeTreeExec *exec;
 
        if(!ntree->execdata)
-               exec = ntreeShaderBeginExecTree(ntree);
+               exec = ntreeShaderBeginExecTree(ntree, 1);
 
        ntreeExecGPUNodes(exec, mat, 1);
 
-       ntreeShaderEndExecTree(exec);
+       ntreeShaderEndExecTree(exec, 1);
 }
 
 /* **************** call to switch lamploop for material node ************ */
@@ -125,16 +125,21 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult
 }
 
 
-bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
+/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
+ * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
+ */
+bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data)
 {
        bNodeTreeExec *exec;
        bNode *node;
        
-       /* XXX hack: prevent exec data from being generated twice.
-        * this should be handled by the renderer!
-        */
-       if (ntree->execdata)
-               return ntree->execdata;
+       if (use_tree_data) {
+               /* XXX hack: prevent exec data from being generated twice.
+                * this should be handled by the renderer!
+                */
+               if (ntree->execdata)
+                       return ntree->execdata;
+       }
        
        /* ensures only a single output node is enabled */
        ntreeSetOutput(ntree);
@@ -148,15 +153,20 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
        for(node= exec->nodetree->nodes.first; node; node= node->next)
                node->need_exec= 1;
        
-       /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
-        * which only store the ntree pointer. Should be fixed at some point!
-        */
-       ntree->execdata = exec;
+       if (use_tree_data) {
+               /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
+                * which only store the ntree pointer. Should be fixed at some point!
+                */
+               ntree->execdata = exec;
+       }
        
        return exec;
 }
 
-void ntreeShaderEndExecTree(bNodeTreeExec *exec)
+/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
+ * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
+ */
+void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data)
 {
        if(exec) {
                bNodeTree *ntree= exec->nodetree;
@@ -176,8 +186,10 @@ void ntreeShaderEndExecTree(bNodeTreeExec *exec)
                
                ntree_exec_end(exec);
                
-               /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
-               ntree->execdata = NULL;
+               if (use_tree_data) {
+                       /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+                       ntree->execdata = NULL;
+               }
        }
 }
 
@@ -199,7 +211,7 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
        memset(shr, 0, sizeof(ShadeResult));
        
        if (!exec)
-               exec = ntree->execdata = ntreeShaderBeginExecTree(exec->nodetree);
+               exec = ntree->execdata = ntreeShaderBeginExecTree(exec->nodetree, 1);
        
        nts= ntreeGetThreadStack(exec, shi->thread);
        ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
index aa8e8241bf893b886ce537ae95e7d0b8d83bc656..2dd15ab1e99242145e8937984219f1be3a27e910 100644 (file)
@@ -76,7 +76,7 @@ static void *group_initexec(bNode *node)
        bNodeTreeExec *exec;
        
        /* initialize the internal node tree execution */
-       exec = ntreeShaderBeginExecTree(ngroup);
+       exec = ntreeShaderBeginExecTree(ngroup, 0);
        
        return exec;
 }
@@ -85,7 +85,7 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata)
 {
        bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
        
-       ntreeShaderEndExecTree(gexec);
+       ntreeShaderEndExecTree(gexec, 0);
 }
 
 /* Copy inputs to the internal stack.
index 3ea15a316abb89f5df67354d19fe277e551521c7..603aa7ceb774b5df61b1f782b83d672fa507f957 100644 (file)
@@ -121,16 +121,21 @@ int ntreeTexTagAnimated(bNodeTree *ntree)
        return 0;
 }
 
-bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree)
+/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
+ * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
+ */
+bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data)
 {
        bNodeTreeExec *exec;
        bNode *node;
        
-       /* XXX hack: prevent exec data from being generated twice.
-        * this should be handled by the renderer!
-        */
-       if (ntree->execdata)
-               return ntree->execdata;
+       if (use_tree_data) {
+               /* XXX hack: prevent exec data from being generated twice.
+                * this should be handled by the renderer!
+                */
+               if (ntree->execdata)
+                       return ntree->execdata;
+       }
        
        /* common base initialization */
        exec = ntree_exec_begin(ntree);
@@ -141,10 +146,12 @@ bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree)
        for(node= exec->nodetree->nodes.first; node; node= node->next)
                node->need_exec= 1;
        
-       /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
-        * which only store the ntree pointer. Should be fixed at some point!
-        */
-       ntree->execdata = exec;
+       if (use_tree_data) {
+               /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
+                * which only store the ntree pointer. Should be fixed at some point!
+                */
+               ntree->execdata = exec;
+       }
        
        return exec;
 }
@@ -163,7 +170,10 @@ static void tex_free_delegates(bNodeTreeExec *exec)
                                        MEM_freeN(ns->data);
 }
 
-void ntreeTexEndExecTree(bNodeTreeExec *exec)
+/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
+ * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
+ */
+void ntreeTexEndExecTree(bNodeTreeExec *exec, int use_tree_data)
 {
        if(exec) {
                bNodeTree *ntree= exec->nodetree;
@@ -185,8 +195,10 @@ void ntreeTexEndExecTree(bNodeTreeExec *exec)
                
                ntree_exec_end(exec);
                
-               /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
-               ntree->execdata = NULL;
+               if (use_tree_data) {
+                       /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+                       ntree->execdata = NULL;
+               }
        }
 }
 
@@ -223,7 +235,7 @@ int ntreeTexExecTree(
        data.shi= shi;
        
        if (!exec)
-               exec = ntreeTexBeginExecTree(nodes);
+               exec = ntreeTexBeginExecTree(nodes, 1);
        
        nts= ntreeGetThreadStack(exec, thread);
        ntreeExecThreadNodes(exec, nts, &data, thread);
index afb24226416ed1c4e9578976340a7067d82c667a..1b46b830909ff443da5356ffe2eccc8e005b0c3e 100644 (file)
@@ -61,7 +61,7 @@ static void *group_initexec(bNode *node)
        void *exec;
        
        /* initialize the internal node tree execution */
-       exec = ntreeTexBeginExecTree(ngroup);
+       exec = ntreeTexBeginExecTree(ngroup, 0);
        
        return exec;
 }
@@ -70,7 +70,7 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata)
 {
        bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
        
-       ntreeTexEndExecTree(gexec);
+       ntreeTexEndExecTree(gexec, 0);
 }
 
 /* Copy inputs to the internal stack.
index f0158fe72c30b9da9c8163076ec44d4de227179f..67ed90c79eb164890448f64025b736e3af3b0df6 100644 (file)
@@ -344,7 +344,7 @@ void bpy_text_clear_modules(int clear_all)
        
        /* looping over the dict */
        PyObject *key, *value;
-       int pos= 0;
+       Py_ssize_t pos= 0;
        
        /* new list */
        PyObject *list;
@@ -374,7 +374,7 @@ void bpy_text_clear_modules(int clear_all)
        }
        
        /* remove all our modules */
-       for(pos=0; pos < PyList_Size(list); pos++) {
+       for(pos=0; pos < PyList_GET_SIZE(list); pos++) {
                /* PyObject_Print(key, stderr, 0); */
                key= PyList_GET_ITEM(list, pos);
                PyDict_DelItem(modules, key);
index d10c8c843e8cd654bfa2aeda1162cb2d5def2e01..2212499d842e439bb7ee4fa322d15a161ce18416 100644 (file)
@@ -4608,7 +4608,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
 
 
 #ifdef DEBUG_STRING_FREE
-       // if(PyList_Size(string_free_ls)) printf("%.200s.%.200s():  has %d strings\n", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), (int)PyList_Size(string_free_ls));
+       // if(PyList_GET_SIZE(string_free_ls)) printf("%.200s.%.200s():  has %d strings\n", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), (int)PyList_GET_SIZE(string_free_ls));
        Py_DECREF(string_free_ls);
 #undef DEBUG_STRING_FREE
 #endif
index bcdfe020e1ab10e3d6585dc6bd8e6324ca177dfd..0394d732ae32e97bd0b67c3f5f3b4f62611ad18c 100644 (file)
@@ -983,7 +983,7 @@ static PyObject *M_Geometry_tesselate_polygon(PyObject *UNUSED(self), PyObject *
 
 static int boxPack_FromPyObject(PyObject *value, boxPack **boxarray)
 {
-       int len, i;
+       Py_ssize_t len, i;
        PyObject *list_item, *item_1, *item_2;
        boxPack *box;
 
@@ -995,14 +995,14 @@ static int boxPack_FromPyObject(PyObject *value, boxPack **boxarray)
                return -1;
        }
 
-       len= PyList_Size(value);
+       len= PyList_GET_SIZE(value);
 
        (*boxarray)= MEM_mallocN(len*sizeof(boxPack), "boxPack box");
 
 
        for(i= 0; i < len; i++) {
                list_item= PyList_GET_ITEM(value, i);
-               if(!PyList_Check(list_item) || PyList_Size(list_item) < 4) {
+               if(!PyList_Check(list_item) || PyList_GET_SIZE(list_item) < 4) {
                        MEM_freeN(*boxarray);
                        PyErr_SetString(PyExc_TypeError,
                                        "can only pack a list of [x, y, w, h]");
@@ -1034,11 +1034,11 @@ static int boxPack_FromPyObject(PyObject *value, boxPack **boxarray)
 
 static void boxPack_ToPyObject(PyObject *value, boxPack **boxarray)
 {
-       int len, i;
+       Py_ssize_t len, i;
        PyObject *list_item;
        boxPack *box;
 
-       len= PyList_Size(value);
+       len= PyList_GET_SIZE(value);
 
        for(i= 0; i < len; i++) {
                box= (*boxarray)+i;
@@ -1062,7 +1062,7 @@ PyDoc_STRVAR(M_Geometry_box_pack_2d_doc,
 static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlist)
 {
        float tot_width= 0.0f, tot_height= 0.0f;
-       int len;
+       Py_ssize_t len;
 
        PyObject *ret;
 
index e35b3e53f5baa7340dd355fc59cdd06cdc48eaa8..cf1fae81eb564a5c5ce8989051178b15370d7443 100644 (file)
@@ -125,7 +125,7 @@ static void init_render_texture(Render *re, Tex *tex)
        }
        
        if(tex->nodetree && tex->use_nodes) {
-               ntreeTexBeginExecTree(tex->nodetree); /* has internal flag to detect it only does it once */
+               ntreeTexBeginExecTree(tex->nodetree, 1); /* has internal flag to detect it only does it once */
        }
 }
 
@@ -145,7 +145,7 @@ void init_render_textures(Render *re)
 static void end_render_texture(Tex *tex)
 {
        if(tex && tex->use_nodes && tex->nodetree && tex->nodetree->execdata)
-               ntreeTexEndExecTree(tex->nodetree->execdata);
+               ntreeTexEndExecTree(tex->nodetree->execdata, 1);
 }
 
 void end_render_textures(Render *re)
index 40f1701e44a89a2582b19a15f144b92a01107acb..810e9b6ddfb1631972f835890cf14693a79ba1a4 100644 (file)
@@ -507,9 +507,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
                                //PyDict_Clear(PyModule_GetDict(gameLogic));
                                
                                // Keep original items, means python plugins will autocomplete members
-                               int listIndex;
                                PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic));
-                               for (listIndex=0; listIndex < PyList_Size(gameLogic_keys_new); listIndex++)  {
+                               const Py_ssize_t numitems= PyList_GET_SIZE(gameLogic_keys_new);
+                               Py_ssize_t listIndex;
+                               for (listIndex=0; listIndex < numitems; listIndex++)  {
                                        PyObject* item = PyList_GET_ITEM(gameLogic_keys_new, listIndex);
                                        if (!PySequence_Contains(gameLogic_keys, item)) {
                                                PyDict_DelItem( PyModule_GetDict(gameLogic), item);
index 8fc224fba6ff6f096a9310f04de272ca9d663986..6ba178cbb2fded440987a088fde600f47194ec86 100644 (file)
@@ -413,14 +413,21 @@ void BL_ConvertActuators(char* maggiename,
                                                // if sound shall be 3D but isn't mono, we have to make it mono!
                                                if(is3d)
                                                {
-                                                       AUD_Reference<AUD_IReader> reader = snd_sound->createReader();
-                                                       if(reader->getSpecs().channels != AUD_CHANNELS_MONO)
+                                                       try
                                                        {
-                                                               AUD_DeviceSpecs specs;
-                                                               specs.channels = AUD_CHANNELS_MONO;
-                                                               specs.rate = AUD_RATE_INVALID;
-                                                               specs.format = AUD_FORMAT_INVALID;
-                                                               snd_sound = new AUD_ChannelMapperFactory(snd_sound, specs);
+                                                               AUD_Reference<AUD_IReader> reader = snd_sound->createReader();
+                                                               if(reader->getSpecs().channels != AUD_CHANNELS_MONO)
+                                                               {
+                                                                       AUD_DeviceSpecs specs;
+                                                                       specs.channels = AUD_CHANNELS_MONO;
+                                                                       specs.rate = AUD_RATE_INVALID;
+                                                                       specs.format = AUD_FORMAT_INVALID;
+                                                                       snd_sound = new AUD_ChannelMapperFactory(snd_sound, specs);
+                                                               }
+                                                       }
+                                                       catch(AUD_Exception&)
+                                                       {
+                                                               // sound cannot be played... ignore
                                                        }
                                                }
                                        }
index 271d5067dd9733352db35173e43d2797013b1dfa..934f2a8dd8794b6e26117e4c179790a490cab7df 100644 (file)
@@ -387,7 +387,7 @@ PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihig
 static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other)
 {
        CListValue *listval= static_cast<CListValue *>(BGE_PROXY_REF(self));
-       int i, numitems, numitems_orig;
+       Py_ssize_t i, numitems, numitems_orig;
        
        if (listval==NULL) {
                PyErr_SetString(PyExc_SystemError, "CList+other, "BGE_PROXY_ERROR_MSG);
@@ -408,7 +408,7 @@ static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other)
                CValue* listitemval;
                bool error = false;
                
-               numitems = PyList_Size(other);
+               numitems = PyList_GET_SIZE(other);
                
                /* copy the first part of the list */
                listval_new->Resize(numitems_orig + numitems);
index e60b380e95cfc96732e11a804678324bc213450e..41c0850a779e2f4ffa0572a9345c5acae071c027 100644 (file)
@@ -546,8 +546,8 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
                CListValue* listval = new CListValue();
                bool error = false;
 
-               int i;
-               int numitems = PyList_Size(pyobj);
+               Py_ssize_t i;
+               Py_ssize_t numitems = PyList_GET_SIZE(pyobj);
                for (i=0;i<numitems;i++)
                {
                        PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
index 395e2048cb7a07e1ba5d594ca0d539ffb67f7ef7..f14d73cb990d6374dcf04913e5eb075225de342e 100644 (file)
@@ -725,7 +725,7 @@ static PyObject *gLibNew(PyObject*, PyObject* args)
        if(idcode==ID_ME) {
                PyObject *ret= PyList_New(0);
                PyObject *item;
-               for(int i= 0; i < PyList_GET_SIZE(names); i++) {
+               for(Py_ssize_t i= 0; i < PyList_GET_SIZE(names); i++) {
                        name= _PyUnicode_AsString(PyList_GET_ITEM(names, i));
                        if(name) {
                                RAS_MeshObject *meshobj= kx_scene->GetSceneConverter()->ConvertMeshSpecial(kx_scene, maggie, name);
@@ -1751,7 +1751,7 @@ static void initPySysObjects(Main *maggie)
        
        initPySysObjects__append(sys_path, gp_GamePythonPath);
        
-//     fprintf(stderr, "\nNew Path: %d ", PyList_Size(sys_path));
+//     fprintf(stderr, "\nNew Path: %d ", PyList_GET_SIZE(sys_path));
 //     PyObject_Print(sys_path, stderr, 0);
 }
 
@@ -1775,7 +1775,7 @@ static void restorePySysObjects(void)
        gp_OrigPythonSysModules= NULL;  
        
        
-//     fprintf(stderr, "\nRestore Path: %d ", PyList_Size(sys_path));
+//     fprintf(stderr, "\nRestore Path: %d ", PyList_GET_SIZE(sys_path));
 //     PyObject_Print(sys_path, stderr, 0);
 }
 
index 06e343cedb235ea5f2496161de00d97a1e40842d..7c76ab01e93bb6bd2be20fc0d637e43b399445d0 100644 (file)
@@ -1916,7 +1916,7 @@ void KX_Scene::Render2DFilters(RAS_ICanvas* canvas)
 
 void KX_Scene::RunDrawingCallbacks(PyObject* cb_list)
 {
-       int len;
+       Py_ssize_t len;
 
        if (cb_list && (len=PyList_GET_SIZE(cb_list)))
        {
@@ -1925,7 +1925,7 @@ void KX_Scene::RunDrawingCallbacks(PyObject* cb_list)
                PyObject* ret;
 
                // Iterate the list and run the callbacks
-               for (int pos=0; pos < len; pos++)
+               for (Py_ssize_t pos=0; pos < len; pos++)
                {
                        func= PyList_GET_ITEM(cb_list, pos);
                        ret= PyObject_Call(func, args, NULL);
index 6c7b515c0953ed1f8883b99e9a330d1f34b4752f..f24243fcdfc6d4c563a2d9ef25aa0943f5e198d0 100644 (file)
@@ -108,7 +108,15 @@ void KX_SoundActuator::play()
                break;
        }
 
-       m_handle = AUD_getDevice()->play(sound, 0);
+       try
+       {
+               m_handle = AUD_getDevice()->play(sound, 0);
+       }
+       catch(AUD_Exception&)
+       {
+               // cannot play back, ignore
+               return;
+       }
 
        AUD_Reference<AUD_I3DHandle> handle3d = AUD_Reference<AUD_I3DHandle>(m_handle);