diff options
author | Joerg Mueller <nexyon@gmail.com> | 2011-07-05 17:54:25 +0400 |
---|---|---|
committer | Joerg Mueller <nexyon@gmail.com> | 2011-07-05 17:54:25 +0400 |
commit | 3f3c6f5f1fb336f8f0015d7857a1ae153fa2a80f (patch) | |
tree | 27e2ae66dd589013c24592fe0803b440a7e014be /release/scripts | |
parent | 887fd19894047832fbb7a7300e5fc11438b1f3b2 (diff) | |
parent | ccd31900ab9659b6fdc035fd91bff9f508334e22 (diff) |
Merging from trunk up to r38119.
Diffstat (limited to 'release/scripts')
-rw-r--r-- | release/scripts/modules/bpy/__init__.py | 29 | ||||
-rw-r--r-- | release/scripts/modules/bpy_extras/mesh_utils.py | 6 | ||||
-rw-r--r-- | release/scripts/modules/console/intellisense.py | 15 | ||||
-rw-r--r-- | release/scripts/startup/bl_operators/image.py | 2 | ||||
-rw-r--r-- | release/scripts/startup/bl_operators/mesh.py | 11 | ||||
-rw-r--r-- | release/scripts/startup/bl_operators/object_quick_effects.py | 2 | ||||
-rw-r--r-- | release/scripts/startup/bl_operators/uvcalc_smart_project.py | 64 | ||||
-rw-r--r-- | release/scripts/startup/bl_operators/wm.py | 71 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_data_mesh.py | 5 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_material.py | 3 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_particle.py | 9 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_render.py | 1 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_image.py | 3 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_userpref.py | 80 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d.py | 78 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d_toolbar.py | 10 |
16 files changed, 306 insertions, 83 deletions
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py index 1df8e9e5588..9c48dc89f83 100644 --- a/release/scripts/modules/bpy/__init__.py +++ b/release/scripts/modules/bpy/__init__.py @@ -22,24 +22,29 @@ Give access to blender data and utility functions. """ -# internal blender C module -import _bpy -from _bpy import types, props, app +__all__ = ( + "app", + "context", + "data", + "ops", + "path", + "props", + "types", + "utils", +) + -data = _bpy.data -context = _bpy.context +# internal blender C module +from _bpy import types, props, app, data, context # python modules -from . import utils, path -from . import ops as _ops_module +from . import utils, path, ops # fake operator module -ops = _ops_module.ops_fake_module - -import sys as _sys - +ops = ops.ops_fake_module def _main(): + import sys as _sys # Possibly temp. addons path from os.path import join, dirname, normpath @@ -59,3 +64,5 @@ def _main(): _main() + +del _main diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index 2062fe4485f..8ed50972c54 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -105,9 +105,9 @@ def edge_face_count(mesh): :return: list face users for each item in mesh.edges. :rtype: list """ - edge_face_count_dict = edge_face_count_dict(mesh) + edge_face_count = edge_face_count_dict(mesh) get = dict.get - return [get(edge_face_count_dict, ed.key, 0) for ed in mesh.edges] + return [get(edge_face_count, ed.key, 0) for ed in mesh.edges] def edge_loops_from_faces(mesh, faces=None, seams=()): @@ -287,7 +287,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True): else: return v1[1], v2[1] - if not PREF_FIX_LOOPS: + if not fix_loops: ''' Normal single concave loop filling ''' diff --git a/release/scripts/modules/console/intellisense.py b/release/scripts/modules/console/intellisense.py index 072d467ff86..a177b305fda 100644 --- a/release/scripts/modules/console/intellisense.py +++ b/release/scripts/modules/console/intellisense.py @@ -53,7 +53,7 @@ RE_UNQUOTED_WORD = re.compile( re.UNICODE) -def complete(line, cursor, namespace, private=True): +def complete(line, cursor, namespace, private): """Returns a list of possible completions: * name completion @@ -82,6 +82,9 @@ def complete(line, cursor, namespace, private=True): if RE_MODULE.match(line): from . import complete_import matches = complete_import.complete(line) + if not private: + matches[:] = [m for m in matches if m[:1] != "_"] + matches.sort() else: from . import complete_namespace matches = complete_namespace.complete(word, namespace, private) @@ -130,11 +133,15 @@ def expand(line, cursor, namespace, private=True): else: # causes blender bug [#27495] since string keys may contain '.' # scrollback = ' '.join([m.split('.')[-1] for m in matches]) + + # add white space to align with the cursor + white_space = " " + (" " * (cursor + len(prefix))) word_prefix = word + prefix - scrollback = ' '.join( - [m[len(word_prefix):] + scrollback = '\n'.join( + [white_space + m[len(word_prefix):] if (word_prefix and m.startswith(word_prefix)) - else m.split('.')[-1] + else + white_space + m.split('.')[-1] for m in matches]) no_calltip = True diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py index 462db3a2c5e..1e5217217dd 100644 --- a/release/scripts/startup/bl_operators/image.py +++ b/release/scripts/startup/bl_operators/image.py @@ -60,7 +60,7 @@ class EditExternally(bpy.types.Operator): filepath = bpy.path.abspath(self.filepath) if not os.path.exists(filepath): - self.report({'ERROR'}, "Image path %r not found." % filepath) + self.report({'ERROR'}, "Image path %r not found, image may be packed or unsaved." % filepath) return {'CANCELLED'} cmd = self._editor_guess(context) + [filepath] diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py index 996b38ae571..8dca30e54df 100644 --- a/release/scripts/startup/bl_operators/mesh.py +++ b/release/scripts/startup/bl_operators/mesh.py @@ -81,8 +81,8 @@ class MeshMirrorUV(bpy.types.Operator): @classmethod def poll(cls, context): - ob = context.active_object - return (ob and ob.type == 'MESH') + obj = context.active_object + return (obj and obj.type == 'MESH' and obj.data.uv_textures.active) def execute(self, context): DIR = (self.direction == 'NEGATIVE') @@ -120,12 +120,7 @@ class MeshMirrorUV(bpy.types.Operator): if j is not None: vmap[i] = j - active_uv_layer = None - for lay in mesh.uv_textures: - if lay.active: - active_uv_layer = lay.data - break - + active_uv_layer = mesh.uv_textures.active.data fuvs = [(uv.uv1, uv.uv2, uv.uv3, uv.uv4) for uv in active_uv_layer] fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy()) for uv in fuvs] diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index a8bb3227b3c..074f204d50e 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -132,7 +132,7 @@ class QuickExplode(bpy.types.Operator): fake_context = bpy.context.copy() obj_act = context.active_object - if obj_act.type != 'MESH': + if obj_act is None or obj_act.type != 'MESH': self.report({'ERROR'}, "Active object is not a mesh") return {'CANCELLED'} diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py index c70b9071985..7ea89cfa479 100644 --- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py +++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py @@ -746,13 +746,15 @@ def packIslands(islandList): uv.y= (uv.y+yoffset) * yfactor - def VectoQuat(vec): - vec = vec.normalized() - if abs(vec.x) > 0.5: - return vec.to_track_quat('Z', 'X') - else: - return vec.to_track_quat('Z', 'Y') + a3 = vec.normalized() + up = Vector((0.0, 0.0, 1.0)) + if abs(a3.dot(up)) == 1.0: + up = Vector((0.0, 1.0, 0.0)) + + a1 = a3.cross(up).normalized() + a2 = a3.cross(a1) + return Matrix((a1, a2, a3)).to_quaternion() class thickface(object): @@ -791,7 +793,11 @@ def main_consts(): global ob ob = None -def main(context, island_margin, projection_limit): +def main(context, + island_margin, + projection_limit, + user_area_weight, + ): global USER_FILL_HOLES global USER_FILL_HOLES_QUALITY global USER_STRETCH_ASPECT @@ -812,21 +818,25 @@ def main(context, island_margin, projection_limit): global RotMatStepRotation main_consts() -#XXX objects= bpy.data.scenes.active.objects - objects = context.selected_editable_objects - + # TODO, all selected meshes + ''' + # objects = context.selected_editable_objects + objects = [] # we can will tag them later. obList = [ob for ob in objects if ob.type == 'MESH'] # Face select object may not be selected. -#XXX ob = objects.active - ob= objects[0] + ob = context.active_object if ob and (not ob.select) and ob.type == 'MESH': # Add to the list obList =[ob] del objects + ''' + + # quick workaround + obList = [ob for ob in [context.active_object] if ob and ob.type == 'MESH'] if not obList: raise('error, no selected mesh objects') @@ -840,7 +850,6 @@ def main(context, island_margin, projection_limit): USER_FILL_HOLES = (0) USER_FILL_HOLES_QUALITY = (50) # Only for hole filling. USER_VIEW_INIT = (0) # Only for hole filling. - USER_AREA_WEIGHT = (1) # Only for hole filling. # Reuse variable if len(obList) == 1: @@ -966,12 +975,15 @@ def main(context, island_margin, projection_limit): # Add the average of all these faces normals as a projectionVec averageVec = Vector((0.0, 0.0, 0.0)) - if USER_AREA_WEIGHT: + if user_area_weight == 0.0: for fprop in newProjectMeshFaces: - averageVec += (fprop.no * fprop.area) + averageVec += fprop.no + elif user_area_weight == 1.0: + for fprop in newProjectMeshFaces: + averageVec += fprop.no * fprop.area else: for fprop in newProjectMeshFaces: - averageVec += fprop.no + averageVec += fprop.no * ((fprop.area * user_area_weight) + (1.0 - user_area_weight)) if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN projectVecs.append(averageVec.normalized()) @@ -1058,7 +1070,7 @@ def main(context, island_margin, projection_limit): f_uv = f.uv for j, v in enumerate(f.v): # XXX - note, between mathutils in 2.4 and 2.5 the order changed. - f_uv[j][:] = (v.co * MatQuat)[:2] + f_uv[j][:] = (v.co * MatQuat).xy if USER_SHARE_SPACE: @@ -1094,12 +1106,8 @@ def main(context, island_margin, projection_limit): """ pup_block = [\ 'Projection',\ -* ('Angle Limit:', USER_PROJECTION_LIMIT, 1, 89, ''),\ ('Selected Faces Only', USER_ONLY_SELECTED_FACES, 'Use only selected faces from all selected meshes.'),\ ('Init from view', USER_VIEW_INIT, 'The first projection will be from the view vector.'),\ - ('Area Weight', USER_AREA_WEIGHT, 'Weight projections vector by face area.'),\ - '',\ - '',\ '',\ 'UV Layout',\ ('Share Tex Space', USER_SHARE_SPACE, 'Objects Share texture space, map all objects into 1 uvmap.'),\ @@ -1121,11 +1129,15 @@ class SmartProject(bpy.types.Operator): bl_options = {'REGISTER', 'UNDO'} angle_limit = FloatProperty(name="Angle Limit", - description="lower for more projection groups, higher for less distortion.", + description="lower for more projection groups, higher for less distortion", default=66.0, min=1.0, max=89.0) island_margin = FloatProperty(name="Island Margin", - description="Margin to reduce bleed from adjacent islands.", + description="Margin to reduce bleed from adjacent islands", + default=0.0, min=0.0, max=1.0) + + user_area_weight = FloatProperty(name="Area Weight", + description="Weight projections vector by faces with larger areas", default=0.0, min=0.0, max=1.0) @classmethod @@ -1133,7 +1145,11 @@ class SmartProject(bpy.types.Operator): return context.active_object != None def execute(self, context): - main(context, self.island_margin, self.angle_limit) + main(context, + self.island_margin, + self.angle_limit, + self.user_area_weight, + ) return {'FINISHED'} def invoke(self, context, event): diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index fcc30ecbb4b..af33e45668c 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -19,7 +19,9 @@ # <pep8 compliant> import bpy -from bpy.props import StringProperty, BoolProperty, IntProperty, FloatProperty +from bpy.props import StringProperty, BoolProperty, IntProperty, \ + FloatProperty, EnumProperty + from rna_prop_ui import rna_idprop_ui_prop_get, rna_idprop_ui_prop_clear @@ -457,15 +459,76 @@ doc_id = StringProperty(name="Doc ID", doc_new = StringProperty(name="Edit Description", description="", maxlen=1024, default="") +data_path_iter = StringProperty( + description="The data path relative to the context, must point to an iterable.") + +data_path_item = StringProperty( + description="The data path from each iterable to the value (int or float)") + + +class WM_OT_context_collection_boolean_set(bpy.types.Operator): + '''Set boolean values for a collection of items''' + bl_idname = "wm.context_collection_boolean_set" + bl_label = "Context Collection Boolean Set" + bl_options = {'UNDO', 'REGISTER', 'INTERNAL'} + + data_path_iter = data_path_iter + data_path_item = data_path_item + + type = EnumProperty(items=( + ('TOGGLE', "Toggle", ""), + ('ENABLE', "Enable", ""), + ('DISABLE', "Disable", ""), + ), + name="Type") + + def execute(self, context): + data_path_iter = self.data_path_iter + data_path_item = self.data_path_item + + items = list(getattr(context, data_path_iter)) + items_ok = [] + is_set = False + for item in items: + try: + value_orig = eval("item." + data_path_item) + except: + continue + + if value_orig == True: + is_set = True + elif value_orig == False: + pass + else: + self.report({'WARNING'}, "Non boolean value found: %s[ ].%s" % + (data_path_iter, data_path_item)) + return {'CANCELLED'} + + items_ok.append(item) + + if self.type == 'ENABLE': + is_set = True + elif self.type == 'DISABLE': + is_set = False + else: + is_set = not is_set + + exec_str = "item.%s = %s" % (data_path_item, is_set) + for item in items_ok: + exec(exec_str) + + return {'FINISHED'} + class WM_OT_context_modal_mouse(bpy.types.Operator): '''Adjust arbitrary values with mouse input''' bl_idname = "wm.context_modal_mouse" bl_label = "Context Modal Mouse" - bl_options = {'INTERNAL'} + bl_options = {'GRAB_POINTER', 'BLOCKING', 'INTERNAL'} + + data_path_iter = data_path_iter + data_path_item = data_path_item - data_path_iter = StringProperty(description="The data path relative to the context, must point to an iterable.") - data_path_item = StringProperty(description="The data path from each iterable to the value (int or float)") input_scale = FloatProperty(default=0.01, description="Scale the mouse movement by this value before applying the delta") invert = BoolProperty(default=False, description="Invert the mouse input") initial_x = IntProperty(options={'HIDDEN'}) diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 8c966825aee..618a88f0879 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -290,9 +290,8 @@ class DATA_PT_texface(MeshButtonsPanel, bpy.types.Panel): @classmethod def poll(cls, context): - ob = context.active_object - - return (context.mode == 'EDIT_MESH') and ob and ob.type == 'MESH' + obj = context.object + return (context.mode == 'EDIT_MESH') and obj and obj.type == 'MESH' def draw(self, context): layout = self.layout diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index 52d6b5f1376..45c15bd1ce6 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -729,6 +729,7 @@ class MATERIAL_PT_options(MaterialButtonsPanel, bpy.types.Panel): col.prop(mat, "use_vertex_color_paint") col.prop(mat, "use_vertex_color_light") col.prop(mat, "use_object_color") + col.prop(mat, "pass_index") class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel): @@ -883,7 +884,7 @@ class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel): sub = col.column() sub.enabled = True sub.active = False - sub.prop(vol, "use_light_cache") + sub.label("Light Cache Enabled") col.prop(vol, "cache_resolution") sub = col.column(align=True) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 63333083cb2..4c92296dacd 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -879,6 +879,15 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel): col = row.column() col.prop(part, "billboard_offset") + row = layout.row() + col = row.column() + col.prop(part, "billboard_size", text="Scale") + if part.billboard_align == 'VEL': + col = row.column(align=True) + col.label("Velocity Scale:") + col.prop(part, "billboard_velocity_head", text="Head") + col.prop(part, "billboard_velocity_tail", text="Tail") + if psys: col = layout.column() col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_textures") diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 9ff4470641b..3ba54aa67c6 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -141,6 +141,7 @@ class RENDER_PT_layers(RenderButtonsPanel, bpy.types.Panel): col.prop(rl, "use_pass_uv") col.prop(rl, "use_pass_mist") col.prop(rl, "use_pass_object_index") + col.prop(rl, "use_pass_material_index") col.prop(rl, "use_pass_color") col = split.column() diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 9f69ca17076..b1322d453fc 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -616,10 +616,9 @@ class IMAGE_PT_view_properties(bpy.types.Panel): split = layout.split() col = split.column() + col.prop(uvedit, "show_faces") col.prop(uvedit, "show_smooth_edges", text="Smooth") col.prop(uvedit, "show_modified_edges", text="Modified") - #col.prop(uvedit, "show_edges") - #col.prop(uvedit, "show_faces") col = split.column() col.prop(uvedit, "show_stretch", text="Stretch") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index dd5b8438cb2..0514d7a06d3 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -850,7 +850,7 @@ class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel): class USERPREF_MT_addons_dev_guides(bpy.types.Menu): - bl_label = "Develoment Guides" + bl_label = "Development Guides" # menu to open webpages with addons development guides def draw(self, context): @@ -877,6 +877,19 @@ class USERPREF_PT_addons(bpy.types.Panel): def module_get(mod_name): return USERPREF_PT_addons._addons_fake_modules[mod_name] + @staticmethod + def is_user_addon(mod, user_addon_paths): + if not user_addon_paths: + user_script_path = bpy.utils.user_script_path() + if user_script_path is not None: + user_addon_paths.append(os.path.join(user_script_path(), "addons")) + user_addon_paths.append(os.path.join(bpy.utils.resource_path('USER'), "scripts", "addons")) + + for path in user_addon_paths: + if bpy.path.is_subdir(mod.__file__, path): + return True + return False + def draw(self, context): layout = self.layout @@ -901,6 +914,9 @@ class USERPREF_PT_addons(bpy.types.Panel): search = context.window_manager.addon_search.lower() support = context.window_manager.addon_support + # initialized on demand + user_addon_paths = [] + for mod, info in addons: module_name = mod.__name__ @@ -970,20 +986,24 @@ class USERPREF_PT_addons(bpy.types.Panel): split = colsub.row().split(percentage=0.15) split.label(text="Warning:") split.label(text=' ' + info["warning"], icon='ERROR') - if info["wiki_url"] or info["tracker_url"]: + + user_addon = __class__.is_user_addon(mod, user_addon_paths) + tot_row = bool(info["wiki_url"]) + bool(info["tracker_url"]) + bool(user_addon) + + if tot_row: split = colsub.row().split(percentage=0.15) split.label(text="Internet:") if info["wiki_url"]: split.operator("wm.url_open", text="Link to the Wiki", icon='HELP').url = info["wiki_url"] if info["tracker_url"]: split.operator("wm.url_open", text="Report a Bug", icon='URL').url = info["tracker_url"] + if user_addon: + split.operator("wm.addon_remove", text="Remove", icon='CANCEL').module = mod.__name__ - if info["wiki_url"] and info["tracker_url"]: - split.separator() - else: - split.separator() + for i in range(4 - tot_row): split.separator() + # Append missing scripts # First collect scripts that are used but have no script file. module_names = {mod.__name__ for mod, info in addons} @@ -1187,6 +1207,54 @@ class WM_OT_addon_install(bpy.types.Operator): return {'RUNNING_MODAL'} +class WM_OT_addon_remove(bpy.types.Operator): + "Disable an addon" + bl_idname = "wm.addon_remove" + bl_label = "Remove Add-On" + + module = StringProperty(name="Module", description="Module name of the addon to remove") + + @staticmethod + def path_from_addon(module): + for mod in addon_utils.modules(USERPREF_PT_addons._addons_fake_modules): + if mod.__name__ == module: + filepath = mod.__file__ + if os.path.exists(filepath): + if os.path.splitext(os.path.basename(filepath))[0] == "__init__": + return os.path.dirname(filepath), True + else: + return filepath, False + return None, False + + def execute(self, context): + path, isdir = __class__.path_from_addon(self.module) + if path is None: + self.report('WARNING', "Addon path %r could not be found" % path) + return {'CANCELLED'} + + # incase its enabled + addon_utils.disable(self.module) + + import shutil + if isdir: + shutil.rmtree(path) + else: + os.remove(path) + + context.area.tag_redraw() + return {'FINISHED'} + + # lame confirmation check + def draw(self, context): + self.layout.label(text="Remove Addon: %r?" % self.module) + path, isdir = __class__.path_from_addon(self.module) + self.layout.label(text="Path: %r" % path) + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_props_dialog(self, width=600) + + class WM_OT_addon_expand(bpy.types.Operator): "Display more information on this add-on" bl_idname = "wm.addon_expand" diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 44b75f6d75e..8dd28909595 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -778,10 +778,16 @@ class VIEW3D_MT_object_specials(bpy.types.Menu): if obj.type == 'CAMERA': layout.operator_context = 'INVOKE_REGION_WIN' - props = layout.operator("wm.context_modal_mouse", text="Camera Lens Angle") - props.data_path_iter = "selected_editable_objects" - props.data_path_item = "data.lens" - props.input_scale = 0.1 + if obj.data.type == 'PERSP': + props = layout.operator("wm.context_modal_mouse", text="Camera Lens Angle") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.lens" + props.input_scale = 0.1 + else: + props = layout.operator("wm.context_modal_mouse", text="Camera Lens Scale") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.ortho_scale" + props.input_scale = 0.01 if not obj.data.dof_object: #layout.label(text="Test Has DOF obj"); @@ -1104,17 +1110,18 @@ class VIEW3D_MT_sculpt(bpy.types.Menu): layout.operator_menu_enum("brush.curve_preset", "shape") layout.separator() - sculpt_tool = brush.sculpt_tool + if brush is not None: # unlikely but can happen + sculpt_tool = brush.sculpt_tool - if sculpt_tool != 'GRAB': - layout.prop_menu_enum(brush, "stroke_method") + if sculpt_tool != 'GRAB': + layout.prop_menu_enum(brush, "stroke_method") - if sculpt_tool in {'DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'}: - layout.prop_menu_enum(brush, "direction") + if sculpt_tool in {'DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'}: + layout.prop_menu_enum(brush, "direction") - if sculpt_tool == 'LAYER': - layout.prop(brush, "use_persistent") - layout.operator("sculpt.set_persistent_base") + if sculpt_tool == 'LAYER': + layout.prop(brush, "use_persistent") + layout.operator("sculpt.set_persistent_base") layout.separator() layout.prop(sculpt, "use_threaded", text="Threaded Sculpt") @@ -1249,7 +1256,7 @@ class VIEW3D_MT_pose(bpy.types.Menu): layout.separator() layout.menu("VIEW3D_MT_pose_showhide") - layout.operator_menu_enum("pose.flags_set", 'mode', text="Bone Settings") + layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings") class VIEW3D_MT_pose_transform(bpy.types.Menu): @@ -1370,6 +1377,49 @@ class VIEW3D_MT_pose_apply(bpy.types.Menu): layout.operator("pose.visual_transform_apply") +class BoneOptions: + def draw(self, context): + layout = self.layout + + options = [ + "show_wire", + "use_deform", + "use_envelope_multiply", + "use_inherit_rotation", + "use_inherit_scale", + ] + + if context.mode == 'EDIT_ARMATURE': + bone_props = bpy.types.EditBone.bl_rna.properties + data_path_iter = "selected_bones" + opt_suffix = "" + options.append("lock") + else: # posemode + bone_props = bpy.types.Bone.bl_rna.properties + data_path_iter = "selected_pose_bones" + opt_suffix = "bone." + + for opt in options: + props = layout.operator("wm.context_collection_boolean_set", text=bone_props[opt].name) + props.data_path_iter = data_path_iter + props.data_path_item = opt_suffix + opt + props.type = self.type + + +class VIEW3D_MT_bone_options_toggle(bpy.types.Menu, BoneOptions): + bl_label = "Toggle Bone Options" + type = 'TOGGLE' + + +class VIEW3D_MT_bone_options_enable(bpy.types.Menu, BoneOptions): + bl_label = "Enable Bone Options" + type = 'ENABLE' + + +class VIEW3D_MT_bone_options_disable(bpy.types.Menu, BoneOptions): + bl_label = "Disable Bone Options" + type = 'DISABLE' + # ********** Edit Menus, suffix from ob.type ********** @@ -1963,7 +2013,7 @@ class VIEW3D_MT_edit_armature(bpy.types.Menu): layout.separator() - layout.operator_menu_enum("armature.flags_set", "mode", text="Bone Settings") + layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings") class VIEW3D_MT_armature_specials(bpy.types.Menu): diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 503a1d806ac..52eb76d0710 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -997,7 +997,11 @@ class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel): @classmethod def poll(cls, context): - return (context.sculpt_object and context.tool_settings.sculpt) or (context.vertex_paint_object and context.tool_settings.vertex_paint) or (context.weight_paint_object and context.tool_settings.weight_paint) or (context.image_paint_object and context.tool_settings.image_paint) + ts = context.tool_settings + return ((context.sculpt_object and ts.sculpt) or + (context.vertex_paint_object and ts.vertex_paint) or + (context.weight_paint_object and ts.weight_paint) or + (context.image_paint_object and ts.image_paint)) def draw(self, context): layout = self.layout @@ -1005,6 +1009,10 @@ class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel): settings = __class__.paint_settings(context) brush = settings.brush + if brush is None: # unlikely but can happen + layout.label(text="Brush Unset") + return + col = layout.column() if context.sculpt_object and context.tool_settings.sculpt: |