Merged changes in the trunk up to revision 45133.

Conflicts resolved:
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/intern/bmesh_construct.c
source/blender/bmesh/intern/bmesh_mesh_conv.c
source/blender/bmesh/intern/bmesh_mesh_conv.h
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/resources.c
source/blender/editors/mesh/bmesh_select.c
source/blender/editors/mesh/bmesh_tools.c
source/blender/editors/space_view3d/drawobject.c
source/blender/render/intern/source/shadeoutput.c
This commit is contained in:
Tamito Kajiyama
2012-03-25 08:20:19 +00:00
1200 changed files with 77004 additions and 63870 deletions

View File

@@ -118,6 +118,14 @@ def clean_name(name, replace="_"):
return name
def _clean_utf8(name):
name = _os.path.splitext(basename(name))[0]
if type(name) == bytes:
return name.decode("utf8", "replace")
else:
return name.encode("utf8", "replace").decode("utf8")
def display_name(name):
"""
Creates a display string from name to be used menus and the user interface.
@@ -126,17 +134,18 @@ def display_name(name):
filenames and module names.
"""
name_base = _os.path.splitext(name)[0]
name = _os.path.splitext(name)[0]
# string replacements
name_base = name_base.replace("_colon_", ":")
name = name.replace("_colon_", ":")
name_base = name_base.replace("_", " ")
name = name.replace("_", " ")
if name_base.islower():
return name_base.lower().title()
else:
return name_base
if name.islower():
name = name.lower().title()
name = _clean_utf8(name)
return name
def display_name_from_filepath(name):
@@ -144,8 +153,10 @@ def display_name_from_filepath(name):
Returns the path stripped of directory and extension,
ensured to be utf8 compatible.
"""
name = _os.path.splitext(basename(name))[0]
return name.encode("utf8", "replace").decode("utf8")
name = _clean_utf8(name)
return name
def resolve_ncase(path):

View File

@@ -19,17 +19,17 @@
# <pep8-80 compliant>
__all__ = (
"mesh_linked_faces",
"mesh_linked_tessfaces",
"edge_face_count_dict",
"edge_face_count",
"edge_loops_from_faces",
"edge_loops_from_tessfaces",
"edge_loops_from_edges",
"ngon_tesselate",
"ngon_tessellate",
"face_random_points",
)
def mesh_linked_faces(mesh):
def mesh_linked_tessfaces(mesh):
"""
Splits the mesh into connected faces, use this for seperating cubes from
other mesh elements within 1 mesh datablock.
@@ -42,20 +42,20 @@ def mesh_linked_faces(mesh):
# Build vert face connectivity
vert_faces = [[] for i in range(len(mesh.vertices))]
for f in mesh.faces:
for f in mesh.tessfaces:
for v in f.vertices:
vert_faces[v].append(f)
# sort faces into connectivity groups
face_groups = [[f] for f in mesh.faces]
face_mapping = list(range(len(mesh.faces))) # map old, new face location
face_groups = [[f] for f in mesh.tessfaces]
face_mapping = list(range(len(mesh.tessfaces))) # map old, new face location
# Now clump faces iteratively
ok = True
while ok:
ok = False
for i, f in enumerate(mesh.faces):
for i, f in enumerate(mesh.tessfaces):
mapped_index = face_mapping[f.index]
mapped_group = face_groups[mapped_index]
@@ -90,7 +90,7 @@ def edge_face_count_dict(mesh):
faces using each edge.
:rtype: dict
"""
face_edge_keys = [face.edge_keys for face in mesh.faces]
face_edge_keys = [face.edge_keys for face in mesh.tessfaces]
face_edge_count = {}
for face_keys in face_edge_keys:
for key in face_keys:
@@ -112,11 +112,11 @@ def edge_face_count(mesh):
return [get(edge_face_count, ed.key, 0) for ed in mesh.edges]
def edge_loops_from_faces(mesh, faces=None, seams=()):
def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()):
"""
Edge loops defined by faces
Takes me.faces or a list of faces and returns the edge loops
Takes me.tessfaces or a list of faces and returns the edge loops
These edge loops are the edges that sit between quads, so they dont touch
1 quad, note: not connected will make 2 edge loops,
both only containing 2 edges.
@@ -126,20 +126,20 @@ def edge_loops_from_faces(mesh, faces=None, seams=()):
:arg mesh: the mesh used to get edge loops from.
:type mesh: :class:`bpy.types.Mesh`
:arg faces: optional face list to only use some of the meshes faces.
:type faces: :class:`bpy.types.MeshFaces`, sequence or or NoneType
:arg tessfaces: optional face list to only use some of the meshes faces.
:type tessfaces: :class:`bpy.types.MeshTessFace`, sequence or or NoneType
:return: return a list of edge vertex index lists.
:rtype: list
"""
OTHER_INDEX = 2, 3, 0, 1 # opposite face index
if faces is None:
faces = mesh.faces
if tessfaces is None:
tessfaces = mesh.tessfaces
edges = {}
for f in faces:
for f in tessfaces:
if len(f.vertices) == 4:
edge_keys = f.edge_keys
for i, edkey in enumerate(f.edge_keys):
@@ -256,7 +256,7 @@ def edge_loops_from_edges(mesh, edges=None):
return line_polys
def ngon_tesselate(from_data, indices, fix_loops=True):
def ngon_tessellate(from_data, indices, fix_loops=True):
'''
Takes a polyline of indices (fgon) and returns a list of face
indicie lists. Designed to be used for importers that need indices for an
@@ -269,7 +269,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
polylines are delt with correctly.
'''
from mathutils.geometry import tesselate_polygon
from mathutils.geometry import tessellate_polygon
from mathutils import Vector
vector_to_tuple = Vector.to_tuple
@@ -303,7 +303,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
if verts[i][1] == verts[i - 1][0]:
verts.pop(i - 1)
fill = tesselate_polygon([verts])
fill = tessellate_polygon([verts])
else:
'''
@@ -411,7 +411,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
vert_map[i + ii] = vert[2]
ii += len(verts)
fill = tesselate_polygon([[v[0] for v in loop] for loop in loop_list])
fill = tessellate_polygon([[v[0] for v in loop] for loop in loop_list])
#draw_loops(loop_list)
#raise 'done loop'
# map to original indices
@@ -442,14 +442,14 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
return fill
def face_random_points(num_points, faces):
def face_random_points(num_points, tessfaces):
"""
Generates a list of random points over mesh faces.
Generates a list of random points over mesh tessfaces.
:arg num_points: the number of random points to generate on each face.
:type int:
:arg faces: list of the faces to generate points on.
:type faces: :class:`bpy.types.MeshFaces`, sequence
:arg tessfaces: list of the faces to generate points on.
:type tessfaces: :class:`bpy.types.MeshTessFace`, sequence
:return: list of random points over all faces.
:rtype: list
"""
@@ -459,7 +459,7 @@ def face_random_points(num_points, faces):
# Split all quads into 2 tris, tris remain unchanged
tri_faces = []
for f in faces:
for f in tessfaces:
tris = []
verts = f.id_data.vertices
fv = f.vertices[:]
@@ -475,7 +475,7 @@ def face_random_points(num_points, faces):
tri_faces.append(tris)
# For each face, generate the required number of random points
sampled_points = [None] * (num_points * len(faces))
sampled_points = [None] * (num_points * len(tessfaces))
for i, tf in enumerate(tri_faces):
for k in range(num_points):
# If this is a quad, we need to weight its 2 tris by their area

View File

@@ -21,12 +21,15 @@
__all__ = (
"add_object_align_init",
"object_data_add",
"AddObjectHelper",
)
import bpy
import mathutils
from bpy.props import BoolProperty, FloatVectorProperty
def add_object_align_init(context, operator):
"""
@@ -116,11 +119,12 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
v3d = context.space_data
if use_active_layer:
if v3d.local_view:
if v3d and v3d.local_view:
base.layers_from_view(context.space_data)
base.layers[scene.active_layer] = True
else:
base.layers = [True if i == scene.active_layer else False for i in range(len(scene.layers))]
base.layers = [True if i == scene.active_layer
else False for i in range(len(scene.layers))]
if v3d:
base.layers_from_view(context.space_data)
@@ -163,3 +167,23 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
bpy.ops.object.mode_set(mode='EDIT')
return base
class AddObjectHelper:
def view_align_update_callback(self, context):
if not self.view_align:
self.rotation.zero()
view_align = BoolProperty(
name="Align to View",
default=False,
update=view_align_update_callback,
)
location = FloatVectorProperty(
name="Location",
subtype='TRANSLATION',
)
rotation = FloatVectorProperty(
name="Rotation",
subtype='EULER',
)

View File

@@ -411,7 +411,7 @@ class MeshEdge(StructRNA):
return ord_ind(*tuple(self.vertices))
class MeshFace(StructRNA):
class MeshTessFace(StructRNA):
__slots__ = ()
@property

View File

@@ -412,6 +412,7 @@
keyframe="#ff8500"
meta_strip="#6d9183"
movie_strip="#516987"
movieclip_strip="#20208f"
plugin_strip="#7e7e50"
scene_strip="#4e983e"
transition_strip="#a25f6f"

View File

@@ -412,6 +412,7 @@
keyframe="#ff8500"
meta_strip="#6d9183"
movie_strip="#516987"
movieclip_strip="#20208f"
plugin_strip="#7e7e50"
scene_strip="#4e983e"
transition_strip="#a25f6f"

View File

@@ -412,6 +412,7 @@
keyframe="#ff8500"
meta_strip="#6d9183"
movie_strip="#516987"
movieclip_strip="#20208f"
plugin_strip="#7e7e50"
scene_strip="#4e983e"
transition_strip="#a25f6f"

View File

@@ -412,6 +412,7 @@
keyframe="#ff8500"
meta_strip="#6d9183"
movie_strip="#516987"
movieclip_strip="#20208f"
plugin_strip="#7e7e50"
scene_strip="#4e983e"
transition_strip="#a25f6f"

View File

@@ -412,6 +412,7 @@
keyframe="#f47421"
meta_strip="#6d9183"
movie_strip="#516987"
movieclip_strip="#20208f"
plugin_strip="#7e7e50"
scene_strip="#4e983e"
transition_strip="#a25f6f"

View File

@@ -21,6 +21,14 @@ import bpy
from bpy.types import Operator
import mathutils
from bpy.props import (FloatProperty,
IntProperty,
BoolProperty,
FloatVectorProperty,
)
from bpy_extras import object_utils
def add_torus(major_rad, minor_rad, major_seg, minor_seg):
from math import cos, sin, pi
@@ -75,14 +83,8 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
return verts, faces
from bpy.props import (FloatProperty,
IntProperty,
BoolProperty,
FloatVectorProperty,
)
class AddTorus(Operator):
class AddTorus(Operator, object_utils.AddObjectHelper):
'''Add a torus mesh'''
bl_idname = "mesh.primitive_torus_add"
bl_label = "Add Torus"
@@ -131,22 +133,7 @@ class AddTorus(Operator):
default=0.5,
)
# generic transform props
view_align = BoolProperty(
name="Align to View",
default=False,
)
location = FloatVectorProperty(
name="Location",
subtype='TRANSLATION',
)
rotation = FloatVectorProperty(
name="Rotation",
subtype='EULER',
)
def execute(self, context):
if self.use_abso == True:
extra_helper = (self.abso_major_rad - self.abso_minor_rad) * 0.5
self.major_radius = self.abso_minor_rad + extra_helper
@@ -160,13 +147,14 @@ class AddTorus(Operator):
mesh = bpy.data.meshes.new("Torus")
mesh.vertices.add(len(verts_loc) // 3)
# BMESH_TODO, use polygons
mesh.faces.add(len(faces) // 4)
mesh.vertices.foreach_set("co", verts_loc)
mesh.faces.foreach_set("vertices_raw", faces)
mesh.update()
from bpy_extras import object_utils
object_utils.object_data_add(context, mesh, operator=self)
return {'FINISHED'}

View File

@@ -716,6 +716,7 @@ class CLIP_OT_setup_tracking_scene(Operator):
mesh.vertices.add(len(vertices))
mesh.vertices.foreach_set("co", unpack_list(vertices))
# BMESH_TODO - use polygons
mesh.faces.add(len(faces))
mesh.faces.foreach_set("vertices_raw", unpack_face_list(faces))

View File

@@ -82,6 +82,7 @@ class MeshMirrorUV(Operator):
for uv in fuvs]
# as a list
# BMESH_TODO - use polygons
faces = mesh.faces[:]
fuvsel = [(False not in uv.select_uv) for uv in active_uv_layer]

View File

@@ -367,6 +367,7 @@ class ShapeTransfer(Operator):
(orig_shape_coords[i] - orig_coords[i]))
elif mode == 'RELATIVE_FACE':
# BMESH TODO - use .polygons
for face in me.faces:
i1, i2, i3, i4 = face.vertices_raw
if i4 != 0:
@@ -539,6 +540,7 @@ class JoinUVs(Operator):
"Object: %s, Mesh: '%s' has no UVs"
% (obj.name, mesh.name))
else:
# BMESH_TODO - use polygons
len_faces = len(mesh.faces)
# seems to be the fastest way to create an array

View File

@@ -20,6 +20,7 @@
import bpy
from bpy.types import Menu, Operator
from bpy.props import StringProperty, BoolProperty
class AddPresetBase():
@@ -31,13 +32,13 @@ class AddPresetBase():
# bl_label = "Add a Python Preset"
bl_options = {'REGISTER'} # only because invoke_props_popup requires.
name = bpy.props.StringProperty(
name = StringProperty(
name="Name",
description="Name of the preset, used to make the path name",
maxlen=64,
options={'SKIP_SAVE'},
)
remove_active = bpy.props.BoolProperty(
remove_active = BoolProperty(
default=False,
options={'HIDDEN', 'SKIP_SAVE'},
)
@@ -166,12 +167,10 @@ class ExecutePreset(Operator):
bl_idname = "script.execute_preset"
bl_label = "Execute a Python Preset"
filepath = bpy.props.StringProperty(
name="Path",
description="Path of the Python file to execute",
maxlen=512,
filepath = StringProperty(
subtype='FILE_PATH',
)
menu_idname = bpy.props.StringProperty(
menu_idname = StringProperty(
name="Menu ID Name",
description="ID name of the menu this was called from",
)
@@ -456,7 +455,7 @@ class AddPresetOperator(AddPresetBase, Operator):
bl_label = "Operator Preset"
preset_menu = "WM_MT_operator_presets"
operator = bpy.props.StringProperty(
operator = StringProperty(
name="Operator",
maxlen=64,
options={'HIDDEN'},

View File

@@ -168,7 +168,7 @@ def extend(obj, operator, EXTEND_MODE):
edge_faces[edkey] = [i]
if EXTEND_MODE == 'LENGTH':
edge_loops = mesh_utils.edge_loops_from_faces(me, face_sel, [ed.key for ed in me.edges if ed.use_seam])
edge_loops = mesh_utils.edge_loops_from_tessfaces(me, face_sel, [ed.key for ed in me.edges if ed.use_seam])
me_verts = me.vertices
for loop in edge_loops:
looplen = [0.0]

View File

@@ -156,19 +156,19 @@ class VertexPaintDirt(Operator):
)
clean_angle = FloatProperty(
name="Highlight Angle",
description="Less then 90 limits the angle used in the tonal range",
description="Less than 90 limits the angle used in the tonal range",
min=0.0, max=180.0,
default=180.0,
)
dirt_angle = FloatProperty(
name="Dirt Angle",
description="Less then 90 limits the angle used in the tonal range",
description="Less than 90 limits the angle used in the tonal range",
min=0.0, max=180.0,
default=0.0,
)
dirt_only = BoolProperty(
name="Dirt Only",
description="Dont calculate cleans for convex areas",
description="Don't calculate cleans for convex areas",
default=False,
)

View File

@@ -206,8 +206,10 @@ class BONE_PT_display(BoneButtonsPanel, Panel):
split = layout.split()
col = split.column()
col.prop(bone, "show_wire", text="Wireframe")
col.prop(bone, "hide", text="Hide")
sub = col.column()
sub.active = bool(pchan.custom_shape)
sub.prop(bone, "show_wire", text="Wireframe")
if pchan:
col = split.column()

View File

@@ -162,7 +162,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
row = layout.row()
sub = row.row(align=True)
sub.operator("object.vertex_group_assign", text="Assign")
sub.operator("object.vertex_group_assign", text="Assign").new = False
sub.operator("object.vertex_group_remove_from", text="Remove")
sub = row.row(align=True)

View File

@@ -124,9 +124,11 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
split.prop(md, "use_only_vertices")
# -- new modifier only, this may be reverted in favor of 2.62 mod.
'''
split = layout.split()
split.prop(md, "use_even_offset")
split.prop(md, "use_distance_offset")
'''
# -- end
layout.label(text="Limit Method:")

View File

@@ -90,7 +90,7 @@ class OBJECT_PT_delta_transform(ObjectButtonsPanel, Panel):
#row.column().prop(ob, "delta_rotation_axis_angle", text="Rotation")
row.column().label(text="Not for Axis-Angle")
else:
row.column().prop(ob, "delta_rotation_euler", text="Rotation")
row.column().prop(ob, "delta_rotation_euler", text="Delta Rotation")
row.column().prop(ob, "delta_scale")
@@ -211,8 +211,11 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
col = split.column()
col.prop(ob, "show_name", text="Name")
col.prop(ob, "show_axis", text="Axis")
col.prop(ob, "show_wire", text="Wire")
col.prop(ob, "color", text="Object Color")
if ob.type in {"MESH", "CURVE", "SURFACE", "META", "FONT"}:
# Makes no sense for cameras, armtures, etc.!
col.prop(ob, "show_wire", text="Wire")
# Only useful with object having faces/materials...
col.prop(ob, "color", text="Object Color")
col = split.column()
col.prop(ob, "show_texture_space", text="Texture Space")

View File

@@ -380,6 +380,7 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
bl_label = "Rotation"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@classmethod
@@ -394,6 +395,15 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
else:
return False
def draw_header(self, context):
psys = context.particle_system
if psys:
part = psys.settings
else:
part = context.space_data.pin_id
self.layout.prop(part, "use_rotations", text="")
def draw(self, context):
layout = self.layout
@@ -403,14 +413,9 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
else:
part = context.space_data.pin_id
layout.enabled = particle_panel_enabled(context, psys)
layout.enabled = particle_panel_enabled(context, psys) and part.use_rotations
layout.prop(part, "use_dynamic_rotation")
if part.use_dynamic_rotation:
layout.label(text="Initial Rotation Axis:")
else:
layout.label(text="Rotation Axis:")
layout.label(text="Initial Orientation:")
split = layout.split()
@@ -423,16 +428,17 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
col.prop(part, "phase_factor_random", text="Random", slider=True)
if part.type != 'HAIR':
col = layout.column()
if part.use_dynamic_rotation:
col.label(text="Initial Angular Velocity:")
else:
col.label(text="Angular Velocity:")
sub = col.row(align=True)
sub.prop(part, "angular_velocity_mode", text="")
subsub = sub.column()
subsub.active = part.angular_velocity_mode != 'NONE'
subsub.prop(part, "angular_velocity_factor", text="")
layout.label(text="Angular Velocity:")
split = layout.split()
col = split.column(align=True)
col.prop(part, "angular_velocity_mode", text="")
sub = col.column()
sub.active = part.angular_velocity_mode != 'NONE'
sub.prop(part, "angular_velocity_factor", text="")
col = split.column()
col.prop(part, "use_dynamic_rotation")
class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):

View File

@@ -985,8 +985,7 @@ class CLIP_MT_select(Menu):
layout.separator()
props = layout.operator("clip.select_all", text="Select/Deselect all")
props.action = 'TOGGLE'
layout.operator("clip.select_all").action = 'TOGGLE'
layout.operator("clip.select_all", text="Inverse").action = 'INVERT'
layout.menu("CLIP_MT_select_grouped")

View File

@@ -97,7 +97,7 @@ class IMAGE_MT_select(Menu):
layout.separator()
layout.operator("uv.select_all")
layout.operator("uv.select_all").action = 'TOGGLE'
layout.operator("uv.select_all", text="Inverse").action = 'INVERT'
layout.operator("uv.unlink_selected")

View File

@@ -109,43 +109,43 @@ class INFO_MT_file(Menu):
layout.operator("wm.read_homefile", text="New", icon='NEW')
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
layout.menu("INFO_MT_file_open_recent")
layout.menu("INFO_MT_file_open_recent", icon='OPEN_RECENT')
layout.operator("wm.recover_last_session", icon='RECOVER_LAST')
layout.operator("wm.recover_auto_save", text="Recover Auto Save...")
layout.operator("wm.recover_auto_save", text="Recover Auto Save...", icon='RECOVER_AUTO')
layout.separator()
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK').check_existing = False
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.save_as_mainfile", text="Save As...")
layout.operator("wm.save_as_mainfile", text="Save As...", icon='SAVE_AS')
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.save_as_mainfile", text="Save Copy...").copy = True
layout.operator("wm.save_as_mainfile", text="Save Copy...", icon='SAVE_COPY').copy = True
layout.separator()
layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES')
layout.operator_context = 'EXEC_AREA'
layout.operator("wm.save_homefile")
layout.operator("wm.read_factory_settings")
layout.operator("wm.save_homefile", icon='SAVE_PREFS')
layout.operator("wm.read_factory_settings", icon='LOAD_FACTORY')
layout.separator()
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.link_append", text="Link")
props = layout.operator("wm.link_append", text="Append")
layout.operator("wm.link_append", text="Link", icon='LINK_BLEND')
props = layout.operator("wm.link_append", text="Append", icon='APPEND_BLEND')
props.link = False
props.instance_groups = False
layout.separator()
layout.menu("INFO_MT_file_import")
layout.menu("INFO_MT_file_export")
layout.menu("INFO_MT_file_import", icon='IMPORT')
layout.menu("INFO_MT_file_export", icon='EXPORT')
layout.separator()
layout.menu("INFO_MT_file_external_data")
layout.menu("INFO_MT_file_external_data", icon='EXTERNAL_DATA')
layout.separator()

View File

@@ -185,6 +185,12 @@ class SEQUENCER_MT_add(Menu):
else:
layout.operator_menu_enum("sequencer.scene_strip_add", "scene", text="Scene...")
if len(bpy.data.movieclips) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("sequencer.movieclip_strip_add", text="Clips...")
else:
layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip...")
layout.operator("sequencer.movie_strip_add", text="Movie")
layout.operator("sequencer.image_strip_add", text="Image")
layout.operator("sequencer.sound_strip_add", text="Sound")
@@ -236,6 +242,7 @@ class SEQUENCER_MT_strip(Menu):
layout.operator("sequencer.offset_clear")
layout.operator("sequencer.deinterlace_selected_movies")
layout.operator("sequencer.rebuild_proxy")
layout.operator("sequencer.update_strip_length")
layout.separator()
layout.operator("sequencer.duplicate")
@@ -534,7 +541,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
if not strip:
return False
return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META',
return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'META',
'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
@@ -697,7 +704,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
if not strip:
return False
return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META',
return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'META',
'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
@@ -713,6 +720,15 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
col.label(text="Video:")
col.prop(strip, "strobe")
if strip.type == 'MOVIECLIP':
col = layout.column()
col.label(text="Tracker:")
col.prop(strip, "stabilize2d")
col = layout.column()
col.label(text="Distortion:")
col.prop(strip, "undistort")
row = layout.row()
row.label(text="Flip:")
row.prop(strip, "use_flip_x", text="X")

View File

@@ -244,6 +244,9 @@ class USERPREF_PT_interface(Panel):
col.prop(view, "show_splash")
if os.name == 'nt':
col.prop(view, "quit_dialog")
class USERPREF_PT_edit(Panel):
bl_space_type = 'USER_PREFERENCES'
@@ -301,6 +304,11 @@ class USERPREF_PT_edit(Panel):
col.separator()
col.label(text="Playback:")
col.prop(edit, "use_negative_frames")
col.separator()
col.separator()
col.separator()
col.label(text="Animation Editors:")
col.prop(edit, "fcurve_unselected_alpha", text="F-Curve Visibility")
row.separator()
row.separator()
@@ -625,6 +633,14 @@ class USERPREF_PT_theme(Panel):
col.label(text="Menu Back:")
ui_items_general(col, ui)
ui = theme.user_interface.wcol_tooltip
col.label(text="Tooltip:")
ui_items_general(col, ui)
ui = theme.user_interface.wcol_tooltip
col.label(text="Tooltip:")
ui_items_general(col, ui)
ui = theme.user_interface.wcol_menu_item
col.label(text="Menu Item:")
ui_items_general(col, ui)

View File

@@ -54,6 +54,8 @@ class VIEW3D_HT_header(Header):
sub.menu("VIEW3D_MT_%s" % mode_string.lower())
if mode_string in {'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT', 'PAINT_TEXTURE'}:
sub.menu("VIEW3D_MT_brush")
if mode_string == 'SCULPT':
sub.menu("VIEW3D_MT_hide")
else:
sub.menu("VIEW3D_MT_object")
@@ -88,10 +90,10 @@ class VIEW3D_HT_header(Header):
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
row.prop(toolsettings, "snap_element", text="", icon_only=True)
if snap_element not in {'INCREMENT', 'VOLUME'}:
if snap_element != 'INCREMENT':
row.prop(toolsettings, "snap_target", text="")
if obj:
if obj.mode == 'OBJECT':
if obj.mode == 'OBJECT' and snap_element != 'VOLUME':
row.prop(toolsettings, "use_snap_align_rotation", text="")
elif obj.mode == 'EDIT':
row.prop(toolsettings, "use_snap_self", text="")
@@ -425,7 +427,7 @@ class VIEW3D_MT_select_object(Menu):
layout.separator()
layout.operator("object.select_all", text="Select/Deselect All").action = 'TOGGLE'
layout.operator("object.select_all").action = 'TOGGLE'
layout.operator("object.select_all", text="Inverse").action = 'INVERT'
layout.operator("object.select_random", text="Random")
layout.operator("object.select_mirror", text="Mirror")
@@ -450,7 +452,7 @@ class VIEW3D_MT_select_pose(Menu):
layout.separator()
layout.operator("pose.select_all", text="Select/Deselect All").action = 'TOGGLE'
layout.operator("pose.select_all").action = 'TOGGLE'
layout.operator("pose.select_all", text="Inverse").action = 'INVERT'
layout.operator("pose.select_flip_active", text="Flip Active")
layout.operator("pose.select_constraint_target", text="Constraint Target")
@@ -487,9 +489,9 @@ class VIEW3D_MT_select_particle(Menu):
layout.separator()
layout.operator("particle.select_all", text="Select/Deselect All").action = 'TOGGLE'
layout.operator("particle.select_all").action = 'TOGGLE'
layout.operator("particle.select_linked")
layout.operator("particle.select_all").action = 'INVERT'
layout.operator("particle.select_all", text="Inverse").action = 'INVERT'
layout.separator()
@@ -513,7 +515,7 @@ class VIEW3D_MT_select_edit_mesh(Menu):
layout.separator()
layout.operator("mesh.select_all", text="Select/Deselect All").action = 'TOGGLE'
layout.operator("mesh.select_all").action = 'TOGGLE'
layout.operator("mesh.select_all", text="Inverse").action = 'INVERT'
layout.separator()
@@ -564,7 +566,7 @@ class VIEW3D_MT_select_edit_curve(Menu):
layout.separator()
layout.operator("curve.select_all", text="Select/Deselect All").action = 'TOGGLE'
layout.operator("curve.select_all").action = 'TOGGLE'
layout.operator("curve.select_all", text="Inverse").action = 'INVERT'
layout.operator("curve.select_random")
layout.operator("curve.select_nth", text="Every Nth Number of Points")
@@ -593,7 +595,7 @@ class VIEW3D_MT_select_edit_surface(Menu):
layout.separator()
layout.operator("curve.select_all", text="Select/Deselect All").action = 'TOGGLE'
layout.operator("curve.select_all").action = 'TOGGLE'
layout.operator("curve.select_all", text="Inverse").action = 'INVERT'
layout.operator("curve.select_random")
layout.operator("curve.select_nth", text="Every Nth Number of Points")
@@ -619,7 +621,7 @@ class VIEW3D_MT_select_edit_metaball(Menu):
layout.separator()
layout.operator("mball.select_all").action = 'TOGGLE'
layout.operator("mball.select_all").action = 'INVERT'
layout.operator("mball.select_all", text="Inverse").action = 'INVERT'
layout.separator()
@@ -636,7 +638,8 @@ class VIEW3D_MT_select_edit_lattice(Menu):
layout.separator()
layout.operator("lattice.select_all", text="Select/Deselect All")
layout.operator("lattice.select_all").action = 'TOGGLE'
layout.operator("lattice.select_all", text="Inverse").action = 'INVERT'
class VIEW3D_MT_select_edit_armature(Menu):
@@ -649,7 +652,7 @@ class VIEW3D_MT_select_edit_armature(Menu):
layout.separator()
layout.operator("armature.select_all", text="Select/Deselect All").action = 'TOGGLE'
layout.operator("armature.select_all").action = 'TOGGLE'
layout.operator("armature.select_all", text="Inverse").action = 'INVERT'
layout.separator()
@@ -1046,6 +1049,19 @@ class VIEW3D_MT_brush(Menu):
ups = context.tool_settings.unified_paint_settings
layout.prop(ups, "use_unified_size", text="Unified Size")
layout.prop(ups, "use_unified_strength", text="Unified Strength")
layout.separator()
# brush paint modes
layout.menu("VIEW3D_MT_brush_paint_modes")
# brush tool
if context.sculpt_object:
layout.operator("brush.reset")
layout.prop_menu_enum(brush, "sculpt_tool")
elif context.image_paint_object:
layout.prop_menu_enum(brush, "image_tool")
elif context.vertex_paint_object or context.weight_paint_object:
layout.prop_menu_enum(brush, "vertex_tool")
# skip if no active brush
if not brush:
@@ -1072,6 +1088,21 @@ class VIEW3D_MT_brush(Menu):
layout.prop(brush, "use_persistent")
layout.operator("sculpt.set_persistent_base")
class VIEW3D_MT_brush_paint_modes(Menu):
bl_label = "Enabled Modes"
def draw(self, context):
layout = self.layout
settings = UnifiedPaintPanel.paint_settings(context)
brush = settings.brush
layout.prop(brush, "use_paint_sculpt", text="Sculpt")
layout.prop(brush, "use_paint_vertex", text="Vertex Paint")
layout.prop(brush, "use_paint_weight", text="Weight Paint")
layout.prop(brush, "use_paint_image", text="Texture Paint")
# ********** Vertex paint menu **********
@@ -1195,6 +1226,25 @@ class VIEW3D_MT_sculpt(Menu):
layout.prop(sculpt, "use_deform_only")
class VIEW3D_MT_hide(Menu):
bl_label = "Hide"
def draw(self, context):
layout = self.layout
op = layout.operator("paint.hide_show", text="Show All")
op.action = 'SHOW'
op.area = 'ALL'
op = layout.operator("paint.hide_show", text="Hide Bounding Box")
op.action = 'HIDE'
op.area = 'INSIDE'
op = layout.operator("paint.hide_show", text="Show Bounding Box")
op.action = 'SHOW'
op.area = 'INSIDE'
# ********** Particle menu **********
@@ -1519,7 +1569,8 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.operator("view3d.edit_mesh_extrude_individual_move", text="Extrude Individual")
layout.operator("mesh.dissolve_limited")
layout.operator("mesh.duplicate_move")
layout.operator("mesh.delete", text="Delete...")
layout.menu("VIEW3D_MT_edit_mesh_delete")
layout.menu("VIEW3D_MT_edit_mesh_dissolve")
layout.separator()
@@ -1556,7 +1607,7 @@ class VIEW3D_MT_edit_mesh_specials(Menu):
layout.operator("mesh.dissolve_limited")
layout.operator("mesh.hide", text="Hide")
layout.operator("mesh.reveal", text="Reveal")
layout.operator("mesh.select_all").action = 'INVERT'
layout.operator("mesh.select_all", text="Select Inverse").action = 'INVERT'
layout.operator("mesh.flip_normals")
layout.operator("mesh.vertices_smooth", text="Smooth")
layout.operator("mesh.bevel", text="Bevel")
@@ -1687,7 +1738,8 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.separator()
layout.operator("mesh.bridge_edge_loops", text="Bridge Two Edge Loops")
layout.operator("mesh.edge_split")
layout.operator("mesh.bridge_edge_loops")
layout.separator()
@@ -1713,11 +1765,11 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("mesh.flip_normals")
# layout.operator("mesh.bevel")
# layout.operator("mesh.bevel")
layout.operator("mesh.edge_face_add")
layout.operator("mesh.fill")
layout.operator("mesh.beautify_fill")
layout.operator("mesh.inset")
layout.operator("mesh.bevel")
layout.operator("mesh.solidify")
layout.operator("mesh.sort_faces")
@@ -1765,6 +1817,44 @@ class VIEW3D_MT_edit_mesh_normals(Menu):
layout.operator("mesh.flip_normals")
class VIEW3D_MT_edit_mesh_delete(Menu):
bl_label = "Delete"
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
layout.operator_enum("mesh.delete", "type")
layout.separator()
layout.operator("mesh.edge_collapse")
layout.operator("mesh.delete_edgeloop")
class VIEW3D_MT_edit_mesh_dissolve(Menu):
bl_label = "Dissolve"
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
layout.operator("mesh.dissolve")
layout.separator()
layout.operator_enum("mesh.dissolve", "type")
layout.separator()
layout.operator("mesh.dissolve_limited")
class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, Menu):
_operator_name = "mesh"

View File

@@ -500,7 +500,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# Sculpt Mode #
elif context.sculpt_object and brush:
tool = brush.sculpt_tool
capabilities = brush.sculpt_capabilities
col = layout.column()
@@ -519,47 +519,43 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_size(row, context, brush, "use_pressure_size")
if tool not in {'SNAKE_HOOK', 'GRAB', 'ROTATE'}:
# strength, use_strength_pressure, and use_strength_attenuation
if capabilities.has_strength:
col.separator()
row = col.row(align=True)
if brush.use_space and tool != 'SMOOTH':
if brush.use_space_atten:
row.prop(brush, "use_space_atten", toggle=True, text="", icon='LOCKED')
if capabilities.has_space_attenuation:
if brush.use_space_attenuation:
row.prop(brush, "use_space_attenuation", toggle=True, text="", icon='LOCKED')
else:
row.prop(brush, "use_space_atten", toggle=True, text="", icon='UNLOCKED')
row.prop(brush, "use_space_attenuation", toggle=True, text="", icon='UNLOCKED')
self.prop_unified_strength(row, context, brush, "strength", text="Strength")
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
if tool == 'ROTATE':
row = col.row(align=True)
self.prop_unified_strength(row, context, brush, "strength", text="Strength")
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
if tool != 'SMOOTH':
# auto_smooth_factor and use_inverse_smooth_pressure
if capabilities.has_auto_smooth:
col.separator()
row = col.row(align=True)
row.prop(brush, "auto_smooth_factor", slider=True)
row.prop(brush, "use_inverse_smooth_pressure", toggle=True, text="")
if tool in {'GRAB', 'SNAKE_HOOK'}:
# normal_weight
if capabilities.has_normal_weight:
col.separator()
row = col.row(align=True)
row.prop(brush, "normal_weight", slider=True)
if tool in {'CREASE', 'BLOB'}:
# crease_pinch_factor
if capabilities.has_pinch_factor:
col.separator()
row = col.row(align=True)
row.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
if tool not in {'PINCH', 'INFLATE', 'SMOOTH'}:
# use_original_normal and sculpt_plane
if capabilities.has_sculpt_plane:
row = col.row(align=True)
col.separator()
if brush.use_original_normal:
@@ -569,8 +565,8 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
row.prop(brush, "sculpt_plane", text="")
#if tool in {'CLAY', 'CLAY_TUBES', 'FLATTEN', 'FILL', 'SCRAPE'}:
if tool in {'CLAY', 'FLATTEN', 'FILL', 'SCRAPE'}:
# plane_offset, use_offset_pressure, use_plane_trim, plane_trim
if capabilities.has_plane_offset:
row = col.row(align=True)
row.prop(brush, "plane_offset", slider=True)
row.prop(brush, "use_offset_pressure", text="")
@@ -583,24 +579,28 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
row.active = brush.use_plane_trim
row.prop(brush, "plane_trim", slider=True, text="Distance")
if tool == 'LAYER':
# height
if capabilities.has_height:
row = col.row()
row.prop(brush, "height", slider=True, text="Height")
# use_frontface
col.separator()
row = col.row()
row.prop(brush, "use_frontface", text="Front Faces Only")
# direction
col.separator()
col.row().prop(brush, "direction", expand=True)
if tool in {'DRAW', 'CREASE', 'BLOB', 'INFLATE', 'LAYER', 'CLAY'}:
# use_accumulate
if capabilities.has_accumulate:
col.separator()
col.prop(brush, "use_accumulate")
if tool == 'LAYER':
# use_persistent, set_persistent_base
if capabilities.has_persistence:
col.separator()
ob = context.sculpt_object
@@ -714,7 +714,7 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
col = layout.column()
col.active = tex_slot.map_mode in {'FIXED'}
col.label(text="Angle:")
if not brush.use_anchor and brush.sculpt_tool not in {'GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE'} and tex_slot.map_mode in {'FIXED'}:
if brush.sculpt_capabilities.has_random_texture_angle:
col.prop(brush, "texture_angle_source_random", text="")
else:
col.prop(brush, "texture_angle_source_no_random", text="")
@@ -733,10 +733,6 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
col.active = tex_slot.map_mode in {'FIXED', 'TILED'}
col.prop(tex_slot, "angle", text="")
#col = layout.column()
#col.prop(brush, "use_random_rotation")
#col.active = (not brush.use_rake) and (not brush.use_anchor) and (brush.sculpt_tool not in {'GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE'}) and tex_slot.map_mode in {'FIXED'}
split = layout.split()
split.prop(tex_slot, "offset")
split.prop(tex_slot, "scale")
@@ -759,40 +755,6 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
sub.prop(brush, "texture_overlay_alpha", text="Alpha")
class VIEW3D_PT_tools_brush_tool(Panel, View3DPaintPanel):
bl_label = "Tool"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
settings = cls.paint_settings(context)
return (settings and settings.brush and
(context.sculpt_object or context.image_paint_object or
context.vertex_paint_object or context.weight_paint_object))
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
brush = settings.brush
col = layout.column(align=True)
if context.sculpt_object:
col.prop(brush, "sculpt_tool", expand=False, text="")
col.operator("brush.reset")
elif context.image_paint_object:
col.prop(brush, "image_tool", expand=False, text="")
elif context.vertex_paint_object or context.weight_paint_object:
col.prop(brush, "vertex_tool", expand=False, text="")
row = layout.row(align=True)
row.prop(brush, "use_paint_sculpt", text="", icon='SCULPTMODE_HLT')
row.prop(brush, "use_paint_vertex", text="", icon='VPAINT_HLT')
row.prop(brush, "use_paint_weight", text="", icon='WPAINT_HLT')
row.prop(brush, "use_paint_image", text="", icon='TPAINT_HLT')
class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
bl_label = "Stroke"
bl_options = {'DEFAULT_CLOSED'}
@@ -832,7 +794,7 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
if (brush.sculpt_tool not in {'GRAB', 'THUMB', 'SNAKE_HOOK', 'ROTATE'}) and (not brush.use_anchor) and (not brush.use_restore_mesh):
if brush.sculpt_capabilities.has_smooth_stroke:
col = layout.column()
col.separator()
@@ -843,6 +805,7 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
if brush.sculpt_capabilities.has_jitter:
col.separator()
row = col.row(align=True)
@@ -869,21 +832,13 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
col.separator()
col = layout.column()
col.active = (not brush.use_anchor) and (brush.sculpt_tool not in {'GRAB', 'THUMB', 'ROTATE', 'SNAKE_HOOK'})
col.active = brush.sculpt_capabilities.has_spacing
col.prop(brush, "use_space")
row = col.row()
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
#col.prop(brush, "use_space_atten", text="Adaptive Strength")
#col.prop(brush, "use_adaptive_space", text="Adaptive Spacing")
#col.separator()
#if image_paint:
# row.prop(brush, "use_pressure_spacing", toggle=True, text="")
class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
bl_label = "Curve"
@@ -989,8 +944,7 @@ class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
col = layout.column()
if context.sculpt_object and context.tool_settings.sculpt:
#if brush.sculpt_tool in {'DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE', 'CLAY_TUBES'}:
if brush.sculpt_tool in {'DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE'}:
if brush.sculpt_capabilities.has_secondary_color:
col.prop(brush, "cursor_color_add", text="Add Color")
col.prop(brush, "cursor_color_subtract", text="Subtract Color")
else:

View File

@@ -0,0 +1,21 @@
# This example assumes we have a mesh object selected
import bpy
import bmesh
# Get the active mesh
me = bpy.context.object.data
# Get a BMesh representation
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
# Modify the BMesh, can do anything here...
for v in bm.verts:
v.co.x += 1.0
# Finish up, write the bmesh back to the mesh
bm.to_mesh(me)

View File

@@ -2,6 +2,7 @@ import bpy
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = "PROPERTIES"