diff options
Diffstat (limited to 'release')
28 files changed, 570 insertions, 477 deletions
diff --git a/release/datafiles/LICENSE-droidsans.ttf.txt b/release/datafiles/LICENSE-droidsans.ttf.txt index 1f090edd309..ca0d6bbaea1 100644 --- a/release/datafiles/LICENSE-droidsans.ttf.txt +++ b/release/datafiles/LICENSE-droidsans.ttf.txt @@ -5,6 +5,7 @@ Blender Main I18n font ("droidsans.ttf") includes glyphs imported from the follo 3. Samyak-devanagari 4. Droid Sans Hebrew Regular 5. Droid Sans Ethiopic Regular +6. Samyak-tamil These were merged using FontForge in (approximately) the above order. For each glyph, a license of the font from which it was imported is applied. @@ -30,7 +31,7 @@ Copyright: License: Apache-2.0 See Appendix A. -(3) Samyak-devanagari +(3) Samyak-devanagari and (6) Samyak-tamil Copyright: 2005-2006, Rahul Bhalerao <b.rahul.pm@gmail.com> 2005-2006, Bageshri Salvi <sbageshri@gmail.com> 2005-2006, Pravin Satpute <pravin.d.s@gmail.com> diff --git a/release/datafiles/fonts/droidsans.ttf.gz b/release/datafiles/fonts/droidsans.ttf.gz Binary files differindex a0e7502cc1f..81683e6379f 100644 --- a/release/datafiles/fonts/droidsans.ttf.gz +++ b/release/datafiles/fonts/droidsans.ttf.gz diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png Binary files differindex 01d903c457b..9551fad2fac 100644 --- a/release/datafiles/splash.png +++ b/release/datafiles/splash.png diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend Binary files differindex 8b58493fe3a..c604d16829c 100644 --- a/release/datafiles/startup.blend +++ b/release/datafiles/startup.blend diff --git a/release/scripts/freestyle/style_modules/ChainingIterators.py b/release/scripts/freestyle/style_modules/ChainingIterators.py index 03ad837aa28..b908fad0b89 100644 --- a/release/scripts/freestyle/style_modules/ChainingIterators.py +++ b/release/scripts/freestyle/style_modules/ChainingIterators.py @@ -24,6 +24,8 @@ from freestyle import AdjacencyIterator, ChainingIterator, ExternalContourUP1D, Nature, TVertex from freestyle import ContextFunctions as CF +import bpy + ## the natural chaining iterator ## It follows the edges of same nature following the topology of ## objects with preseance on silhouettes, then borders, @@ -212,7 +214,7 @@ class pySketchyChainSilhouetteIterator(ChainingIterator): visitNext = 1 break if visitNext != 0: - break + break count = count+1 winner = ve it.increment() @@ -238,14 +240,22 @@ class pySketchyChainingIterator(ChainingIterator): self._timeStamp = CF.get_time_stamp()+self._nRounds def traverse(self, iter): winner = None + found = False it = AdjacencyIterator(iter) while not it.is_end: ve = it.object if ve.id == self.current_edge.id: + found = True it.increment() continue winner = ve it.increment() + if not found: + # This is a fatal error condition: self.current_edge must be found + # among the edges seen by the AdjacencyIterator [bug #35695]. + if bpy.app.debug_freestyle: + print('pySketchyChainingIterator: current edge not found') + return None if winner is None: winner = self.current_edge if winner.chaining_time_stamp == self._timeStamp: diff --git a/release/scripts/freestyle/style_modules/parameter_editor.py b/release/scripts/freestyle/style_modules/parameter_editor.py index 71cfdce43f0..5b773cd7a6d 100644 --- a/release/scripts/freestyle/style_modules/parameter_editor.py +++ b/release/scripts/freestyle/style_modules/parameter_editor.py @@ -32,7 +32,7 @@ from freestyle import BackboneStretcherShader, BezierCurveShader, BinaryPredicat FalseBP1D, FalseUP1D, GuidingLinesShader, Interface0DIterator, Nature, Noise, Normal2DF0D, Operators, \ PolygonalizationShader, QuantitativeInvisibilityF1D, QuantitativeInvisibilityUP1D, SamplingShader, \ SpatialNoiseShader, StrokeAttribute, StrokeShader, TipRemoverShader, TrueBP1D, TrueUP1D, UnaryPredicate0D, \ - UnaryPredicate1D, VertexOrientation2DF0D, WithinImageBoundaryUP1D + UnaryPredicate1D, VertexOrientation2DF0D, WithinImageBoundaryUP1D, ContextFunctions from Functions0D import CurveMaterialF0D from PredicatesU1D import pyNatureUP1D from logical_operators import AndUP1D, NotUP1D, OrUP1D @@ -1046,17 +1046,7 @@ def process(layer_name, lineset_name): selection_criteria.append(upred) # prepare selection criteria by image border if lineset.select_by_image_border: - fac = scene.render.resolution_percentage / 100.0 - w = scene.render.resolution_x * fac - h = scene.render.resolution_y * fac - if scene.render.use_border: - xmin = scene.render.border_min_x * w - xmax = scene.render.border_max_x * w - ymin = scene.render.border_min_y * h - ymax = scene.render.border_max_y * h - else: - xmin, xmax = 0.0, float(w) - ymin, ymax = 0.0, float(h) + xmin, ymin, xmax, ymax = ContextFunctions.get_border() upred = WithinImageBoundaryUP1D(xmin, ymin, xmax, ymax) selection_criteria.append(upred) # select feature edges diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index 8c237840d96..1da45a9f415 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -40,6 +40,7 @@ class SpellChecker(): "derivate", "doesn", # doesn't "fader", + "globbing", "hasn", # hasn't "hoc", # ad-hoc "indices", @@ -59,6 +60,7 @@ class SpellChecker(): "autoclip", "autocomplete", "autoexec", + "autoexecution", "autoname", "autosave", "autoscale", diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py index c9ed91d3a83..d87c207e2d0 100644 --- a/release/scripts/modules/bpy_extras/anim_utils.py +++ b/release/scripts/modules/bpy_extras/anim_utils.py @@ -31,6 +31,7 @@ def bake_action(frame_start, only_selected=False, do_pose=True, do_object=True, + do_visual_keying=True, do_constraint_clear=False, do_parents_clear=False, do_clean=False, @@ -53,7 +54,9 @@ def bake_action(frame_start, :type do_pose: bool :arg do_object: Bake objects. :type do_object: bool - :arg do_constraint_clear: Remove constraints (and do 'visual keying'). + :arg do_visual_keying: Use the final transformations for baking ('visual keying') + :type do_visual_keying: bool + :arg do_constraint_clear: Remove constraints after baking. :type do_constraint_clear: bool :arg do_parents_clear: Unparent after baking objects. :type do_parents_clear: bool @@ -83,14 +86,14 @@ def bake_action(frame_start, if do_parents_clear: def obj_frame_info(obj, do_visual_keying): parent = obj.parent - matrix = obj.matrix_local if do_visual_keying else obj.matrix_basis + matrix = obj.matrix_local if do_visual_keying else obj.matrix_local if parent: return parent.matrix_world * matrix else: return matrix.copy() else: def obj_frame_info(obj, do_visual_keying): - return obj.matrix_local.copy() if do_visual_keying else obj.matrix_basis.copy() + return obj.matrix_local.copy() if do_visual_keying else obj.matrix_local.copy() # ------------------------------------------------------------------------- # Setup the Context @@ -118,10 +121,11 @@ def bake_action(frame_start, for f in frame_range: scene.frame_set(f) + scene.update() if do_pose: - pose_info.append(pose_frame_info(obj, do_constraint_clear)) + pose_info.append(pose_frame_info(obj, do_visual_keying)) if do_object: - obj_info.append(obj_frame_info(obj, do_constraint_clear)) + obj_info.append(obj_frame_info(obj, do_visual_keying)) # ------------------------------------------------------------------------- # Create action diff --git a/release/scripts/modules/rna_keymap_ui.py b/release/scripts/modules/rna_keymap_ui.py new file mode 100644 index 00000000000..727e9935bcc --- /dev/null +++ b/release/scripts/modules/rna_keymap_ui.py @@ -0,0 +1,384 @@ +# ##### 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. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +__all__ = ( + "draw_entry", + "draw_km", + "draw_kmi", + "draw_filtered", + "draw_hierarchy", + "draw_keymaps", + ) + + +import bpy +from bpy.app.translations import pgettext_iface as iface_ +from bpy.app.translations import contexts as i18n_contexts + + +def _indented_layout(layout, level): + indentpx = 16 + if level == 0: + level = 0.0001 # Tweak so that a percentage of 0 won't split by half + indent = level * indentpx / bpy.context.region.width + + split = layout.split(percentage=indent) + col = split.column() + col = split.column() + return col + + +def draw_entry(display_keymaps, entry, col, level=0): + idname, spaceid, regionid, children = entry + + for km, kc in display_keymaps: + if km.name == idname and km.space_type == spaceid and km.region_type == regionid: + draw_km(display_keymaps, kc, km, children, col, level) + + ''' + km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid) + if not km: + kc = defkc + km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid) + + if km: + draw_km(kc, km, children, col, level) + ''' + + +def draw_km(display_keymaps, kc, km, children, layout, level): + km = km.active() + + layout.context_pointer_set("keymap", km) + + col = _indented_layout(layout, level) + + row = col.row() + row.prop(km, "show_expanded_children", text="", emboss=False) + row.label(text=km.name, text_ctxt=i18n_contexts.id_windowmanager) + + row.label() + row.label() + + if km.is_modal: + row.label(text="", icon='LINKED') + if km.is_user_modified: + row.operator("wm.keymap_restore", text="Restore") + else: + row.label() + + if km.show_expanded_children: + if children: + # Put the Parent key map's entries in a 'global' sub-category + # equal in hierarchy to the other children categories + subcol = _indented_layout(col, level + 1) + subrow = subcol.row() + subrow.prop(km, "show_expanded_items", text="", emboss=False) + subrow.label(text=iface_("%s (Global)") % km.name, translate=False) + else: + km.show_expanded_items = True + + # Key Map items + if km.show_expanded_items: + for kmi in km.keymap_items: + draw_kmi(display_keymaps, kc, km, kmi, col, level + 1) + + # "Add New" at end of keymap item list + col = _indented_layout(col, level + 1) + subcol = col.split(percentage=0.2).column() + subcol.operator("wm.keyitem_add", text="Add New", text_ctxt=i18n_contexts.id_windowmanager, + icon='ZOOMIN') + + col.separator() + + # Child key maps + if children: + subcol = col.column() + row = subcol.row() + + for entry in children: + draw_entry(display_keymaps, entry, col, level + 1) + + +def draw_kmi(display_keymaps, kc, km, kmi, layout, level): + map_type = kmi.map_type + + col = _indented_layout(layout, level) + + if kmi.show_expanded: + col = col.column(align=True) + box = col.box() + else: + box = col.column() + + split = box.split(percentage=0.05) + + # header bar + row = split.row() + row.prop(kmi, "show_expanded", text="", emboss=False) + + row = split.row() + row.prop(kmi, "active", text="", emboss=False) + + if km.is_modal: + row.prop(kmi, "propvalue", text="") + else: + row.label(text=kmi.name) + + row = split.row() + row.prop(kmi, "map_type", text="") + if map_type == 'KEYBOARD': + row.prop(kmi, "type", text="", full_event=True) + elif map_type == 'MOUSE': + row.prop(kmi, "type", text="", full_event=True) + elif map_type == 'NDOF': + row.prop(kmi, "type", text="", full_event=True) + elif map_type == 'TWEAK': + subrow = row.row() + subrow.prop(kmi, "type", text="") + subrow.prop(kmi, "value", text="") + elif map_type == 'TIMER': + row.prop(kmi, "type", text="") + else: + row.label() + + if (not kmi.is_user_defined) and kmi.is_user_modified: + row.operator("wm.keyitem_restore", text="", icon='BACK').item_id = kmi.id + else: + row.operator("wm.keyitem_remove", text="", icon='X').item_id = kmi.id + + # Expanded, additional event settings + if kmi.show_expanded: + box = col.box() + + split = box.split(percentage=0.4) + sub = split.row() + + if km.is_modal: + sub.prop(kmi, "propvalue", text="") + else: + # One day... + #~ sub.prop_search(kmi, "idname", bpy.context.window_manager, "operators_all", text="") + sub.prop(kmi, "idname", text="") + + if map_type not in {'TEXTINPUT', 'TIMER'}: + sub = split.column() + subrow = sub.row(align=True) + + if map_type == 'KEYBOARD': + subrow.prop(kmi, "type", text="", event=True) + subrow.prop(kmi, "value", text="") + elif map_type in {'MOUSE', 'NDOF'}: + subrow.prop(kmi, "type", text="") + subrow.prop(kmi, "value", text="") + + subrow = sub.row() + subrow.scale_x = 0.75 + subrow.prop(kmi, "any") + subrow.prop(kmi, "shift") + subrow.prop(kmi, "ctrl") + subrow.prop(kmi, "alt") + subrow.prop(kmi, "oskey", text="Cmd") + subrow.prop(kmi, "key_modifier", text="", event=True) + + # Operator properties + box.template_keymap_item_properties(kmi) + + # Modal key maps attached to this operator + if not km.is_modal: + kmm = kc.keymaps.find_modal(kmi.idname) + if kmm: + draw_km(display_keymaps, kc, kmm, None, layout, level + 1) + layout.context_pointer_set("keymap", km) + +_EVENT_TYPES = set() +_EVENT_TYPE_MAP = {} + + +def draw_filtered(display_keymaps, filter_type, filter_text, layout): + + if filter_type == 'NAME': + def filter_func(kmi): + return (filter_text in kmi.idname.lower() or + filter_text in kmi.name.lower()) + else: + if not _EVENT_TYPES: + enum = bpy.types.Event.bl_rna.properties["type"].enum_items + _EVENT_TYPES.update(enum.keys()) + _EVENT_TYPE_MAP.update({item.name.replace(" ", "_").upper(): key + for key, item in enum.items()}) + + del enum + _EVENT_TYPE_MAP.update({ + "`": 'ACCENT_GRAVE', + "*": 'NUMPAD_ASTERIX', + "/": 'NUMPAD_SLASH', + "RMB": 'RIGHTMOUSE', + "LMB": 'LEFTMOUSE', + "MMB": 'MIDDLEMOUSE', + }) + _EVENT_TYPE_MAP.update({ + "%d" % i: "NUMPAD_%d" % i for i in range(9) + }) + # done with once off init + + filter_text_split = filter_text.strip() + filter_text_split = filter_text.split() + + # Modifier {kmi.attribute: name} mapping + key_mod = { + "ctrl": "ctrl", + "alt": "alt", + "shift": "shift", + "cmd": "oskey", + "oskey": "oskey", + "any": "any", + } + # KeyMapItem like dict, use for comparing against + # attr: state + kmi_test_dict = {} + + # initialize? - so if a if a kmi has a MOD assigned it wont show up. + #~ for kv in key_mod.values(): + #~ kmi_test_dict[kv] = False + + # altname: attr + for kk, kv in key_mod.items(): + if kk in filter_text_split: + filter_text_split.remove(kk) + kmi_test_dict[kv] = True + # whats left should be the event type + if len(filter_text_split) > 1: + return False + elif filter_text_split: + kmi_type = filter_text_split[0].upper() + + if kmi_type not in _EVENT_TYPES: + # replacement table + kmi_type_test = _EVENT_TYPE_MAP.get(kmi_type) + if kmi_type_test is None: + # print("Unknown Type:", kmi_type) + + # Partial match + for k, v in _EVENT_TYPE_MAP.items(): + if kmi_type in k: + kmi_type_test = v + break + if kmi_type in v: + kmi_type_test = v + break + + if kmi_type_test is None: + return False + + kmi_type = kmi_type_test + del kmi_type_test + + kmi_test_dict["type"] = kmi_type + + # main filter func, runs many times + def filter_func(kmi): + for kk, ki in kmi_test_dict.items(): + if getattr(kmi, kk) != ki: + return False + return True + + for km, kc in display_keymaps: + km = km.active() + layout.context_pointer_set("keymap", km) + + filtered_items = [kmi for kmi in km.keymap_items if filter_func(kmi)] + + if filtered_items: + col = layout.column() + + row = col.row() + row.label(text=km.name, icon='DOT') + + row.label() + row.label() + + if km.is_user_modified: + row.operator("wm.keymap_restore", text="Restore") + else: + row.label() + + for kmi in filtered_items: + draw_kmi(display_keymaps, kc, km, kmi, col, 1) + + # "Add New" at end of keymap item list + col = _indented_layout(layout, 1) + subcol = col.split(percentage=0.2).column() + subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN') + return True + + +def draw_hierarchy(display_keymaps, layout): + from bpy_extras import keyconfig_utils + for entry in keyconfig_utils.KM_HIERARCHY: + draw_entry(display_keymaps, entry, layout) + + +def draw_keymaps(context, layout): + from bpy_extras import keyconfig_utils + + wm = context.window_manager + kc = wm.keyconfigs.user + spref = context.space_data + + col = layout.column() + sub = col.column() + + subsplit = sub.split() + subcol = subsplit.column() + + row = subcol.row(align=True) + + #~ row.prop_search(wm.keyconfigs, "active", wm, "keyconfigs", text="Key Config:") + text = bpy.path.display_name(wm.keyconfigs.active.name) + if not text: + text = "Blender (default)" + row.menu("USERPREF_MT_keyconfigs", text=text) + row.operator("wm.keyconfig_preset_add", text="", icon='ZOOMIN') + row.operator("wm.keyconfig_preset_add", text="", icon='ZOOMOUT').remove_active = True + + #~ layout.context_pointer_set("keyconfig", wm.keyconfigs.active) + #~ row.operator("wm.keyconfig_remove", text="", icon='X') + row.separator() + rowsub = row.split(align=True, percentage=0.33) + # postpone drawing into rowsub, so we can set alert! + + col.separator() + display_keymaps = keyconfig_utils.keyconfig_merge(kc, kc) + filter_type = spref.filter_type + filter_text = spref.filter_text.strip() + if filter_text: + filter_text = filter_text.lower() + ok = draw_filtered(display_keymaps, filter_type, filter_text, col) + else: + draw_hierarchy(display_keymaps, col) + ok = True + + # go back and fill in rowsub + rowsub.prop(spref, "filter_type", text="") + rowsubsub = rowsub.row(align=True) + if not ok: + rowsubsub.alert = True + rowsubsub.prop(spref, "filter_text", text="", icon='VIEWZOOM') diff --git a/release/scripts/presets/cycles/sampling/final.py b/release/scripts/presets/cycles/sampling/final.py new file mode 100644 index 00000000000..4bb90d106f4 --- /dev/null +++ b/release/scripts/presets/cycles/sampling/final.py @@ -0,0 +1,16 @@ +import bpy +cycles = bpy.context.scene.cycles + +cycles.squared_samples = True + +cycles.samples = 24 +cycles.preview_samples = 24 +cycles.aa_samples = 8 +cycles.preview_aa_samples = 8 + +cycles.diffuse_samples = 3 +cycles.glossy_samples = 2 +cycles.transmission_samples = 2 +cycles.ao_samples = 1 +cycles.mesh_light_samples = 2 +cycles.subsurface_samples = 2 diff --git a/release/scripts/presets/cycles/sampling/preview.py b/release/scripts/presets/cycles/sampling/preview.py new file mode 100644 index 00000000000..fbe8a011c97 --- /dev/null +++ b/release/scripts/presets/cycles/sampling/preview.py @@ -0,0 +1,16 @@ +import bpy +cycles = bpy.context.scene.cycles + +cycles.squared_samples = True + +cycles.samples = 12 +cycles.preview_samples = 12 +cycles.aa_samples = 4 +cycles.preview_aa_samples = 4 + +cycles.diffuse_samples = 3 +cycles.glossy_samples = 2 +cycles.transmission_samples = 2 +cycles.ao_samples = 1 +cycles.mesh_light_samples = 2 +cycles.subsurface_samples = 2 diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py index ed20cb22297..6193611504e 100644 --- a/release/scripts/startup/bl_operators/anim.py +++ b/release/scripts/startup/bl_operators/anim.py @@ -190,6 +190,11 @@ class BakeAction(Operator): description="Only key selected object/bones", default=True, ) + visual_keying = BoolProperty( + name="Visual Keying", + description="Keyframe from the final transformations (with constraints applied)", + default=False, + ) clear_constraints = BoolProperty( name="Clear Constraints", description="Remove all constraints from keyed object/bones, and do 'visual' keying", @@ -220,6 +225,7 @@ class BakeAction(Operator): only_selected=self.only_selected, do_pose='POSE' in self.bake_types, do_object='OBJECT' in self.bake_types, + do_visual_keying=self.visual_keying, do_constraint_clear=self.clear_constraints, do_parents_clear=self.clear_parents, do_clean=True, diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py index cc1fa93ec2c..c70b5832bfb 100644 --- a/release/scripts/startup/bl_operators/node.py +++ b/release/scripts/startup/bl_operators/node.py @@ -66,8 +66,12 @@ class NodeAddOperator(): # convert mouse position to the View2D for later node placement if context.region.type == 'WINDOW': + # XXX, temp fix for [#35920], still fails for (U.pixelsize != 1) + dpi_fac = context.user_preferences.system.dpi / 72.0 space.cursor_location = v2d.region_to_view(event.mouse_region_x, event.mouse_region_y) + space.cursor_location /= dpi_fac + else: space.cursor_location = tree.view_center diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 3919ecdd72f..63d9aa31ddd 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -471,34 +471,29 @@ class WM_OT_context_cycle_array(Operator): return operator_path_undo_return(context, data_path) -class WM_MT_context_menu_enum(Menu): - bl_label = "" - data_path = "" # BAD DESIGN, set from operator below. +class WM_OT_context_menu_enum(Operator): + bl_idname = "wm.context_menu_enum" + bl_label = "Context Enum Menu" + bl_options = {'UNDO', 'INTERNAL'} + data_path = rna_path_prop - def draw(self, context): + def execute(self, context): data_path = self.data_path value = context_path_validate(context, data_path) + if value is Ellipsis: return {'PASS_THROUGH'} + base_path, prop_string = data_path.rsplit(".", 1) value_base = context_path_validate(context, base_path) prop = value_base.bl_rna.properties[prop_string] - layout = self.layout - layout.label(prop.name, icon=prop.icon) - layout.prop(value_base, prop_string, expand=True) + def draw_cb(self, context): + layout = self.layout + layout.prop(value_base, prop_string, expand=True) + context.window_manager.popup_menu(draw_func=draw_cb, title=prop.name, icon=prop.icon) -class WM_OT_context_menu_enum(Operator): - bl_idname = "wm.context_menu_enum" - bl_label = "Context Enum Menu" - bl_options = {'UNDO', 'INTERNAL'} - data_path = rna_path_prop - - def execute(self, context): - data_path = self.data_path - WM_MT_context_menu_enum.data_path = data_path - bpy.ops.wm.call_menu(name="WM_MT_context_menu_enum") return {'PASS_THROUGH'} diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 594f724c6e3..b9f2e8406c6 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -72,7 +72,6 @@ _modules = [ "space_sequencer", "space_text", "space_time", - "space_userpref_keymap", "space_userpref", "space_view3d", "space_view3d_toolbar", diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index 7747ef45c4d..117a662cd07 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -362,7 +362,7 @@ class DATA_PT_paragraph(CurveButtonsPanel, Panel): col = split.column(align=True) col.label(text="Spacing:") - col.prop(text, "space_character", text="Character") + col.prop(text, "space_character", text="Letter") col.prop(text, "space_word", text="Word") col.prop(text, "space_line", text="Line") diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index b6ad14196cd..b5461c45433 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -33,7 +33,7 @@ class MESH_MT_vertex_group_specials(Menu): layout.operator("object.vertex_group_copy", icon='COPY_ID') layout.operator("object.vertex_group_copy_to_linked", icon='LINK_AREA') layout.operator("object.vertex_group_copy_to_selected", icon='LINK_AREA') - layout.operator("object.vertex_group_mirror", icon='ARROW_LEFTRIGHT') + layout.operator("object.vertex_group_mirror", icon='ARROW_LEFTRIGHT').use_topology = False layout.operator("object.vertex_group_mirror", text="Mirror Vertex Group (Topology)", icon='ARROW_LEFTRIGHT').use_topology = True layout.operator("object.vertex_group_remove_from", icon='X', text="Remove from All Groups").use_all_groups = True layout.operator("object.vertex_group_remove_from", icon='X', text="Clear Active Group").use_all_verts = True @@ -53,7 +53,7 @@ class MESH_MT_shape_key_specials(Menu): layout.operator("object.shape_key_transfer", icon='COPY_ID') # icon is not ideal layout.operator("object.join_shapes", icon='COPY_ID') # icon is not ideal - layout.operator("object.shape_key_mirror", icon='ARROW_LEFTRIGHT') + layout.operator("object.shape_key_mirror", icon='ARROW_LEFTRIGHT').use_topology = False layout.operator("object.shape_key_mirror", text="Mirror Shape Key (Topology)", icon='ARROW_LEFTRIGHT').use_topology = True layout.operator("object.shape_key_add", icon='ZOOMIN', text="New Shape From Mix").from_mix = True layout.operator("object.shape_key_remove", icon='X', text="Delete All Shapes").all = True diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 89e90618383..861d64382ef 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -715,9 +715,11 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col = split.column() col.label(text="Origin:") col.prop(md, "origin", text="") - sub = col.column() - sub.active = (md.origin is not None) - sub.prop(md, "use_relative") + + if md.deform_method in {'TAPER', 'STRETCH', 'TWIST'}: + col.label(text="Lock:") + col.prop(md, "lock_x") + col.prop(md, "lock_y") col = split.column() col.label(text="Deform:") @@ -726,9 +728,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): else: col.prop(md, "angle") col.prop(md, "limits", slider=True) - if md.deform_method in {'TAPER', 'STRETCH', 'TWIST'}: - col.prop(md, "lock_x") - col.prop(md, "lock_y") def SMOKE(self, layout, ob, md): layout.label(text="Settings can be found inside the Physics context") diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 38e49853454..025d86204f2 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -414,6 +414,9 @@ class RENDER_PT_game_system(RenderButtonsPanel, Panel): col.active = gs.raster_storage != 'VERTEX_BUFFER_OBJECT' row = layout.row() + row.prop(gs, "vsync") + + row = layout.row() row.prop(gs, "raster_storage") row = layout.row() diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py index c9b1bc0ccff..d38f5f934b4 100644 --- a/release/scripts/startup/bl_ui/properties_mask_common.py +++ b/release/scripts/startup/bl_ui/properties_mask_common.py @@ -339,6 +339,11 @@ class MASK_MT_select(Menu): layout.separator() + layout.operator("mask.select_more") + layout.operator("mask.select_less") + + layout.separator() + layout.operator("mask.select_all").action = 'TOGGLE' layout.operator("mask.select_all", text="Inverse").action = 'INVERT' diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 31023d49340..ec2492f7365 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -205,10 +205,20 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel): layout = self.layout obj = context.object + obj_type = obj.type + is_geometry = (obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}) + is_empty_image = (obj_type == 'EMPTY' and obj.empty_draw_type == 'IMAGE') split = layout.split() + col = split.column() - col.prop(obj, "draw_type", text="Type") + col.prop(obj, "show_name", text="Name") + col.prop(obj, "show_axis", text="Axis") + if is_geometry: + # Makes no sense for cameras, armatures, etc.! + col.prop(obj, "show_wire", text="Wire") + if obj_type == 'MESH': + col.prop(obj, "show_all_edges") col = split.column() row = col.row() @@ -217,27 +227,24 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel): sub.active = obj.show_bounds sub.prop(obj, "draw_bounds_type", text="") + if is_geometry: + col.prop(obj, "show_texture_space", text="Texture Space") + col.prop(obj, "show_x_ray", text="X-Ray") + if obj_type == 'MESH' or is_empty_image: + col.prop(obj, "show_transparent", text="Transparency") + split = layout.split() col = split.column() - col.prop(obj, "show_name", text="Name") - col.prop(obj, "show_axis", text="Axis") - - obj_type = obj.type - - if obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}: - # Makes no sense for cameras, armtures, etc.! - col.prop(obj, "show_wire", text="Wire") - # Only useful with object having faces/materials... - col.prop(obj, "color", text="Object Color") + if obj_type not in {'CAMERA', 'EMPTY'}: + col.label(text="Maximum draw type:") + col.prop(obj, "draw_type", text="") col = split.column() - col.prop(obj, "show_texture_space", text="Texture Space") - col.prop(obj, "show_x_ray", text="X-Ray") - if obj_type == 'MESH' or (obj_type == 'EMPTY' and obj.empty_draw_type == 'IMAGE'): - col.prop(obj, "show_transparent", text="Transparency") - if obj_type == 'MESH': - col.prop(obj, "show_all_edges") + if is_geometry or is_empty_image: + # Only useful with object having faces/materials... + col.label(text="Object Color:") + col.prop(obj, "color", text="") class OBJECT_PT_duplication(ObjectButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index eb0d9c5082d..22e2e6e08a2 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -232,6 +232,7 @@ class IMAGE_MT_uvs_snap(Menu): layout.operator("uv.snap_selected", text="Selected to Pixels").target = 'PIXELS' layout.operator("uv.snap_selected", text="Selected to Cursor").target = 'CURSOR' + layout.operator("uv.snap_selected", text="Selected to Cursor (Offset)").target = 'CURSOR_OFFSET' layout.operator("uv.snap_selected", text="Selected to Adjacent Unselected").target = 'ADJACENT_UNSELECTED' layout.separator() diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 3477353ba0d..79191637080 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -671,13 +671,14 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel): layout.separator() layout.prop(strip, "filepath", text="") - row = layout.row() - if sound.packed_file: - row.operator("sound.unpack", icon='PACKAGE', text="Unpack") - else: - row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack") + if sound is not None: + row = layout.row() + if sound.packed_file: + row.operator("sound.unpack", icon='PACKAGE', text="Unpack") + else: + row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack") - row.prop(sound, "use_memory_cache") + row.prop(sound, "use_memory_cache") layout.prop(strip, "show_waveform") layout.prop(strip, "volume") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 54387f10a8d..3e281e08983 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -917,9 +917,6 @@ class USERPREF_PT_file(Panel): col.prop(system, "author", text="") -from bl_ui.space_userpref_keymap import InputKeyMapPanel - - class USERPREF_MT_ndof_settings(Menu): # accessed from the window key-bindings in C (only) bl_label = "3D Mouse Settings" @@ -960,9 +957,25 @@ class USERPREF_MT_ndof_settings(Menu): layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM') -class USERPREF_PT_input(Panel, InputKeyMapPanel): +class USERPREF_MT_keyconfigs(Menu): + bl_label = "KeyPresets" + preset_subdir = "keyconfig" + preset_operator = "wm.keyconfig_activate" + + def draw(self, context): + props = self.layout.operator("wm.context_set_value", text="Blender (default)") + props.data_path = "window_manager.keyconfigs.active" + props.value = "context.window_manager.keyconfigs.default" + + # now draw the presets + Menu.draw_preset(self, context) + + +class USERPREF_PT_input(Panel): bl_space_type = 'USER_PREFERENCES' bl_label = "Input" + bl_region_type = 'WINDOW' + bl_options = {'HIDE_HEADER'} @classmethod def poll(cls, context): @@ -1039,6 +1052,8 @@ class USERPREF_PT_input(Panel, InputKeyMapPanel): row.separator() def draw(self, context): + from rna_keymap_ui import draw_keymaps + layout = self.layout #import time @@ -1055,7 +1070,7 @@ class USERPREF_PT_input(Panel, InputKeyMapPanel): self.draw_input_prefs(inputs, split) # Keymap Settings - self.draw_keymaps(context, split) + draw_keymaps(context, split) #print("runtime", time.time() - start) diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py deleted file mode 100644 index 8d6eb2c623d..00000000000 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ /dev/null @@ -1,391 +0,0 @@ -# ##### 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. -# -# ##### END GPL LICENSE BLOCK ##### - -# <pep8 compliant> -import bpy -from bpy.types import Menu -from bpy.app.translations import pgettext_iface as iface_ -from bpy.app.translations import contexts as i18n_contexts - - -class USERPREF_MT_keyconfigs(Menu): - bl_label = "KeyPresets" - preset_subdir = "keyconfig" - preset_operator = "wm.keyconfig_activate" - - def draw(self, context): - props = self.layout.operator("wm.context_set_value", text="Blender (default)") - props.data_path = "window_manager.keyconfigs.active" - props.value = "context.window_manager.keyconfigs.default" - - # now draw the presets - Menu.draw_preset(self, context) - - -class InputKeyMapPanel: - bl_space_type = 'USER_PREFERENCES' - bl_label = "Input" - bl_region_type = 'WINDOW' - bl_options = {'HIDE_HEADER'} - - def draw_entry(self, display_keymaps, entry, col, level=0): - idname, spaceid, regionid, children = entry - - for km, kc in display_keymaps: - if km.name == idname and km.space_type == spaceid and km.region_type == regionid: - self.draw_km(display_keymaps, kc, km, children, col, level) - - ''' - km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid) - if not km: - kc = defkc - km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid) - - if km: - self.draw_km(kc, km, children, col, level) - ''' - - def indented_layout(self, layout, level): - indentpx = 16 - if level == 0: - level = 0.0001 # Tweak so that a percentage of 0 won't split by half - indent = level * indentpx / bpy.context.region.width - - split = layout.split(percentage=indent) - col = split.column() - col = split.column() - return col - - def draw_km(self, display_keymaps, kc, km, children, layout, level): - km = km.active() - - layout.context_pointer_set("keymap", km) - - col = self.indented_layout(layout, level) - - row = col.row() - row.prop(km, "show_expanded_children", text="", emboss=False) - row.label(text=km.name, text_ctxt=i18n_contexts.id_windowmanager) - - row.label() - row.label() - - if km.is_modal: - row.label(text="", icon='LINKED') - if km.is_user_modified: - row.operator("wm.keymap_restore", text="Restore") - else: - row.label() - - if km.show_expanded_children: - if children: - # Put the Parent key map's entries in a 'global' sub-category - # equal in hierarchy to the other children categories - subcol = self.indented_layout(col, level + 1) - subrow = subcol.row() - subrow.prop(km, "show_expanded_items", text="", emboss=False) - subrow.label(text=iface_("%s (Global)") % km.name, translate=False) - else: - km.show_expanded_items = True - - # Key Map items - if km.show_expanded_items: - for kmi in km.keymap_items: - self.draw_kmi(display_keymaps, kc, km, kmi, col, level + 1) - - # "Add New" at end of keymap item list - col = self.indented_layout(col, level + 1) - subcol = col.split(percentage=0.2).column() - subcol.operator("wm.keyitem_add", text="Add New", text_ctxt=i18n_contexts.id_windowmanager, - icon='ZOOMIN') - - col.separator() - - # Child key maps - if children: - subcol = col.column() - row = subcol.row() - - for entry in children: - self.draw_entry(display_keymaps, entry, col, level + 1) - - def draw_kmi(self, display_keymaps, kc, km, kmi, layout, level): - map_type = kmi.map_type - - col = self.indented_layout(layout, level) - - if kmi.show_expanded: - col = col.column(align=True) - box = col.box() - else: - box = col.column() - - split = box.split(percentage=0.05) - - # header bar - row = split.row() - row.prop(kmi, "show_expanded", text="", emboss=False) - - row = split.row() - row.prop(kmi, "active", text="", emboss=False) - - if km.is_modal: - row.prop(kmi, "propvalue", text="") - else: - row.label(text=kmi.name) - - row = split.row() - row.prop(kmi, "map_type", text="") - if map_type == 'KEYBOARD': - row.prop(kmi, "type", text="", full_event=True) - elif map_type == 'MOUSE': - row.prop(kmi, "type", text="", full_event=True) - elif map_type == 'NDOF': - row.prop(kmi, "type", text="", full_event=True) - elif map_type == 'TWEAK': - subrow = row.row() - subrow.prop(kmi, "type", text="") - subrow.prop(kmi, "value", text="") - elif map_type == 'TIMER': - row.prop(kmi, "type", text="") - else: - row.label() - - if (not kmi.is_user_defined) and kmi.is_user_modified: - row.operator("wm.keyitem_restore", text="", icon='BACK').item_id = kmi.id - else: - row.operator("wm.keyitem_remove", text="", icon='X').item_id = kmi.id - - # Expanded, additional event settings - if kmi.show_expanded: - box = col.box() - - split = box.split(percentage=0.4) - sub = split.row() - - if km.is_modal: - sub.prop(kmi, "propvalue", text="") - else: - # One day... - #~ sub.prop_search(kmi, "idname", bpy.context.window_manager, "operators_all", text="") - sub.prop(kmi, "idname", text="") - - if map_type not in {'TEXTINPUT', 'TIMER'}: - sub = split.column() - subrow = sub.row(align=True) - - if map_type == 'KEYBOARD': - subrow.prop(kmi, "type", text="", event=True) - subrow.prop(kmi, "value", text="") - elif map_type in {'MOUSE', 'NDOF'}: - subrow.prop(kmi, "type", text="") - subrow.prop(kmi, "value", text="") - - subrow = sub.row() - subrow.scale_x = 0.75 - subrow.prop(kmi, "any") - subrow.prop(kmi, "shift") - subrow.prop(kmi, "ctrl") - subrow.prop(kmi, "alt") - subrow.prop(kmi, "oskey", text="Cmd") - subrow.prop(kmi, "key_modifier", text="", event=True) - - # Operator properties - box.template_keymap_item_properties(kmi) - - # Modal key maps attached to this operator - if not km.is_modal: - kmm = kc.keymaps.find_modal(kmi.idname) - if kmm: - self.draw_km(display_keymaps, kc, kmm, None, layout, level + 1) - layout.context_pointer_set("keymap", km) - - _EVENT_TYPES = set() - _EVENT_TYPE_MAP = {} - - def draw_filtered(self, display_keymaps, filter_type, filter_text, layout): - - if filter_type == 'NAME': - def filter_func(kmi): - return (filter_text in kmi.idname.lower() or - filter_text in kmi.name.lower()) - else: - if not self._EVENT_TYPES: - enum = bpy.types.Event.bl_rna.properties["type"].enum_items - self._EVENT_TYPES.update(enum.keys()) - self._EVENT_TYPE_MAP.update({item.name.replace(" ", "_").upper(): key for key, item in enum.items()}) - - del enum - self._EVENT_TYPE_MAP.update({ - "`": 'ACCENT_GRAVE', - "*": 'NUMPAD_ASTERIX', - "/": 'NUMPAD_SLASH', - "RMB": 'RIGHTMOUSE', - "LMB": 'LEFTMOUSE', - "MMB": 'MIDDLEMOUSE', - }) - self._EVENT_TYPE_MAP.update({ - "%d" % i: "NUMPAD_%d" % i for i in range(9) - }) - # done with once off init - - filter_text_split = filter_text.strip() - filter_text_split = filter_text.split() - - # Modifier {kmi.attribute: name} mapping - key_mod = { - "ctrl": "ctrl", - "alt": "alt", - "shift": "shift", - "cmd": "oskey", - "oskey": "oskey", - "any": "any", - } - # KeyMapItem like dict, use for comparing against - # attr: state - kmi_test_dict = {} - - # initialize? - so if a if a kmi has a MOD assigned it wont show up. - #~ for kv in key_mod.values(): - #~ kmi_test_dict[kv] = False - - # altname: attr - for kk, kv in key_mod.items(): - if kk in filter_text_split: - filter_text_split.remove(kk) - kmi_test_dict[kv] = True - # whats left should be the event type - if len(filter_text_split) > 1: - return False - elif filter_text_split: - kmi_type = filter_text_split[0].upper() - - if kmi_type not in self._EVENT_TYPES: - # replacement table - kmi_type_test = self._EVENT_TYPE_MAP.get(kmi_type) - if kmi_type_test is None: - # print("Unknown Type:", kmi_type) - - # Partial match - for k, v in self._EVENT_TYPE_MAP.items(): - if kmi_type in k: - kmi_type_test = v - break - if kmi_type in v: - kmi_type_test = v - break - - if kmi_type_test is None: - return False - - kmi_type = kmi_type_test - del kmi_type_test - - kmi_test_dict["type"] = kmi_type - - # main filter func, runs many times - def filter_func(kmi): - for kk, ki in kmi_test_dict.items(): - if getattr(kmi, kk) != ki: - return False - return True - - for km, kc in display_keymaps: - km = km.active() - layout.context_pointer_set("keymap", km) - - filtered_items = [kmi for kmi in km.keymap_items if filter_func(kmi)] - - if filtered_items: - col = layout.column() - - row = col.row() - row.label(text=km.name, icon='DOT') - - row.label() - row.label() - - if km.is_user_modified: - row.operator("wm.keymap_restore", text="Restore") - else: - row.label() - - for kmi in filtered_items: - self.draw_kmi(display_keymaps, kc, km, kmi, col, 1) - - # "Add New" at end of keymap item list - col = self.indented_layout(layout, 1) - subcol = col.split(percentage=0.2).column() - subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN') - return True - - def draw_hierarchy(self, display_keymaps, layout): - from bpy_extras import keyconfig_utils - for entry in keyconfig_utils.KM_HIERARCHY: - self.draw_entry(display_keymaps, entry, layout) - - def draw_keymaps(self, context, layout): - from bpy_extras import keyconfig_utils - - wm = context.window_manager - kc = wm.keyconfigs.user - spref = context.space_data - - col = layout.column() - sub = col.column() - - subsplit = sub.split() - subcol = subsplit.column() - - row = subcol.row(align=True) - - #~ row.prop_search(wm.keyconfigs, "active", wm, "keyconfigs", text="Key Config:") - text = bpy.path.display_name(wm.keyconfigs.active.name) - if not text: - text = "Blender (default)" - row.menu("USERPREF_MT_keyconfigs", text=text) - row.operator("wm.keyconfig_preset_add", text="", icon='ZOOMIN') - row.operator("wm.keyconfig_preset_add", text="", icon='ZOOMOUT').remove_active = True - - #~ layout.context_pointer_set("keyconfig", wm.keyconfigs.active) - #~ row.operator("wm.keyconfig_remove", text="", icon='X') - row.separator() - rowsub = row.split(align=True, percentage=0.33) - # postpone drawing into rowsub, so we can set alert! - - col.separator() - display_keymaps = keyconfig_utils.keyconfig_merge(kc, kc) - filter_type = spref.filter_type - filter_text = spref.filter_text.strip() - if filter_text: - filter_text = filter_text.lower() - ok = self.draw_filtered(display_keymaps, filter_type, filter_text, col) - else: - self.draw_hierarchy(display_keymaps, col) - ok = True - - # go back and fill in rowsub - rowsub.prop(spref, "filter_type", text="") - rowsubsub = rowsub.row(align=True) - if not ok: - rowsubsub.alert = True - rowsubsub.prop(spref, "filter_text", text="", icon='VIEWZOOM') - - -if __name__ == "__main__": # only for live edit. - bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 20f998cd568..58eecc2641d 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -293,7 +293,10 @@ class VIEW3D_MT_snap(Menu): layout = self.layout layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid") - layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor") + props = layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor") + props.use_offset = False + props = layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Offset)") + props.use_offset = True layout.separator() @@ -617,8 +620,8 @@ class VIEW3D_MT_select_edit_mesh(Menu): layout.separator() - layout.operator("mesh.select_less", text="Less") layout.operator("mesh.select_more", text="More") + layout.operator("mesh.select_less", text="Less") layout.separator() @@ -723,6 +726,7 @@ class VIEW3D_MT_select_edit_lattice(Menu): layout.separator() + layout.operator("lattice.select_random") layout.operator("lattice.select_all").action = 'TOGGLE' layout.operator("lattice.select_all", text="Inverse").action = 'INVERT' @@ -747,6 +751,11 @@ class VIEW3D_MT_select_edit_armature(Menu): layout.separator() + layout.operator("armature.select_more", text="More") + layout.operator("armature.select_less", text="Less") + + layout.separator() + layout.operator("armature.select_hierarchy", text="Parent").direction = 'PARENT' layout.operator("armature.select_hierarchy", text="Child").direction = 'CHILD' @@ -1813,6 +1822,7 @@ class VIEW3D_MT_edit_mesh(Menu): layout.menu("VIEW3D_MT_edit_mesh_edges") layout.menu("VIEW3D_MT_edit_mesh_faces") layout.menu("VIEW3D_MT_edit_mesh_normals") + layout.menu("VIEW3D_MT_edit_mesh_clean") layout.separator() @@ -1963,7 +1973,9 @@ class VIEW3D_MT_edit_mesh_edges(Menu): def draw(self, context): layout = self.layout + with_freestyle = bpy.app.build_options.freestyle + scene = context.scene layout.operator_context = 'INVOKE_REGION_WIN' @@ -1988,11 +2000,10 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.separator() - if with_freestyle: + if with_freestyle and not scene.render.use_shading_nodes: layout.operator("mesh.mark_freestyle_edge").clear = False layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True - - layout.separator() + layout.separator() layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").use_ccw = True @@ -2018,7 +2029,9 @@ class VIEW3D_MT_edit_mesh_faces(Menu): def draw(self, context): layout = self.layout + with_freestyle = bpy.app.build_options.freestyle + scene = context.scene layout.operator_context = 'INVOKE_REGION_WIN' @@ -2034,11 +2047,10 @@ class VIEW3D_MT_edit_mesh_faces(Menu): layout.separator() - if with_freestyle: + if with_freestyle and not scene.render.use_shading_nodes: layout.operator("mesh.mark_freestyle_face").clear = False layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True - - layout.separator() + layout.separator() layout.operator("mesh.poke") layout.operator("mesh.quads_convert_to_tris") @@ -2075,6 +2087,16 @@ class VIEW3D_MT_edit_mesh_normals(Menu): layout.operator("mesh.flip_normals") +class VIEW3D_MT_edit_mesh_clean(Menu): + bl_label = "Clean" + + def draw(self, context): + layout = self.layout + + layout.operator("mesh.fill_holes") + layout.operator("mesh.vert_connect_nonplanar") + + class VIEW3D_MT_edit_mesh_delete(Menu): bl_label = "Delete" @@ -2188,7 +2210,9 @@ class VIEW3D_MT_edit_curve_specials(Menu): layout.operator("curve.spline_weight_set") layout.operator("curve.radius_set") layout.operator("curve.smooth") + layout.operator("curve.smooth_weight") layout.operator("curve.smooth_radius") + layout.operator("curve.smooth_tilt") class VIEW3D_MT_edit_curve_showhide(ShowHideMenu, Menu): @@ -2534,7 +2558,7 @@ class VIEW3D_PT_view3d_display(Panel): view = context.space_data scene = context.scene gs = scene.game_settings - ob = context.object + obj = context.object col = layout.column() col.prop(view, "show_only_render") @@ -2574,6 +2598,8 @@ class VIEW3D_PT_view3d_display(Panel): if view.use_matcap: col.template_icon_view(view, "matcap_icon") col.prop(view, "show_backface_culling") + if obj and obj.mode == 'EDIT' and view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}: + col.prop(view, "show_occlude_wire") layout.separator() @@ -2637,6 +2663,7 @@ class VIEW3D_PT_view3d_meshdisplay(Panel): with_freestyle = bpy.app.build_options.freestyle mesh = context.active_object.data + scene = context.scene split = layout.split() @@ -2656,7 +2683,7 @@ class VIEW3D_PT_view3d_meshdisplay(Panel): col.prop(mesh, "show_edge_seams", text="Seams") col.prop(mesh, "show_edge_sharp", text="Sharp", text_ctxt=i18n_contexts.plural) col.prop(mesh, "show_edge_bevel_weight", text="Bevel") - if with_freestyle: + if with_freestyle and not scene.render.use_shading_nodes: col.prop(mesh, "show_freestyle_edge_marks", text="Edge Marks") col.prop(mesh, "show_freestyle_face_marks", text="Face Marks") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 1383775042d..f253801f431 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -277,7 +277,6 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel): col.operator("curve.switch_direction") col.operator("curve.spline_type_set") col.operator("curve.radius_set") - col.operator("curve.smooth_radius") col = layout.column(align=True) col.label(text="Handles:") diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py index d5bb71416c9..5f002f37161 100644 --- a/release/scripts/templates_py/custom_nodes.py +++ b/release/scripts/templates_py/custom_nodes.py @@ -1,5 +1,5 @@ import bpy -from bpy_types import NodeTree, Node, NodeSocket +from bpy.types import NodeTree, Node, NodeSocket # Implementation of custom nodes from Python |