Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2011-09-07 09:40:12 +0400
committerBastien Montagne <montagne29@wanadoo.fr>2011-09-07 09:40:12 +0400
commitbac64b39e91f9da10f2b79db8fafecaf9c45a4e7 (patch)
tree58e40312855dfaf9d367ec6e23a9e1faed968426
parentc64336390569a344f972ce41d8a1fb96d3c9c38f (diff)
parent9161d3ce4bdd7c838751462b47eb045ea33a686e (diff)
Merging r39948 through r39988 from trunk into vgroup_modifiers.vgroup_modifiers
-rw-r--r--CMakeLists.txt2
-rw-r--r--build_files/cmake/macros.cmake1
-rw-r--r--build_files/scons/config/win32-mingw-config.py2
-rw-r--r--doc/python_api/rst/bgl.rst90
-rw-r--r--doc/python_api/rst/info_quickstart.rst2
-rw-r--r--doc/python_api/rst/info_tips_and_tricks.rst118
-rw-r--r--doc/python_api/sphinx_doc_gen.py1
-rw-r--r--intern/guardedalloc/MEM_sys_types.h5
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py3
-rw-r--r--source/blender/blenkernel/BKE_global.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h12
-rw-r--r--source/blender/blenkernel/intern/blender.c11
-rw-r--r--source/blender/blenkernel/intern/material.c4
-rw-r--r--source/blender/blenkernel/intern/node.c16
-rw-r--r--source/blender/blenkernel/intern/texture.c2
-rw-r--r--source/blender/blenlib/intern/string.c4
-rw-r--r--source/blender/blenloader/BLO_sys_types.h9
-rw-r--r--source/blender/blenloader/intern/readfile.c33
-rw-r--r--source/blender/blenloader/intern/writefile.c33
-rw-r--r--source/blender/collada/CMakeLists.txt2
-rw-r--r--source/blender/collada/DocumentExporter.cpp162
-rw-r--r--source/blender/collada/SceneExporter.cpp161
-rw-r--r--source/blender/collada/SceneExporter.h101
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt1
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h7
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c263
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c168
-rw-r--r--source/blender/editors/include/ED_gpencil.h4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c4
-rw-r--r--source/blender/editors/space_node/drawnode.c2
-rw-r--r--source/blender/editors/space_node/node_header.c3
-rw-r--r--source/blender/editors/transform/transform.c9
-rw-r--r--source/blender/editors/util/undo.c6
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_access.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_screen.c8
-rw-r--r--source/blender/makesrna/intern/rna_texture.c2
-rw-r--r--source/blender/makesrna/intern/rna_texture_api.c54
-rw-r--r--source/blender/makesrna/intern/rna_wm.c8
-rw-r--r--source/blender/makesrna/intern/rna_world.c2
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c47
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_common.c4
-rw-r--r--source/blender/nodes/intern/node_socket.c6
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c44
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_common.c4
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c40
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_common.c4
-rw-r--r--source/blender/python/generic/bpy_internal_import.c4
-rw-r--r--source/blender/python/intern/bpy_rna.c2
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c12
-rw-r--r--source/blender/render/intern/source/render_texture.c4
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp5
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp21
-rw-r--r--source/gameengine/Expressions/ListValue.cpp4
-rw-r--r--source/gameengine/Expressions/Value.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp10
63 files changed, 1113 insertions, 451 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b54b18aab37..8b5693fb1aa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 58938c8b0b0..d09215d040d 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -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")
diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py
index c815b76ef73..37d693db560 100644
--- a/build_files/scons/config/win32-mingw-config.py
+++ b/build_files/scons/config/win32-mingw-config.py
@@ -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']
diff --git a/doc/python_api/rst/bgl.rst b/doc/python_api/rst/bgl.rst
index 5f3158bf5dd..61400351d16 100644
--- a/doc/python_api/rst/bgl.rst
+++ b/doc/python_api/rst/bgl.rst
@@ -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.
diff --git a/doc/python_api/rst/info_quickstart.rst b/doc/python_api/rst/info_quickstart.rst
index e77e9a76d7f..751e5e1ec61 100644
--- a/doc/python_api/rst/info_quickstart.rst
+++ b/doc/python_api/rst/info_quickstart.rst
@@ -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.
diff --git a/doc/python_api/rst/info_tips_and_tricks.rst b/doc/python_api/rst/info_tips_and_tricks.rst
index bd5faf000c8..f4e68a4516c 100644
--- a/doc/python_api/rst/info_tips_and_tricks.rst
+++ b/doc/python_api/rst/info_tips_and_tricks.rst
@@ -1,34 +1,112 @@
-###############
+***************
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
-=================
+-----------------
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index e378dd19e73..661d41af4ef 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -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),
diff --git a/intern/guardedalloc/MEM_sys_types.h b/intern/guardedalloc/MEM_sys_types.h
index 48230db23a3..4debb32b5c4 100644
--- a/intern/guardedalloc/MEM_sys_types.h
+++ b/intern/guardedalloc/MEM_sys_types.h
@@ -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__)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index b71593add96..aa26cb43eed 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -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()
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 17876c6ec9d..0e48673f1b1 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -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 */
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 7207fb7d0fb..1de3c295f4d 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 5f33059e117..2d4354bdd9f 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -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;
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 36631d5af90..aab8e1abbea 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -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);
}
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 481893b86a8..292f38b9472 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -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) {
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 6119a855366..38165182d83 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -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);
}
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index c4ed44f0cdb..ae5fa40f3b9 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -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;
diff --git a/source/blender/blenloader/BLO_sys_types.h b/source/blender/blenloader/BLO_sys_types.h
index 2114fc34bf1..4b3902dca43 100644
--- a/source/blender/blenloader/BLO_sys_types.h
+++ b/source/blender/blenloader/BLO_sys_types.h
@@ -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__)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 5518e133daf..eb5d6a6fbcb 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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 */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index c3f51dc6ce4..3b736e8aeae 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -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);
diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt
index d73373aa901..cc7229383e3 100644
--- a/source/blender/collada/CMakeLists.txt
+++ b/source/blender/collada/CMakeLists.txt
@@ -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
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index 6e780889d16..85f37d29f22 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -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
index 00000000000..96f20ac21c3
--- /dev/null
+++ b/source/blender/collada/SceneExporter.cpp
@@ -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
index 00000000000..30fef924ffd
--- /dev/null
+++ b/source/blender/collada/SceneExporter.h
@@ -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
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 7a2f196fd6d..b312f397939 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -42,6 +42,7 @@ set(SRC
gpencil_edit.c
gpencil_ops.c
gpencil_paint.c
+ gpencil_undo.c
gpencil_intern.h
)
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 440d5ee7c4d..cfa9585868e 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -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. */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 9dc764b7aac..1cd8b1f05db 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -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);
}
}
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index c31de8d30a7..8000af54f53 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -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! */
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index e1e4c8d5457..150e0ba90e4 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -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);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 04565eab155..a23f2064a9e 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -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
index 00000000000..1154975e3cc
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -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;
+}
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 07dcc959e32..bfd16487ae5 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -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 */
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 9539706468f..79a3251cdf1 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -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);
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index bf34a3b8c9f..ced3dd00a9c 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -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))
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 890b04dce91..0d2ec7c646f 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -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 */
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index 5c921d40344..7077f4a7497 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -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));
}
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 09507194969..1796bd4e928 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -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;
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index a2381a208ef..c1aca61f795 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -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;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 3a51a6a56a4..bac1e3cd8ca 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -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 */
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 936f2e5e40c..e7d0c5cdec2 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -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);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 9e98f166875..78b8c67d92c 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -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 */
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 59707f05e6f..bd1021f038a 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -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 */
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 503212201c4..890be76c49a 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -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)
diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c
index 8d4b73f1f0c..8c63d5da8fd 100644
--- a/source/blender/makesrna/intern/rna_texture_api.c
+++ b/source/blender/makesrna/intern/rna_texture_api.c
@@ -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
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index a595b121d1a..7ce1e1ab88f 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -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");
}
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index 72b54dce473..11ec327c306 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -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");
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 0ea62b0aa5f..4fc5e23e26a 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -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);
}
/* *********************************************** */
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c
index fbff8198dde..d5ae442c25f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.c
+++ b/source/blender/nodes/composite/nodes/node_composite_common.c
@@ -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.
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 3ea34dd094a..aabaf5b86de 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -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);
}
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 8cb1ebeb15f..642e4be10d7 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -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);
diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c
index aa8e8241bf8..2dd15ab1e99 100644
--- a/source/blender/nodes/shader/nodes/node_shader_common.c
+++ b/source/blender/nodes/shader/nodes/node_shader_common.c
@@ -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.
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 3ea15a316ab..603aa7ceb77 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -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);
diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c
index afb24226416..1b46b830909 100644
--- a/source/blender/nodes/texture/nodes/node_texture_common.c
+++ b/source/blender/nodes/texture/nodes/node_texture_common.c
@@ -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.
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index f0158fe72c3..67ed90c79eb 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -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);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index d10c8c843e8..2212499d842 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -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
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index bcdfe020e1a..0394d732ae3 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -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;
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index e35b3e53f5b..cf1fae81eb5 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -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)
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 40f1701e44a..810e9b6ddfb 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -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);
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 8fc224fba6f..6ba178cbb2f 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -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
}
}
}
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
index 271d5067dd9..934f2a8dd87 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -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);
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index e60b380e95c..41c0850a779 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -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 */
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 395e2048cb7..f14d73cb990 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -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);
}
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 06e343cedb2..7c76ab01e93 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -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);
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 6c7b515c095..f24243fcdfc 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -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);