[SCM] blender/upstream: Imported Upstream version 2.67b

mfv-guest at users.alioth.debian.org mfv-guest at users.alioth.debian.org
Wed Jun 5 09:47:15 UTC 2013


The following commit has been merged in the upstream branch:
commit 595a41d6c41f70c90de2a2e66d306aeba550f669
Author: Matteo F. Vescovi <mfv.debian at gmail.com>
Date:   Wed Jun 5 11:44:03 2013 +0200

    Imported Upstream version 2.67b

diff --git a/intern/smoke/extern/smoke_API.h b/intern/smoke/extern/smoke_API.h
index 98c63f0..08dbded 100644
--- a/intern/smoke/extern/smoke_API.h
+++ b/intern/smoke/extern/smoke_API.h
@@ -74,7 +74,7 @@ size_t smoke_get_index2d(int x, int max_x, int y);
 void smoke_dissolve(struct FLUID_3D *fluid, int speed, int log);
 
 // wavelet turbulence functions
-struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, int use_fire, int use_colors);
+struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, const char *noisefile_path, int use_fire, int use_colors);
 void smoke_turbulence_free(struct WTURBULENCE *wt);
 void smoke_turbulence_step(struct WTURBULENCE *wt, struct FLUID_3D *fluid);
 
@@ -89,7 +89,7 @@ float *smoke_turbulence_get_fuel(struct WTURBULENCE *wt);
 float *smoke_turbulence_get_react(struct WTURBULENCE *wt);
 void smoke_turbulence_get_res(struct WTURBULENCE *wt, int *res);
 int smoke_turbulence_get_cells(struct WTURBULENCE *wt);
-void smoke_turbulence_set_noise(struct WTURBULENCE *wt, int type);
+void smoke_turbulence_set_noise(struct WTURBULENCE *wt, int type, const char *noisefile_path);
 void smoke_initWaveletBlenderRNA(struct WTURBULENCE *wt, float *strength);
 void smoke_dissolve_wavelet(struct WTURBULENCE *wt, int speed, int log);
 
diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp
index efc6c19..3d712d2 100644
--- a/intern/smoke/intern/WTURBULENCE.cpp
+++ b/intern/smoke/intern/WTURBULENCE.cpp
@@ -51,7 +51,7 @@ static const float persistence = 0.56123f;
 //////////////////////////////////////////////////////////////////////
 // constructor
 //////////////////////////////////////////////////////////////////////
-WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors)
+WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, const char *noisefile_path, int init_fire, int init_colors)
 {
 	// if noise magnitude is below this threshold, its contribution
 	// is negilgible, so stop evaluating new octaves
@@ -131,15 +131,7 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no
 	
 	// noise tiles
 	_noiseTile = new float[noiseTileSize * noiseTileSize * noiseTileSize];
-	/*
-	std::string noiseTileFilename = std::string("noise.wavelets");
-	generateTile_WAVELET(_noiseTile, noiseTileFilename);
-	*/
-	setNoise(noisetype);
-	/*
-	std::string noiseTileFilename = std::string("noise.fft");
-	generatTile_FFT(_noiseTile, noiseTileFilename);
-	*/
+	setNoise(noisetype, noisefile_path);
 }
 
 void WTURBULENCE::initFire()
@@ -216,13 +208,13 @@ WTURBULENCE::~WTURBULENCE() {
 // type (1<<1) = FFT / 4
 // type (1<<2) = curl / 8
 //////////////////////////////////////////////////////////////////////
-void WTURBULENCE::setNoise(int type)
+void WTURBULENCE::setNoise(int type, const char *noisefile_path)
 {
 	if(type == (1<<1)) // FFT
 	{
 #ifdef WITH_FFTW3
 		// needs fft
-		std::string noiseTileFilename = std::string("noise.fft");
+		std::string noiseTileFilename = std::string(noisefile_path) + std::string("noise.fft");
 		generatTile_FFT(_noiseTile, noiseTileFilename);
 		return;
 #else
@@ -237,7 +229,7 @@ void WTURBULENCE::setNoise(int type)
 	}
 #endif
 
-	std::string noiseTileFilename = std::string("noise.wavelets");
+	std::string noiseTileFilename = std::string(noisefile_path) + std::string("noise.wavelets");
 	generateTile_WAVELET(_noiseTile, noiseTileFilename);
 }
 
diff --git a/intern/smoke/intern/WTURBULENCE.h b/intern/smoke/intern/WTURBULENCE.h
index 4e76466..3663532 100644
--- a/intern/smoke/intern/WTURBULENCE.h
+++ b/intern/smoke/intern/WTURBULENCE.h
@@ -36,7 +36,7 @@ struct WTURBULENCE
 {
 	public:
 		// both config files can be NULL, altCfg might override values from noiseCfg
-		WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors);
+		WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, const char *noisefile_path, int init_fire, int init_colors);
 
 		/// destructor
 		virtual ~WTURBULENCE();
@@ -44,7 +44,7 @@ struct WTURBULENCE
 		void initFire();
 		void initColors(float init_r, float init_g, float init_b);
 		
-		void setNoise(int type);
+		void setNoise(int type, const char *noisefile_path);
 		void initBlenderRNA(float *strength);
 
 		// step more readable version -- no rotation correction
diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp
index 67f1ea2..e25dff0 100644
--- a/intern/smoke/intern/smoke_API.cpp
+++ b/intern/smoke/intern/smoke_API.cpp
@@ -44,10 +44,10 @@ extern "C" FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, i
 	return fluid;
 }
 
-extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, int use_fire, int use_colors)
+extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, const char *noisefile_path, int use_fire, int use_colors)
 {
 	if (amplify)
-		return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype, use_fire, use_colors);
+		return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype, noisefile_path, use_fire, use_colors);
 	else 
 		return NULL;
 }
@@ -436,9 +436,9 @@ extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid)
 }
 #endif
 
-extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
+extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type, const char *noisefile_path)
 {
-	wt->setNoise(type);
+	wt->setNoise(type, noisefile_path);
 }
 
 extern "C" void flame_get_spectrum(unsigned char *spec, int width, float t1, float t2)
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 440cd65..01d903c 100644
Binary files a/release/datafiles/splash.png and b/release/datafiles/splash.png differ
diff --git a/release/scripts/addons/node_efficiency_tools.py b/release/scripts/addons/node_efficiency_tools.py
index eef13bb..e0d38f3 100644
--- a/release/scripts/addons/node_efficiency_tools.py
+++ b/release/scripts/addons/node_efficiency_tools.py
@@ -19,8 +19,8 @@
 bl_info = {
     'name': "Nodes Efficiency Tools",
     'author': "Bartek Skorupa",
-    'version': (2, 27),
-    'blender': (2, 6, 6),
+    'version': (2, 31),
+    'blender': (2, 6, 7),
     'location': "Node Editor Properties Panel (Ctrl-SPACE)",
     'description': "Nodes Efficiency Tools",
     'warning': "",
@@ -32,6 +32,7 @@ bl_info = {
 import bpy
 from bpy.types import Operator, Panel, Menu
 from bpy.props import FloatProperty, EnumProperty, BoolProperty
+from mathutils import Vector
 
 #################
 # rl_outputs:
@@ -299,7 +300,12 @@ class MergeNodes(Operator, NodeToolBase):
                 last_add = nodes[count_before]
                 # add links from last_add to all links 'to_socket' of out links of first selected.
                 for fs_link in first_selected.outputs[0].links:
-                    links.new(last_add.outputs[0], fs_link.to_socket)
+                    # Prevent cyclic dependencies when nodes to be marged are linked to one another.
+                    # Create list of invalid indexes.
+                    invalid_i = [n[0] for n in (selected_mix + selected_math + selected_shader)]
+                    # Link only if "to_node" index not in invalid indexes list.
+                    if fs_link.to_node not in [nodes[i] for i in invalid_i]:
+                        links.new(last_add.outputs[0], fs_link.to_socket)
                 # add link from "first" selected and "first" add node
                 links.new(first_selected.outputs[0], nodes[count_after - 1].inputs[first])
                 # add links between added ADD nodes and between selected and ADD nodes
@@ -1091,6 +1097,75 @@ class SelectParentChildren(Operator, NodeToolBase):
         return {'FINISHED'}
 
 
+class DetachOutputs(Operator, NodeToolBase):
+    bl_idname = "node.detach_outputs"
+    bl_label = "Detach Outputs"
+    bl_options = {'REGISTER', 'UNDO'}
+    
+    def execute(self, context):
+        nodes, links = get_nodes_links(context)
+        selected = context.selected_nodes
+        bpy.ops.node.duplicate_move_keep_inputs()
+        new_nodes = context.selected_nodes
+        bpy.ops.node.select_all(action="DESELECT")
+        for node in selected:
+            node.select = True
+        bpy.ops.node.delete_reconnect()
+        for new_node in new_nodes:
+            new_node.select = True
+        bpy.ops.transform.translate('INVOKE_DEFAULT')
+        
+        return {'FINISHED'}
+
+
+class LinkToOutputNode(Operator, NodeToolBase):
+    bl_idname = "node.link_to_output_node"
+    bl_label = "Link to Output Node"
+    bl_options = {'REGISTER', 'UNDO'}
+    
+    @classmethod
+    def poll(cls, context):
+        space = context.space_data
+        valid = False
+        if (space.type == 'NODE_EDITOR' and
+                space.node_tree is not None and
+                context.active_node is not None and
+                ):
+            valid = True
+        return valid
+    
+    def execute(self, context):
+        nodes, links = get_nodes_links(context)
+        active = nodes.active
+        output_node = None
+        for node in nodes:
+            if (node.type == 'OUTPUT_MATERIAL' or\
+                    node.type == 'OUTPUT_WORLD' or\
+                    node.type == 'OUTPUT_LAMP' or\
+                    node.type == 'COMPOSITE'):
+                output_node = node
+                break
+        if not output_node:
+            bpy.ops.node.select_all(action="DESELECT")
+            type = context.space_data.tree_type
+            print(type)
+            if type == 'ShaderNodeTree':
+                output_node = nodes.new('ShaderNodeOutputMaterial')
+            elif type == 'CompositorNodeTree':
+                output_node = nodes.new('CompositorNodeComposite')
+            output_node.location = active.location + Vector((300.0, 0.0))
+            nodes.active = output_node
+        if (output_node and active.outputs):
+            output_index = 0
+            for i, output in enumerate(active.outputs):
+                if output.type == output_node.inputs[0].type:
+                    output_index = i
+                    break
+            links.new(active.outputs[output_index], output_node.inputs[0])
+
+        return {'FINISHED'}
+
+
 #############################################################
 #  P A N E L S
 #############################################################
@@ -1113,9 +1188,11 @@ class EfficiencyToolsPanel(Panel, NodeToolBase):
         box.menu(NodeAlignMenu.bl_idname, text="Align Nodes (Shift =)")
         box.menu(CopyToSelectedMenu.bl_idname, text="Copy to Selected (Shift-C)")
         box.operator(NodesClearLabel.bl_idname).option = True
+        box.operator(DetachOutputs.bl_idname)
         box.menu(AddReroutesMenu.bl_idname, text="Add Reroutes ( / )")
         box.menu(NodesSwapMenu.bl_idname, text="Swap Nodes (Shift-S)")
         box.menu(LinkActiveToSelectedMenu.bl_idname, text="Link Active To Selected ( \\ )")
+        box.operator(LinkToOutputNode.bl_idname)
 
 
 #############################################################
@@ -1136,9 +1213,11 @@ class EfficiencyToolsMenu(Menu, NodeToolBase):
         layout.menu(NodeAlignMenu.bl_idname, text="Align Nodes")
         layout.menu(CopyToSelectedMenu.bl_idname, text="Copy to Selected")
         layout.operator(NodesClearLabel.bl_idname).option = True
+        layout.operator(DetachOutputs.bl_idname)
         layout.menu(AddReroutesMenu.bl_idname, text="Add Reroutes")
         layout.menu(NodesSwapMenu.bl_idname, text="Swap Nodes")
         layout.menu(LinkActiveToSelectedMenu.bl_idname, text="Link Active To Selected")
+        layout.operator(LinkToOutputNode.bl_idname)
 
 
 class MergeNodesMenu(Menu, NodeToolBase):
@@ -1510,12 +1589,19 @@ kmi_defs = (
     (ChangeMixFactor.bl_idname, 'ONE', True, True, True, (('option', 1.0),)),
     # CLEAR LABEL (Alt L)
     (NodesClearLabel.bl_idname, 'L', False, False, True, (('option', False),)),
+    # DETACH OUTPUTS (Alt Shift D)
+    (DetachOutputs.bl_idname, 'D', False, True, True, None),
+    # LINK TO OUTPUT NODE (O)
+    (LinkToOutputNode.bl_idname, 'O', False, False, False, None),
     # SELECT PARENT/CHILDREN
     # Select Children
     (SelectParentChildren.bl_idname, 'RIGHT_BRACKET', False, False, False, (('option', 'CHILD'),)),
     # Select Parent
     (SelectParentChildren.bl_idname, 'LEFT_BRACKET', False, False, False, (('option', 'PARENT'),)),
+    # Add Texture Setup
     (NodesAddTextureSetup.bl_idname, 'T', True, False, False, None),
+    # Copy Label from active to selected
+    (NodesCopyLabel.bl_idname, 'V', False, True, False, (('option', 'FROM_ACTIVE'),)),
     # MENUS
     ('wm.call_menu', 'SPACE', True, False, False, (('name', EfficiencyToolsMenu.bl_idname),)),
     ('wm.call_menu', 'SLASH', False, False, False, (('name', AddReroutesMenu.bl_idname),)),
diff --git a/release/scripts/modules/nodeitems_utils.py b/release/scripts/modules/nodeitems_utils.py
index 7ab5d8b..259c119 100644
--- a/release/scripts/modules/nodeitems_utils.py
+++ b/release/scripts/modules/nodeitems_utils.py
@@ -26,27 +26,28 @@ class NodeCategory():
     def poll(cls, context):
         return True
 
-    @property
-    def items(self):
-        if hasattr(self, '_items'):
-            return self._items
-        elif hasattr(self, '_itemfunc'):
-            return self._itemfunc(self)
-
-    def __init__(self, identifier, name, description="", items=[]):
+    def __init__(self, identifier, name, description="", items=None):
         self.identifier = identifier
         self.name = name
         self.description = description
-        if callable(items):
-            self._itemfunc = items
+
+        if items is None:
+            self.items = lambda context: []
+        elif callable(items):
+            self.items = items
         else:
-            self._items = items
+            def items_gen(context):
+                for item in items:
+                    if item.poll is None or item.poll(context):
+                        yield item
+            self.items = items_gen
 
 class NodeItem():
-    def __init__(self, nodetype, label=None, settings={}):
+    def __init__(self, nodetype, label=None, settings={}, poll=None):
         self.nodetype = nodetype
         self._label = label
         self.settings = settings
+        self.poll = poll
 
     @property
     def label(self):
@@ -69,7 +70,7 @@ def register_node_categories(identifier, cat_list):
         layout = self.layout
         col = layout.column()
         default_context = bpy.app.translations.contexts.default
-        for item in self.category.items:
+        for item in self.category.items(context):
             op = col.operator("node.add_node", text=item.label, text_ctxt=default_context)
             op.type = item.nodetype
             op.use_transform = True
diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py
index 6c2b64a..592e91d 100644
--- a/release/scripts/presets/keyconfig/3dsmax.py
+++ b/release/scripts/presets/keyconfig/3dsmax.py
@@ -82,7 +82,7 @@ kmi = km.keymap_items.new('info.reports_display_update', 'TIMER_REPORT', 'ANY',
 km = kc.keymaps.new('Screen', space_type='EMPTY', region_type='WINDOW', modal=False)
 
 kmi = km.keymap_items.new('screen.animation_step', 'TIMER0', 'ANY', any=True)
-kmi = km.keymap_items.new('screen.region_blend', 'TIMER', 'ANY', any=True)
+kmi = km.keymap_items.new('screen.region_blend', 'TIMER_REGION', 'ANY', any=True)
 kmi = km.keymap_items.new('screen.screen_set', 'RIGHT_ARROW', 'PRESS', ctrl=True)
 kmi.properties.delta = 1
 kmi = km.keymap_items.new('screen.screen_set', 'LEFT_ARROW', 'PRESS', ctrl=True)
@@ -202,7 +202,9 @@ kmi = km.keymap_items.new('paint.face_select_linked_pick', 'L', 'PRESS')
 km = kc.keymaps.new('Weight Paint Vertex Selection', space_type='EMPTY', region_type='WINDOW', modal=False)
 
 kmi = km.keymap_items.new('paint.vert_select_all', 'A', 'PRESS', ctrl=True)
-kmi = km.keymap_items.new('paint.vert_select_inverse', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'SELECT'
+kmi = km.keymap_items.new('paint.vert_select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
 kmi = km.keymap_items.new('view3d.select_border', 'B', 'PRESS')
 kmi = km.keymap_items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', ctrl=True)
 kmi.properties.deselect = False
@@ -1032,16 +1034,8 @@ kmi = km.keymap_items.new('node.select_lasso', 'EVT_TWEAK_A', 'ANY', shift=True,
 kmi.properties.deselect = True
 kmi = km.keymap_items.new('node.link', 'LEFTMOUSE', 'PRESS')
 kmi.properties.detach = False
-kmi.properties.expose = False
 kmi = km.keymap_items.new('node.link', 'LEFTMOUSE', 'PRESS', ctrl=True)
 kmi.properties.detach = True
-kmi.properties.expose = False
-kmi = km.keymap_items.new('node.link', 'LEFTMOUSE', 'PRESS', shift=True)
-kmi.properties.detach = False
-kmi.properties.expose = True
-kmi = km.keymap_items.new('node.link', 'LEFTMOUSE', 'PRESS', shift=True, ctrl=True)
-kmi.properties.detach = True
-kmi.properties.expose = True
 kmi = km.keymap_items.new('node.resize', 'LEFTMOUSE', 'PRESS')
 kmi = km.keymap_items.new('node.add_reroute', 'LEFTMOUSE', 'PRESS', shift=True)
 kmi = km.keymap_items.new('node.links_cut', 'LEFTMOUSE', 'PRESS', ctrl=True)
@@ -1088,40 +1082,25 @@ kmi = km.keymap_items.new('node.select_same_type_step', 'LEFT_BRACKET', 'PRESS',
 kmi.properties.prev = True
 kmi = km.keymap_items.new('node.find_node', 'F', 'PRESS', ctrl=True)
 kmi = km.keymap_items.new('node.group_make', 'G', 'PRESS', ctrl=True)
-kmi.properties.node_type = 'ShaderNodeGroup'
 kmi = km.keymap_items.new('node.group_ungroup', 'G', 'PRESS', alt=True)
-kmi.properties.node_type = 'ShaderNodeGroup'
 kmi = km.keymap_items.new('node.group_separate', 'P', 'PRESS')
-kmi.properties.node_type = 'ShaderNodeGroup'
 kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS')
-kmi.properties.node_type = 'ShaderNodeGroup'
 kmi.properties.exit = False
 kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS', shift=True)
-kmi.properties.node_type = 'ShaderNodeGroup'
 kmi.properties.exit = True
 kmi = km.keymap_items.new('node.group_make', 'G', 'PRESS', ctrl=True)
-kmi.properties.node_type = 'CompositorNodeGroup'
 kmi = km.keymap_items.new('node.group_ungroup', 'G', 'PRESS', alt=True)
-kmi.properties.node_type = 'CompositorNodeGroup'
 kmi = km.keymap_items.new('node.group_separate', 'P', 'PRESS')
-kmi.properties.node_type = 'CompositorNodeGroup'
 kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS')
-kmi.properties.node_type = 'CompositorNodeGroup'
 kmi.properties.exit = False
 kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS', shift=True)
-kmi.properties.node_type = 'CompositorNodeGroup'
 kmi.properties.exit = True
 kmi = km.keymap_items.new('node.group_make', 'G', 'PRESS', ctrl=True)
-kmi.properties.node_type = 'TextureNodeGroup'
 kmi = km.keymap_items.new('node.group_ungroup', 'G', 'PRESS', alt=True)
-kmi.properties.node_type = 'TextureNodeGroup'
 kmi = km.keymap_items.new('node.group_separate', 'P', 'PRESS')
-kmi.properties.node_type = 'TextureNodeGroup'
 kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS')
-kmi.properties.node_type = 'TextureNodeGroup'
 kmi.properties.exit = False
 kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS', shift=True)
-kmi.properties.node_type = 'TextureNodeGroup'
 kmi.properties.exit = True
 kmi = km.keymap_items.new('node.read_renderlayers', 'R', 'PRESS', ctrl=True)
 kmi = km.keymap_items.new('node.read_fullsamplelayers', 'R', 'PRESS', shift=True)
@@ -1606,9 +1585,11 @@ kmi = km.keymap_items.new('transform.rotate', 'R', 'PRESS')
 km = kc.keymaps.new('Image Paint', space_type='EMPTY', region_type='WINDOW', modal=False)
 
 kmi = km.keymap_items.new('paint.image_paint', 'LEFTMOUSE', 'PRESS')
+kmi.properties.mode = 'NORMAL'
+kmi = km.keymap_items.new('paint.image_paint', 'LEFTMOUSE', 'PRESS', ctrl=True)
+kmi.properties.mode = 'INVERT'
 kmi = km.keymap_items.new('paint.grab_clone', 'RIGHTMOUSE', 'PRESS')
 kmi = km.keymap_items.new('paint.sample_color', 'RIGHTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('paint.clone_cursor_set', 'LEFTMOUSE', 'PRESS', ctrl=True)
 kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS')
 kmi.properties.mode = 'image_paint'
 kmi.properties.index = 0
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index cd39928..fbdb6d2 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -82,6 +82,7 @@ kmi = km.keymap_items.new('info.reports_display_update', 'TIMER', 'ANY', any=Tru
 km = kc.keymaps.new('Screen', space_type='EMPTY', region_type='WINDOW', modal=False)
 
 kmi = km.keymap_items.new('screen.animation_step', 'TIMER0', 'ANY', any=True)
+kmi = km.keymap_items.new('screen.region_blend', 'TIMER_REGION', 'ANY', any=True)
 kmi = km.keymap_items.new('screen.screen_set', 'RIGHT_ARROW', 'PRESS', ctrl=True)
 kmi.properties.delta = 1
 kmi = km.keymap_items.new('screen.screen_set', 'LEFT_ARROW', 'PRESS', ctrl=True)
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index d03b450..a2a8c99 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -1761,7 +1761,11 @@ class WM_OT_addon_install(Operator):
             return {'CANCELLED'}
 
         # create dir is if missing.
-        os.makedirs(path_addons, exist_ok=True)
+        try:
+            os.makedirs(path_addons, exist_ok=True)
+        except:
+            import traceback
+            traceback.print_exc()
 
         # Check if we are installing from a target path,
         # doing so causes 2+ addons of same name or when the same from/to
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 74b5647..bdc7a6f 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -47,18 +47,46 @@ class TextureNodeCategory(NodeCategory):
         return context.space_data.tree_type == 'TextureNodeTree'
 
 
-def compositor_node_group_items(self):
-    return [NodeItem('CompositorNodeGroup', group.name, { "node_tree" : "bpy.data.node_groups[%r]" % group.name })
-            for group in bpy.data.node_groups if group.bl_idname == 'CompositorNodeTree']
+# maps node tree type to group node type
+node_tree_group_type = {
+    'CompositorNodeTree'    : 'CompositorNodeGroup',
+    'ShaderNodeTree'        : 'ShaderNodeGroup',
+    'TextureNodeTree'       : 'TextureNodeGroup',
+    }
+# generic node group items generator for shader, compositor and texture node groups
+def node_group_items(context):
+    space = context.space_data
+    if not space:
+        return
+    ntree = space.edit_tree
+    if not ntree:
+        return
 
-# Note: node groups not distinguished by old/new shader nodes
-def shader_node_group_items(self):
-    return [NodeItem('ShaderNodeGroup', group.name, { "node_tree" : "bpy.data.node_groups[%r]" % group.name })
-            for group in bpy.data.node_groups if group.bl_idname == 'ShaderNodeTree']
+    def contains_group(nodetree, group):
+        if nodetree == group:
+            return True
+        else:
+            for node in nodetree.nodes:
+                if node.bl_idname in node_tree_group_type.values() and node.node_tree is not None:
+                    if contains_group(node.node_tree, group):
+                        return True
+        return False
 
-def texture_node_group_items(self):
-    return [NodeItem('TextureNodeGroup', group.name, { "node_tree" : "bpy.data.node_groups[%r]" % group.name })
-            for group in bpy.data.node_groups if group.bl_idname == 'TextureNodeTree']
+    for group in context.blend_data.node_groups:
+        if group.bl_idname != ntree.bl_idname:
+            continue
+        # filter out recursive groups
+        if contains_group(group, ntree):
+            continue
+
+        yield NodeItem(node_tree_group_type[group.bl_idname], group.name, { "node_tree" : "bpy.data.node_groups[%r]" % group.name })
+
+# only show input/output nodes inside node groups
+def group_input_output_item_poll(context):
+    space = context.space_data
+    if space.edit_tree in bpy.data.node_groups.values():
+        return True
+    return False
 
 
 # All standard node categories currently used in nodes.
@@ -73,9 +101,11 @@ shader_node_categories = [
         NodeItem("ShaderNodeTexture"),
         NodeItem("ShaderNodeGeometry"),
         NodeItem("ShaderNodeExtendedMaterial"),
+        NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
         ]),
     ShaderOldNodeCategory("SH_OUTPUT", "Output", items=[
         NodeItem("ShaderNodeOutput"),
+        NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
         ]),
     ShaderOldNodeCategory("SH_OP_COLOR", "Color", items=[
         NodeItem("ShaderNodeMixRGB"),
@@ -99,7 +129,7 @@ shader_node_categories = [
         ]),
     ShaderOldNodeCategory("SH_SCRIPT", "Script", items=[
         ]),
-    ShaderOldNodeCategory("SH_GROUP", "Group", items=shader_node_group_items),
+    ShaderOldNodeCategory("SH_GROUP", "Group", items=node_group_items),
     ShaderOldNodeCategory("SH_LAYOUT", "Layout", items=[
         NodeItem("NodeFrame"),
         ]),
@@ -119,11 +149,13 @@ shader_node_categories = [
         NodeItem("ShaderNodeHairInfo"),
         NodeItem("ShaderNodeParticleInfo"),
         NodeItem("ShaderNodeCameraData"),
+        NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
         ]),
     ShaderNewNodeCategory("SH_NEW_OUTPUT", "Output", items=[
         NodeItem("ShaderNodeOutputMaterial"),
         NodeItem("ShaderNodeOutputLamp"),
         NodeItem("ShaderNodeOutputWorld"),
+        NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
         ]),
     ShaderNewNodeCategory("SH_NEW_SHADER", "Shader", items=[
         NodeItem("ShaderNodeMixShader"),
@@ -182,7 +214,7 @@ shader_node_categories = [
     ShaderNewNodeCategory("SH_NEW_SCRIPT", "Script", items=[
         NodeItem("ShaderNodeScript"),
         ]),
-    ShaderNewNodeCategory("SH_NEW_GROUP", "Group", items=shader_node_group_items),
+    ShaderNewNodeCategory("SH_NEW_GROUP", "Group", items=node_group_items),
     ShaderNewNodeCategory("SH_NEW_LAYOUT", "Layout", items=[
         NodeItem("NodeFrame"),
         ]),
@@ -201,6 +233,7 @@ compositor_node_categories = [
         NodeItem("CompositorNodeBokehImage"),
         NodeItem("CompositorNodeTime"),
         NodeItem("CompositorNodeTrackPos"),
+        NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
         ]),
     CompositorNodeCategory("CMP_OUTPUT", "Output", items = [
         NodeItem("CompositorNodeComposite"),
@@ -208,6 +241,7 @@ compositor_node_categories = [
         NodeItem("CompositorNodeSplitViewer"),
         NodeItem("CompositorNodeOutputFile"),
         NodeItem("CompositorNodeLevels"),
+        NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
         ]),
     CompositorNodeCategory("CMP_OP_COLOR", "Color", items = [
         NodeItem("CompositorNodeMixRGB"),
@@ -287,7 +321,7 @@ compositor_node_categories = [
         NodeItem("CompositorNodeTransform"),
         NodeItem("CompositorNodeStabilize"),
         ]),
-    CompositorNodeCategory("CMP_GROUP", "Group", items=compositor_node_group_items),
+    CompositorNodeCategory("CMP_GROUP", "Group", items=node_group_items),
     CompositorNodeCategory("CMP_LAYOUT", "Layout", items = [
         NodeItem("NodeFrame"),
         NodeItem("CompositorNodeSwitch"),
@@ -301,10 +335,12 @@ texture_node_categories = [
         NodeItem("TextureNodeCoordinates"),
         NodeItem("TextureNodeTexture"),
         NodeItem("TextureNodeImage"),
+        NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
         ]),
     TextureNodeCategory("TEX_OUTPUT", "Output", items = [
         NodeItem("TextureNodeOutput"),
         NodeItem("TextureNodeViewer"),
+        NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
         ]),
     TextureNodeCategory("TEX_OP_COLOR", "Color", items = [
         NodeItem("TextureNodeMixRGB"),
@@ -342,7 +378,7 @@ texture_node_categories = [
         NodeItem("TextureNodeTranslate"),
         NodeItem("TextureNodeRotate"),
         ]),
-    TextureNodeCategory("TEX_GROUP", "Group", items=texture_node_group_items),
+    TextureNodeCategory("TEX_GROUP", "Group", items=node_group_items),
     TextureNodeCategory("TEX_LAYOUT", "Layout", items = [
         NodeItem("NodeFrame"),
         ]),
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index bedd3f9..3ccee34 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -50,7 +50,7 @@ extern "C" {
 
 /* used by packaging tools */
 /* can be left blank, otherwise a,b,c... etc with no quotes */
-#define BLENDER_VERSION_CHAR    a
+#define BLENDER_VERSION_CHAR    b
 /* alpha/beta/rc/release, docs use this */
 #define BLENDER_VERSION_CYCLE   release
 
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 2b7a419..c8cd65e 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -1597,7 +1597,15 @@ void paste_matcopybuf(Material *ma)
 		mtex = ma->mtex[a];
 		if (mtex) {
 			ma->mtex[a] = MEM_dupallocN(mtex);
-			if (mtex->tex) id_us_plus((ID *)mtex->tex);
+			if (mtex->tex) {
+				/* first check this is in main (we may have loaded another file) [#35500] */
+				if (BLI_findindex(&G.main->tex, mtex->tex) != -1) {
+					id_us_plus((ID *)mtex->tex);
+				}
+				else {
+					ma->mtex[a]->tex = NULL;
+				}
+			}
 		}
 	}
 
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index c1f1ca0..0e945dd 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -860,6 +860,12 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob)
 	MEM_freeN(origco);
 	cddm->release(cddm);
 
+	/* Vertices were moved around, need to update normals after all the vertices are updated
+	 * Probably this is possible to do in the loop above, but this is rather tricky because
+	 * we don't know all needed vertices' coordinates there yet.
+	 */
+	BKE_mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL);
+
 	/* subdivide the mesh to highest level without displacements */
 	cddm = CDDM_from_mesh(me, NULL);
 	DM_set_only_copy(cddm, CD_MASK_BAREMESH);
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index 7f95782..1415eb0 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -149,7 +149,7 @@ char *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_t
 		}
 	}
 	else {
-		memset(dg_selection, FALSE, sizeof(char) * defbase_tot);
+		memset(dg_selection, FALSE, sizeof(*dg_selection) * defbase_tot);
 	}
 
 	return dg_selection;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 1067abf..a115d58 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4100,6 +4100,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
 {
 	ParticleSystem *psys = sim->psys;
 	ParticleSettings *part=psys->part;
+	RNG *rng;
 	BoidBrainData bbd;
 	ParticleTexture ptex;
 	PARTICLE_P;
@@ -4127,6 +4128,8 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
 	}
 
 	BLI_srandom(31415926 + (int)cfra + psys->seed);
+	/* for now do both, boids us 'rng' */
+	rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed);
 
 	psys_update_effectors(sim);
 
@@ -4143,6 +4146,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
 			bbd.cfra = cfra;
 			bbd.dfra = dfra;
 			bbd.timestep = timestep;
+			bbd.rng = rng;
 
 			psys_update_particle_tree(psys, cfra);
 
@@ -4326,6 +4330,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
 	}
 
 	free_collider_cache(&sim->colliders);
+	BLI_rng_free(rng);
 }
 static void update_children(ParticleSimulationData *sim)
 {
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index f0c1542..3a3955a 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -146,7 +146,7 @@ struct SmokeModifierData;
 #else /* WITH_SMOKE */
 
 /* Stubs to use when smoke is disabled */
-struct WTURBULENCE *smoke_turbulence_init(int *UNUSED(res), int UNUSED(amplify), int UNUSED(noisetype), int UNUSED(use_fire), int UNUSED(use_colors)) { return NULL; }
+struct WTURBULENCE *smoke_turbulence_init(int *UNUSED(res), int UNUSED(amplify), int UNUSED(noisetype), const char *UNUSED(noisefile_path), int UNUSED(use_fire), int UNUSED(use_colors)) { return NULL; }
 //struct FLUID_3D *smoke_init(int *UNUSED(res), float *UNUSED(dx), float *UNUSED(dtdef), int UNUSED(use_heat), int UNUSED(use_fire), int UNUSED(use_colors)) { return NULL; }
 void smoke_free(struct FLUID_3D *UNUSED(fluid)) {}
 float *smoke_get_density(struct FLUID_3D *UNUSED(fluid)) { return NULL; }
@@ -196,7 +196,7 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[
 		sds->wt = NULL;
 		return;
 	}
-	sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, use_fire, use_colors);
+	sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BLI_temporary_dir(), use_fire, use_colors);
 	sds->res_wt[0] = res[0] * (sds->amplify + 1);
 	sds->res_wt[1] = res[1] * (sds->amplify + 1);
 	sds->res_wt[2] = res[2] * (sds->amplify + 1);
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 2cc8467..2608a79 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -675,6 +675,7 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
 			else                        vec[2] = 1.0f;
 			cross_v3_v3v3(r_plane, eve->no, vec);
 		}
+		normalize_v3(r_plane);
 	}
 	else if (ese->htype == BM_EDGE) {
 		BMEdge *eed = (BMEdge *)ese->ele;
@@ -690,74 +691,12 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
 		else {
 			sub_v3_v3v3(r_plane, eed->v1->co, eed->v2->co);
 		}
-		
+		normalize_v3(r_plane);
 	}
 	else if (ese->htype == BM_FACE) {
 		BMFace *efa = (BMFace *)ese->ele;
-		float vec[3] = {0.0f, 0.0f, 0.0f};
-		
-		/* for now, use face normal */
-
-		/* make a fake plane thats at rightangles to the normal
-		 * we cant make a crossvec from a vec thats the same as the vec
-		 * unlikely but possible, so make sure if the normal is (0, 0, 1)
-		 * that vec isn't the same or in the same direction even. */
-		if (UNLIKELY(efa->len < 3)) {
-			/* crappy fallback method */
-			if      (efa->no[0] < 0.5f)	vec[0] = 1.0f;
-			else if (efa->no[1] < 0.5f)	vec[1] = 1.0f;
-			else                        vec[2] = 1.0f;
-			cross_v3_v3v3(r_plane, efa->no, vec);
-		}
-		else {
-			if (efa->len == 3) {
-				BMVert *verts[3];
-				float lens[3];
-				float difs[3];
-				int  order[3] = {0, 1, 2};
-
-				BM_face_as_array_vert_tri(efa, verts);
-
-				lens[0] = len_v3v3(verts[0]->co, verts[1]->co);
-				lens[1] = len_v3v3(verts[1]->co, verts[2]->co);
-				lens[2] = len_v3v3(verts[2]->co, verts[0]->co);
-
-				/* find the shortest or the longest loop */
-				difs[0] = fabsf(lens[1] - lens[2]);
-				difs[1] = fabsf(lens[2] - lens[0]);
-				difs[2] = fabsf(lens[0] - lens[1]);
-
-				axis_sort_v3(difs, order);
-				sub_v3_v3v3(r_plane, verts[order[0]]->co, verts[(order[0] + 1) % 3]->co);
-			}
-			else if (efa->len == 4) {
-				BMVert *verts[4];
-				float vecA[3], vecB[3];
-
-				// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
-				BM_face_as_array_vert_quad(efa, verts);
-
-				sub_v3_v3v3(vecA, verts[3]->co, verts[2]->co);
-				sub_v3_v3v3(vecB, verts[0]->co, verts[1]->co);
-				add_v3_v3v3(r_plane, vecA, vecB);
-
-				sub_v3_v3v3(vecA, verts[0]->co, verts[3]->co);
-				sub_v3_v3v3(vecB, verts[1]->co, verts[2]->co);
-				add_v3_v3v3(vec, vecA, vecB);
-				/* use the biggest edge length */
-				if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec)) {
-					copy_v3_v3(r_plane, vec);
-				}
-			}
-			else {
-				BMLoop *l_long  = BM_face_find_longest_loop(efa);
-
-				sub_v3_v3v3(r_plane, l_long->v->co, l_long->next->v->co);
-			}
-
-		}
+		BM_face_calc_plane(efa, r_plane);
 	}
-	normalize_v3(r_plane);
 }
 
 
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 0886edc..4eaf6ac 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -292,6 +292,60 @@ float BM_face_calc_perimeter(BMFace *f)
 }
 
 /**
+ * Compute a meaningful direction along the face (use for manipulator axis).
+ * \note result isnt normalized.
+ */
+void BM_face_calc_plane(BMFace *f, float r_plane[3])
+{
+	if (f->len == 3) {
+		BMVert *verts[3];
+		float lens[3];
+		float difs[3];
+		int  order[3] = {0, 1, 2};
+
+		BM_face_as_array_vert_tri(f, verts);
+
+		lens[0] = len_v3v3(verts[0]->co, verts[1]->co);
+		lens[1] = len_v3v3(verts[1]->co, verts[2]->co);
+		lens[2] = len_v3v3(verts[2]->co, verts[0]->co);
+
+		/* find the shortest or the longest loop */
+		difs[0] = fabsf(lens[1] - lens[2]);
+		difs[1] = fabsf(lens[2] - lens[0]);
+		difs[2] = fabsf(lens[0] - lens[1]);
+
+		axis_sort_v3(difs, order);
+		sub_v3_v3v3(r_plane, verts[order[0]]->co, verts[(order[0] + 1) % 3]->co);
+	}
+	else if (f->len == 4) {
+		BMVert *verts[4];
+		float vec[3], vec_a[3], vec_b[3];
+
+		// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
+		BM_face_as_array_vert_quad(f, verts);
+
+		sub_v3_v3v3(vec_a, verts[3]->co, verts[2]->co);
+		sub_v3_v3v3(vec_b, verts[0]->co, verts[1]->co);
+		add_v3_v3v3(r_plane, vec_a, vec_b);
+
+		sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co);
+		sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co);
+		add_v3_v3v3(vec, vec_a, vec_b);
+		/* use the biggest edge length */
+		if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec)) {
+			copy_v3_v3(r_plane, vec);
+		}
+	}
+	else {
+		BMLoop *l_long  = BM_face_find_longest_loop(f);
+
+		sub_v3_v3v3(r_plane, l_long->v->co, l_long->next->v->co);
+	}
+
+	normalize_v3(r_plane);
+}
+
+/**
  * computes center of face in 3d.  uses center of bounding box.
  */
 void BM_face_calc_center_bounds(BMFace *f, float r_cent[3])
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index d857ba7..428a98e 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -35,6 +35,7 @@ int   BM_face_calc_tessellation(BMFace *f, BMLoop **r_loops, int (*r_index)[3])
 ;
 float BM_face_calc_area(BMFace *f);
 float BM_face_calc_perimeter(BMFace *f);
+void  BM_face_calc_plane(BMFace *f, float r_plane[3]);
 void  BM_face_calc_center_bounds(BMFace *f, float center[3]);
 void  BM_face_calc_center_mean(BMFace *f, float center[3]);
 void  BM_face_calc_center_mean_weighted(BMFace *f, float center[3]);
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index 363e46c..3e5652d 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -648,7 +648,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
 			} while (true);
 		}
 
-		if (owalk.is_single == false && bm_edge_is_single(l->e)) {
+		if (owalk.is_single == false && l && bm_edge_is_single(l->e)) {
 			l = NULL;
 		}
 
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index acb1001..32c8ee5 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -409,6 +409,12 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
 			continue;
 		}
 
+		/* skip creating face for excluded edges see [#35503] */
+		if (BMO_slot_map_contains(slot_edges_exclude, e)) {
+			/* simply skip creating the face */
+			continue;
+		}
+
 		e_new = *(BMEdge **)BMO_iter_map_value(&siter);
 
 		if (!e_new) {
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index a0fbaae..cac63b8 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -310,6 +310,19 @@ static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3
 	return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep);
 }
 
+/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */
+static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3])
+{
+	float dir[3], len;
+
+	sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co);
+	len = normalize_v3(dir);
+	if (d > len)
+		d = len - (float)(50.0 * BEVEL_EPSILON_D);
+	copy_v3_v3(slideco, v->co);
+	madd_v3_v3fl(slideco, dir, -d);
+}
+
 /*
  * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco.
  * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of
@@ -324,13 +337,14 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
                         int on_right, float meetco[3])
 {
 	float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3],
-	      off1a[3], off1b[3], off2a[3], off2b[3], isect2[3];
+	      off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], ang;
 
 	/* get direction vectors for two offset lines */
 	sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
 	sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
 
-	if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) {
+	ang = angle_v3v3(dir1, dir2);
+	if (ang < 100.0f * BEVEL_EPSILON) {
 		/* special case: e1 and e2 are parallel; put offset point perp to both, from v.
 		 * need to find a suitable plane.
 		 * if offsets are different, we're out of luck: just use e1->offset */
@@ -344,6 +358,12 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
 		madd_v3_v3fl(off1a, norm_perp1, e1->offset);
 		copy_v3_v3(meetco, off1a);
 	}
+	else if (fabs(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) {
+		/* special case e1 and e2 are antiparallel, so bevel is into
+		 * a zero-area face.  Just make the offset point on the
+		 * common line, at offset distance from v. */
+		slide_dist(e2, v, e2->offset, meetco);
+	}
 	else {
 		/* get normal to plane where meet point should be */
 		cross_v3_v3v3(norm_v, dir2, dir1);
@@ -391,7 +411,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
 {
 	float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3],
 	      off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], co[3],
-	      f1no[3], f2no[3];
+	      f1no[3], f2no[3], ang;
 	int iret;
 
 	/* get direction vectors for two offset lines */
@@ -416,10 +436,14 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
 	madd_v3_v3fl(off2a, norm_perp2, e2->offset);
 	add_v3_v3v3(off2b, off2a, dir2);
 
-	if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) {
+	ang = angle_v3v3(dir1, dir2);
+	if (ang < 100.0f * BEVEL_EPSILON) {
 		/* lines are parallel; off1a is a good meet point */
 		copy_v3_v3(meetco, off1a);
 	}
+	else if (fabs(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) {
+		slide_dist(e2, v, e2->offset, meetco);
+	}
 	else {
 		iret = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
 		if (iret == 0) {
@@ -469,19 +493,6 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], int left, floa
 	madd_v3_v3fl(r, fdir, e->offset);
 }
 
-/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */
-static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3])
-{
-	float dir[3], len;
-
-	sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co);
-	len = normalize_v3(dir);
-	if (d > len)
-		d = len - (float)(50.0 * BEVEL_EPSILON_D);
-	copy_v3_v3(slideco, v->co);
-	madd_v3_v3fl(slideco, dir, -d);
-}
-
 /* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */
 static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3], float projco[3])
 {
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 7c0c063..cb1b55d 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -1033,7 +1033,11 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
 	Mesh *new_mesh = uid_mesh_map[*geom_uid];
 
 	BKE_mesh_assign_object(ob, new_mesh);
-	
+    BKE_mesh_calc_normals_mapping(new_mesh->mvert, new_mesh->totvert, 
+								  new_mesh->mloop, new_mesh->mpoly,
+								  new_mesh->totloop, new_mesh->totpoly,
+								  NULL, NULL, 0, NULL, NULL);
+
 	if (old_mesh->id.us == 0) BKE_libblock_free(&G.main->mesh, old_mesh);
 	
 	char layername[100];
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 08cae94..1ddde76 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1177,6 +1177,10 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
 int ED_curve_updateAnimPaths(Curve *cu)
 {
 	AnimData *adt = BKE_animdata_from_id(&cu->id);
+	EditNurb *editnurb = cu->editnurb;
+
+	if (!editnurb->keyindex)
+		return 0;
 
 	if (!curve_is_animated(cu)) return 0;
 
@@ -1416,12 +1420,14 @@ static int separate_exec(bContext *C, wmOperator *op)
 	newedit = newcu->editnurb;
 	BKE_nurbList_free(&newedit->nurbs);
 	BKE_curve_editNurb_keyIndex_free(newedit);
+	newedit->keyindex = NULL;
 
 	/* 3. move over parts from old object */
 	for (nu = oldedit->nurbs.first; nu; nu = nu1) {
 		nu1 = nu->next;
 
 		if (isNurbsel(nu)) {
+			keyIndex_delNurb(oldedit, nu);
 			BLI_remlink(&oldedit->nurbs, nu);
 			BLI_addtail(&newedit->nurbs, nu);
 		}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 22ec2c8..dc5e12d 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -2051,7 +2051,7 @@ void GPENCIL_OT_draw(wmOperatorType *ot)
 	ot->poll = gpencil_draw_poll;
 	
 	/* flags */
-	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+	ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
 	
 	/* settings for drawing */
 	ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 4cc5b0e..8307686 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1328,6 +1328,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s
 			char name_ui[MAX_ID_NAME];
 
 #if 0       /* this name is used for a string comparison and can't be modified, TODO */
+			/* if ever enabled, make name_ui be MAX_ID_NAME+1 */
 			name_uiprefix_id(name_ui, id);
 #else
 			BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui));
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 637417f..dc4ef7f 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -151,7 +151,10 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str,
 					continue;
 
 			if (BLI_strcasestr(id->name + 2, str)) {
-				char name_ui[MAX_ID_NAME];
+				/* +1 is needed because name_uiprefix_id used 3 letter prefix
+				 * followed by ID_NAME-2 characters from id->name
+				 */
+				char name_ui[MAX_ID_NAME + 1];
 				name_uiprefix_id(name_ui, id);
 
 				iconid = ui_id_icon_get((bContext *)C, id, template->preview);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 38a2644..a5d7a99 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -2184,9 +2184,12 @@ void ED_vgroup_mirror(Object *ob,
 		}
 	}
 
+	/* disabled, confusing when you have an active pose bone */
+#if 0
 	/* flip active group index */
 	if (flip_vgroups && flip_map[def_nr] >= 0)
 		ob->actdef = flip_map[def_nr] + 1;
+#endif
 
 cleanup:
 	if (flip_map) MEM_freeN(flip_map);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 02c9760..7e5f614 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -248,7 +248,8 @@ typedef struct ProjPaintState {
 	short is_ortho;
 	bool do_masking;              /* use masking during painting. Some operations such as airbrush may disable */
 	bool is_texbrush;              /* only to avoid running  */
-	bool is_maskbrush;
+	bool is_maskbrush;            /* mask brush is applied before masking */
+	bool is_maskbrush_tiled;      /* mask brush is applied after masking */
 #ifndef PROJ_DEBUG_NOSEAMBLEED
 	float seam_bleed_px;
 #endif
@@ -3845,7 +3846,14 @@ static void *do_projectpaint_thread(void *ph_v)
 							 * and never exceeds it, which gives nice smooth results. */
 							float mask_accum = projPixel->mask_accum;
 
-							mask = mask_accum + (brush_alpha * 65535.0f - mask_accum) * mask;
+							if (ps->is_maskbrush) {
+								float texmask = BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
+								CLAMP(texmask, 0.0, 1.0);
+								mask = mask_accum + (brush_alpha * texmask * 65535.0f - mask_accum) * mask;
+							}
+							else {
+								mask = mask_accum + (brush_alpha * 65535.0f - mask_accum) * mask;
+							}
 							mask_short = (unsigned short)mask;
 
 							if (mask_short > projPixel->mask_accum) {
@@ -3857,8 +3865,14 @@ static void *do_projectpaint_thread(void *ph_v)
 								continue;
 							}
 						}
-						else
+						else {
 							mask *= brush_alpha;
+							if (ps->is_maskbrush) {
+								float texmask = BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
+								CLAMP(texmask, 0.0, 1.0);
+								mask *= texmask;
+							}
+						}
 
 						if (ps->is_texbrush) {
 							MTex *mtex = &brush->mtex;
@@ -3881,7 +3895,7 @@ static void *do_projectpaint_thread(void *ph_v)
 							mask *= texrgba[3];
 						}
 
-						if (ps->is_maskbrush) {
+						if (ps->is_maskbrush_tiled) {
 							mask *= BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
 						}
 
@@ -4103,13 +4117,23 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
 		                  (brush->mtex.tex && !ELEM3(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D)))
 		                 ? false : true;
 		ps->is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true : false;
-		ps->is_maskbrush = (brush->mask_mtex.tex) ? true : false;
+		ps->is_maskbrush = false;
+		ps->is_maskbrush_tiled = false;
+		if (brush->mask_mtex.tex) {
+			if (ELEM(brush->mask_mtex.brush_map_mode, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_TILED)) {
+				ps->is_maskbrush_tiled = true;
+			}
+			else {
+				ps->is_maskbrush = true;
+			}
+		}
 	}
 	else {
 		/* brush may be NULL*/
 		ps->do_masking = false;
 		ps->is_texbrush = false;
 		ps->is_maskbrush = false;
+		ps->is_maskbrush_tiled = false;
 	}
 
 	/* sizeof(ProjPixel), since we alloc this a _lot_ */
@@ -4294,6 +4318,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
 	/* override */
 	ps.is_texbrush = false;
 	ps.is_maskbrush = false;
+	ps.is_maskbrush_tiled = false;
 	ps.do_masking = false;
 	orig_brush_size = BKE_brush_size_get(scene, ps.brush);
 	BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 6969b3b..badd49c 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -411,6 +411,7 @@ static void PAINT_OT_brush_select(wmOperatorType *ot)
 		{OB_MODE_TEXTURE_PAINT, "TEXTURE_PAINT", ICON_TPAINT_HLT, "Texture Paint", ""},
 		{0, NULL, 0, NULL, NULL}
 	};
+	PropertyRNA *prop;
 
 	/* identifiers */
 	ot->name = "Brush Select";
@@ -430,8 +431,10 @@ static void PAINT_OT_brush_select(wmOperatorType *ot)
 	RNA_def_enum(ot->srna, "weight_paint_tool", brush_vertex_tool_items, 0, "Weight Paint Tool", "");
 	RNA_def_enum(ot->srna, "texture_paint_tool", brush_image_tool_items, 0, "Texture Paint Tool", "");
 
-	RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle between two brushes rather than cycling");
-	RNA_def_boolean(ot->srna, "create_missing", 0, "Create Missing", "If the requested brush type does not exist, create a new brush");
+	prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle between two brushes rather than cycling");
+	RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+	prop = RNA_def_boolean(ot->srna, "create_missing", 0, "Create Missing", "If the requested brush type does not exist, create a new brush");
+	RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
 static wmKeyMapItem *keymap_brush_select(wmKeyMap *keymap, int paint_mode,
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index ba12543..23c8569 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -783,7 +783,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
 	Image *ima;
 	ImBuf *ibuf;
 	float zoomx, zoomy;
-	int show_viewer, show_render;
+	bool show_viewer, show_render, show_paint;
 	void *lock;
 
 	/* XXX can we do this in refresh? */
@@ -810,8 +810,9 @@ void draw_image_main(const bContext *C, ARegion *ar)
 	ima = ED_space_image(sima);
 	ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
 
-	show_viewer = (ima && ima->source == IMA_SRC_VIEWER);
-	show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT);
+	show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
+	show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
+	show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && (show_render == false));
 
 	if (show_viewer) {
 		/* use locked draw for drawing viewer image buffer since the compositor
@@ -835,7 +836,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
 		draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
 
 	/* paint helpers */
-	if (sima->mode == SI_MODE_PAINT)
+	if (show_paint)
 		draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
 
 	/* XXX integrate this code */
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index ec5c465..d0d7405 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -500,8 +500,6 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
 	/* default now: refresh node is starting preview */
 	SpaceNode *snode = sa->spacedata.first;
 	
-	ED_preview_kill_jobs(C);
-	
 	snode_set_context(C);
 
 	if (snode->nodetree) {
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 76a32a2..8ae6723 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -383,6 +383,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
 	if (block) { /* buttons */
 		uiBut *but;
 		int yi = 200;
+		const float tilt_limit = DEG2RADF(21600.0f);
 		const int buth = 20 * UI_DPI_FAC;
 		const int but_margin = 2;
 		const char *c;
@@ -459,7 +460,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
 			uiDefButR(block, NUM, 0, IFACE_("Radius"), 0, yi -= buth + but_margin, 200, buth,
 			          &data_ptr, "radius", 0, 0.0, 100.0, 1, 3, NULL);
 			uiDefButR(block, NUM, 0, IFACE_("Tilt"), 0, yi -= buth + but_margin, 200, buth,
-			          &data_ptr, "tilt", 0, -FLT_MAX, FLT_MAX, 1, 3, NULL);
+			          &data_ptr, "tilt", 0, -tilt_limit, tilt_limit, 1, 3, NULL);
 		}
 		else if (totcurvedata > 1) {
 			uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Weight:"),
@@ -470,7 +471,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
 			          &(tfp->ve_median[C_RADIUS]), 0.0, 100.0, 1, 3, TIP_("Radius of curve control points"));
 			but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Tilt:"),
 			                0, yi -= buth + but_margin, 200, buth,
-			                &(tfp->ve_median[C_TILT]), -FLT_MAX, FLT_MAX, 1, 3,
+			                &(tfp->ve_median[C_TILT]), -tilt_limit, tilt_limit, 1, 3,
 			                TIP_("Tilt of curve control points"));
 			uiButSetUnitType(but, PROP_UNIT_ROTATION);
 		}
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 4be4328..fa30f5a 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -40,6 +40,8 @@
 
 #include "BLI_math_vector.h"
 
+#include "BKE_screen.h"
+
 #include "ED_view3d.h"  /* own include */
 
 #define BL_NEAR_CLIP 0.001
@@ -410,8 +412,14 @@ void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float
 		}
 	}
 	else {
-		const float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f;
-		const float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f;
+		float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f;
+		float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f;
+		if (rv3d->persp == RV3D_CAMOB) {
+			/* ortho camera needs offset applied */
+			const float zoomfac = BKE_screen_view3d_zoom_to_fac((float)rv3d->camzoom) * 4.0f;
+			dx += rv3d->camdx * zoomfac;
+			dy += rv3d->camdy * zoomfac;
+		}
 		line_sta[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0];
 		line_sta[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1];
 		line_sta[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2];
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 7552e09..3bbb2b5 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -64,6 +64,8 @@
 #include "ED_screen.h"
 #include "ED_armature.h"
 
+#include "RE_engine.h"
+
 #ifdef WITH_GAMEENGINE
 #include "BL_System.h"
 #endif
@@ -1217,6 +1219,13 @@ static void restore_localviewdata(ScrArea *sa, int free)
 					rv3d->localvd = NULL;
 				}
 			}
+
+			if (v3d->drawtype != OB_RENDER) {
+				if (rv3d->render_engine) {
+					RE_engine_free(rv3d->render_engine);
+					rv3d->render_engine = NULL;
+				}
+			}
 		}
 	}
 }
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index ae8193d..f38eee1 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -307,7 +307,7 @@ static void transformops_loopsel_hack(bContext *C, wmOperator *op)
 			int mesh_select_mode[3];
 			PropertyRNA *prop = RNA_struct_find_property(op_prev->ptr, "mesh_select_mode_init");
 
-			if (RNA_property_is_set(op_prev->ptr, prop)) {
+			if (prop && RNA_property_is_set(op_prev->ptr, prop)) {
 				ToolSettings *ts = scene->toolsettings;
 				short selectmode_orig;
 
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 6090c2f..0fa324e 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -599,10 +599,8 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
 
 					BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
 						if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+							BM_face_calc_plane(efa, vec);
 							add_v3_v3(normal, efa->no);
-							sub_v3_v3v3(vec,
-							            BM_FACE_FIRST_LOOP(efa)->v->co,
-							            BM_FACE_FIRST_LOOP(efa)->next->v->co);
 							add_v3_v3(plane, vec);
 						}
 					}
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp
index cc21ba0..a5701ea 100644
--- a/source/blender/freestyle/intern/geometry/FitCurve.cpp
+++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp
@@ -376,6 +376,12 @@ static Vector2 ComputeCenterTangent(Vector2 *d, int center)
 	tHatCenter[0] = (V1[0] + V2[0]) / 2.0;
 	tHatCenter[1] = (V1[1] + V2[1]) / 2.0;
 	tHatCenter = *V2Normalize(&tHatCenter);
+
+	/* avoid numerical singularity in the special case when V1 == -V2 */
+	if (V2Length(&tHatCenter) < M_EPSILON) {
+		tHatCenter = *V2Normalize(&V1);
+	}
+
 	return tHatCenter;
 }
 
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
index 8199f5b..48aaa2e 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -186,6 +186,7 @@ static PyObject *Stroke_insert_vertex(BPy_Stroke *self, PyObject *args, PyObject
 	{
 		return NULL;
 	}
+	((BPy_StrokeVertex *)py_sv)->py_cp.py_if0D.borrowed = 1; /* make the wrapped StrokeVertex internal */
 	StrokeVertex *sv = ((BPy_StrokeVertex *)py_sv)->sv;
 	StrokeInternal::StrokeVertexIterator sv_it(*(((BPy_StrokeVertexIterator *)py_sv_it)->sv_it));
 	self->s->InsertVertex(sv, sv_it);
diff --git a/source/blender/freestyle/intern/system/PseudoNoise.cpp b/source/blender/freestyle/intern/system/PseudoNoise.cpp
index b70564d..538460d 100644
--- a/source/blender/freestyle/intern/system/PseudoNoise.cpp
+++ b/source/blender/freestyle/intern/system/PseudoNoise.cpp
@@ -46,7 +46,7 @@ void PseudoNoise::init(long seed)
 real PseudoNoise::linearNoise(real x)
 {
 	real tmp;
-	int i = modf(x, &tmp) * NB_VALUE_NOISE;
+	int i = abs(modf(x, &tmp)) * NB_VALUE_NOISE;
 	real x1 = _values[i], x2 = _values[(i + 1) % NB_VALUE_NOISE];
 	real t = modf(x * NB_VALUE_NOISE, &tmp);
 	return x1 * (1 - t) + x2 * t;
@@ -64,7 +64,7 @@ static real LanczosWindowed(real t)
 real PseudoNoise::smoothNoise(real x)
 {
 	real tmp;
-	int i = modf(x, &tmp) * NB_VALUE_NOISE;
+	int i = abs(modf(x, &tmp)) * NB_VALUE_NOISE;
 	int h = i - 1;
 	if (h < 0) {
 		h = NB_VALUE_NOISE + h;
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index b024870..a793286 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -300,6 +300,9 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
 			}
 		}
 
+		/* note material must be bound before setting uniforms */
+		GPU_pass_bind(material->pass, time, mipmap);
+
 		/* handle per material built-ins */
 		if (material->builtins & GPU_VIEW_MATRIX) {
 			GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat);
@@ -308,7 +311,6 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
 			GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv);
 		}
 
-		GPU_pass_bind(material->pass, time, mipmap);
 		GPU_pass_update_uniforms(material->pass);
 
 		material->bound = 1;
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index c127a7b..a5e877c 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -672,7 +672,7 @@ void IMB_colormanagement_display_settings_from_ctx(const bContext *C,
 	*view_settings_r = &scene->view_settings;
 	*display_settings_r = &scene->display_settings;
 
-	if (sima) {
+	if (sima && sima->image) {
 		if ((sima->image->flag & IMA_VIEW_AS_RENDER) == 0)
 			*view_settings_r = NULL;
 	}
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 0d354b0..c973454 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -32,6 +32,7 @@
 #include "DNA_scene_types.h"
 
 #include "BLI_utildefines.h"
+#include "BLI_math.h"
 
 #include "BKE_font.h"
 
@@ -688,6 +689,7 @@ static void rna_def_bpoint(BlenderRNA *brna)
 {
 	StructRNA *srna;
 	PropertyRNA *prop;
+	const float tilt_limit = DEG2RADF(21600.0f);
 
 	srna = RNA_def_struct(brna, "SplinePoint", NULL);
 	RNA_def_struct_sdna(srna, "BPoint");
@@ -720,7 +722,8 @@ static void rna_def_bpoint(BlenderRNA *brna)
 	/* Number values */
 	prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_ANGLE);
 	RNA_def_property_float_sdna(prop, NULL, "alfa");
-	/*RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);*/
+	RNA_def_property_range(prop, -tilt_limit, tilt_limit);
+	RNA_def_property_ui_range(prop, -tilt_limit, tilt_limit, 0.1, 3);
 	RNA_def_property_ui_text(prop, "Tilt", "Tilt in 3D View");
 	RNA_def_property_update(prop, 0, "rna_Curve_update_data");
 
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index c6a8e26..aae1581 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -121,6 +121,7 @@ EnumPropertyItem event_timer_type_items[] = {
 	{TIMERJOBS, "TIMER_JOBS", 0, "Timer Jobs", ""},
 	{TIMERAUTOSAVE, "TIMER_AUTOSAVE", 0, "Timer Autosave", ""},
 	{TIMERREPORT, "TIMER_REPORT", 0, "Timer Report", ""},
+	{TIMERREGION, "TIMERREGION", 0, "Timer Region", ""},
 	{0, NULL, 0, NULL, NULL}
 };
 
@@ -334,6 +335,7 @@ EnumPropertyItem event_type_items[] = {
 	{TIMERJOBS, "TIMER_JOBS", 0, "Timer Jobs", ""},
 	{TIMERAUTOSAVE, "TIMER_AUTOSAVE", 0, "Timer Autosave", ""},
 	{TIMERREPORT, "TIMER_REPORT", 0, "Timer Report", ""},
+	{TIMERREGION, "TIMER_REGION", 0, "Timer Region", ""},
 	{0, "", 0, NULL, NULL},
 	{NDOF_MOTION, "NDOF_MOTION", 0, "NDOF Motion", ""},
 	/* buttons on all 3dconnexion devices */
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 841dde3..acc5090 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -228,7 +228,7 @@ void register_node_tree_type_cmp(void)
 	strcpy(tt->idname, "CompositorNodeTree");
 	strcpy(tt->ui_name, "Compositing");
 	tt->ui_icon = 0;	/* defined in drawnode.c */
-	strcpy(tt->ui_description, "");
+	strcpy(tt->ui_description, "Compositing nodes");
 	
 	tt->free_cache = free_cache;
 	tt->free_node_cache = free_node_cache;
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 47d3855..ef6f375 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -170,7 +170,7 @@ void register_node_tree_type_sh(void)
 	strcpy(tt->idname, "ShaderNodeTree");
 	strcpy(tt->ui_name, "Shader");
 	tt->ui_icon = 0;	/* defined in drawnode.c */
-	strcpy(tt->ui_description, "");
+	strcpy(tt->ui_description, "Shader nodes");
 	
 	tt->foreach_nodeclass = foreach_nodeclass;
 	tt->localize = localize;
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 6636957..2cf8d03 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -170,7 +170,7 @@ void register_node_tree_type_tex(void)
 	strcpy(tt->idname, "TextureNodeTree");
 	strcpy(tt->ui_name, "Texture");
 	tt->ui_icon = 0;	/* defined in drawnode.c */
-	strcpy(tt->ui_description, "");
+	strcpy(tt->ui_description, "Texture nodes");
 	
 	tt->foreach_nodeclass = foreach_nodeclass;
 	tt->update = update;
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index c87f2df..c5e4f97 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -224,9 +224,11 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
 	}
 
 	/* keep this before interpolation [#29761] */
-	if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
-		if ((tex->imaflag & TEX_CALCALPHA) == 0) {
-			texres->talpha = TRUE;
+	if (ima) {
+		if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+			if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+				texres->talpha = TRUE;
+			}
 		}
 	}
 
@@ -1529,9 +1531,11 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
 	/* mipmap test */
 	image_mipmap_test(tex, ibuf);
 
-	if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
-		if ((tex->imaflag & TEX_CALCALPHA) == 0) {
-			texres->talpha = TRUE;
+	if (ima) {
+		if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+			if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+				texres->talpha = TRUE;
+			}
 		}
 	}
 	
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 15b8189..5e92c7b 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1636,6 +1636,15 @@ static void add_freestyle(Render *re)
 
 	actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
 
+	/* We use the same window manager for freestyle bmain as
+	 * real bmain uses. This is needed because freestyle's
+	 * bmain could be used to tag scenes for update, which
+	 * implies call of ED_render_scene_update in some cases
+	 * and that function requires proper windoew manager
+	 * to present (sergey)
+	 */
+	re->freestyle_bmain.wm = re->main->wm;
+
 	FRS_init_stroke_rendering(re);
 
 	for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 03a1785..ed4609a 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -716,9 +716,10 @@ int WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op)
 	}
 	else if (op->opm) {
 		/* for macros, check all have exec() we can call */
-		wmOperator *opm;
-		for (opm = op->opm->type->macro.first; opm; opm = opm->next) {
-			if (opm->type->exec == NULL) {
+		wmOperatorTypeMacro *otmacro;
+		for (otmacro = op->opm->type->macro.first; otmacro; otmacro = otmacro->next) {
+			wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0);
+			if (otm && otm->exec == NULL) {
 				return false;
 			}
 		}
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 5c6f85c..b02d7d9 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -634,6 +634,11 @@ static int playback_mode(int argc, const char **argv, void *UNUSED(data))
 {
 	/* not if -b was given first */
 	if (G.background == 0) {
+#ifdef WITH_FFMPEG
+		/* Setup FFmpeg with current debug flags. */
+		IMB_ffmpeg_init();
+#endif
+
 		WM_main_playanim(argc, argv); /* not the same argc and argv as before */
 		exit(0); /* 2.4x didn't do this */
 	}
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index ebe3536..2fb83d4 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -905,7 +905,7 @@ static RAS_MaterialBucket *material_from_mesh(Material *ma, MFace *mface, MTFace
 			ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol,
 				converter->GetGLSLMaterials());
 
-			if ((!ma->mode & MA_FACETEXTURE))
+			if (ma && (ma->mode & MA_FACETEXTURE) == 0)
 				converter->CacheBlenderMaterial(ma, bl_mat);
 		}
 
@@ -921,7 +921,7 @@ static RAS_MaterialBucket *material_from_mesh(Material *ma, MFace *mface, MTFace
 
 			kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL), lightlayer);
 			polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat);
-			if ((!ma->mode & MA_FACETEXTURE))
+			if (ma && (ma->mode & MA_FACETEXTURE) == 0)
 				converter->CachePolyMaterial(ma, polymat);
 		}
 	}

-- 
blender packaging



More information about the pkg-multimedia-commits mailing list