Merge branch 'master' into blender2.8

This commit is contained in:
2018-06-26 22:56:39 +02:00
68 changed files with 1554 additions and 1454 deletions

View File

@@ -15,6 +15,7 @@ font_info = {
"handler": None, "handler": None,
} }
def init(): def init():
"""init function - runs once""" """init function - runs once"""
import os import os

View File

@@ -10,22 +10,22 @@ bm = bmesh.new()
# Add a circle XXX, should return all geometry created, not just verts. # Add a circle XXX, should return all geometry created, not just verts.
bmesh.ops.create_circle( bmesh.ops.create_circle(
bm, bm,
cap_ends=False, cap_ends=False,
radius=0.2, radius=0.2,
segments=8) segments=8)
# Spin and deal with geometry on side 'a' # Spin and deal with geometry on side 'a'
edges_start_a = bm.edges[:] edges_start_a = bm.edges[:]
geom_start_a = bm.verts[:] + edges_start_a geom_start_a = bm.verts[:] + edges_start_a
ret = bmesh.ops.spin( ret = bmesh.ops.spin(
bm, bm,
geom=geom_start_a, geom=geom_start_a,
angle=math.radians(180.0), angle=math.radians(180.0),
steps=8, steps=8,
axis=(1.0, 0.0, 0.0), axis=(1.0, 0.0, 0.0),
cent=(0.0, 1.0, 0.0)) cent=(0.0, 1.0, 0.0))
edges_end_a = [ele for ele in ret["geom_last"] edges_end_a = [ele for ele in ret["geom_last"]
if isinstance(ele, bmesh.types.BMEdge)] if isinstance(ele, bmesh.types.BMEdge)]
del ret del ret
@@ -33,8 +33,8 @@ del ret
# Extrude and create geometry on side 'b' # Extrude and create geometry on side 'b'
ret = bmesh.ops.extrude_edge_only( ret = bmesh.ops.extrude_edge_only(
bm, bm,
edges=edges_start_a) edges=edges_start_a)
geom_extrude_mid = ret["geom"] geom_extrude_mid = ret["geom"]
del ret del ret
@@ -45,19 +45,19 @@ verts_extrude_b = [ele for ele in geom_extrude_mid
edges_extrude_b = [ele for ele in geom_extrude_mid edges_extrude_b = [ele for ele in geom_extrude_mid
if isinstance(ele, bmesh.types.BMEdge) and ele.is_boundary] if isinstance(ele, bmesh.types.BMEdge) and ele.is_boundary]
bmesh.ops.translate( bmesh.ops.translate(
bm, bm,
verts=verts_extrude_b, verts=verts_extrude_b,
vec=(0.0, 0.0, 1.0)) vec=(0.0, 0.0, 1.0))
# Create the circle on side 'b' # Create the circle on side 'b'
ret = bmesh.ops.spin( ret = bmesh.ops.spin(
bm, bm,
geom=verts_extrude_b + edges_extrude_b, geom=verts_extrude_b + edges_extrude_b,
angle=-math.radians(180.0), angle=-math.radians(180.0),
steps=8, steps=8,
axis=(1.0, 0.0, 0.0), axis=(1.0, 0.0, 0.0),
cent=(0.0, 1.0, 1.0)) cent=(0.0, 1.0, 1.0))
edges_end_b = [ele for ele in ret["geom_last"] edges_end_b = [ele for ele in ret["geom_last"]
if isinstance(ele, bmesh.types.BMEdge)] if isinstance(ele, bmesh.types.BMEdge)]
del ret del ret
@@ -65,30 +65,30 @@ del ret
# Bridge the resulting edge loops of both spins 'a & b' # Bridge the resulting edge loops of both spins 'a & b'
bmesh.ops.bridge_loops( bmesh.ops.bridge_loops(
bm, bm,
edges=edges_end_a + edges_end_b) edges=edges_end_a + edges_end_b)
# Now we have made a links of the chain, make a copy and rotate it # Now we have made a links of the chain, make a copy and rotate it
# (so this looks something like a chain) # (so this looks something like a chain)
ret = bmesh.ops.duplicate( ret = bmesh.ops.duplicate(
bm, bm,
geom=bm.verts[:] + bm.edges[:] + bm.faces[:]) geom=bm.verts[:] + bm.edges[:] + bm.faces[:])
geom_dupe = ret["geom"] geom_dupe = ret["geom"]
verts_dupe = [ele for ele in geom_dupe if isinstance(ele, bmesh.types.BMVert)] verts_dupe = [ele for ele in geom_dupe if isinstance(ele, bmesh.types.BMVert)]
del ret del ret
# position the new link # position the new link
bmesh.ops.translate( bmesh.ops.translate(
bm, bm,
verts=verts_dupe, verts=verts_dupe,
vec=(0.0, 0.0, 2.0)) vec=(0.0, 0.0, 2.0))
bmesh.ops.rotate( bmesh.ops.rotate(
bm, bm,
verts=verts_dupe, verts=verts_dupe,
cent=(0.0, 1.0, 0.0), cent=(0.0, 1.0, 0.0),
matrix=mathutils.Matrix.Rotation(math.radians(90.0), 3, 'Z')) matrix=mathutils.Matrix.Rotation(math.radians(90.0), 3, 'Z'))
# Done with creating the mesh, simply link it into the scene so we can see it # Done with creating the mesh, simply link it into the scene so we can see it

View File

@@ -17,4 +17,5 @@ from bpy.app.handlers import persistent
def load_handler(dummy): def load_handler(dummy):
print("Load Handler:", bpy.data.filepath) print("Load Handler:", bpy.data.filepath)
bpy.app.handlers.load_post.append(load_handler) bpy.app.handlers.load_post.append(load_handler)

View File

@@ -11,4 +11,5 @@ import bpy
def my_handler(scene): def my_handler(scene):
print("Frame Change", scene.frame_current) print("Frame Change", scene.frame_current)
bpy.app.handlers.frame_change_pre.append(my_handler) bpy.app.handlers.frame_change_pre.append(my_handler)

View File

@@ -54,19 +54,19 @@ translations_tuple = (
"Copyright (C) 2013 The Blender Foundation.", "Copyright (C) 2013 The Blender Foundation.",
"This file is distributed under the same license as the Blender package.", "This file is distributed under the same license as the Blender package.",
"FIRST AUTHOR <EMAIL@ADDRESS>, YEAR."))), "FIRST AUTHOR <EMAIL@ADDRESS>, YEAR."))),
), ),
(("Operator", "Render: Copy Settings"), (("Operator", "Render: Copy Settings"),
(("bpy.types.SCENE_OT_render_copy_settings",), (("bpy.types.SCENE_OT_render_copy_settings",),
()), ()),
("fr_FR", "Rendu : copier réglages", ("fr_FR", "Rendu : copier réglages",
(False, ())), (False, ())),
), ),
(("*", "Copy render settings from current scene to others"), (("*", "Copy render settings from current scene to others"),
(("bpy.types.SCENE_OT_render_copy_settings",), (("bpy.types.SCENE_OT_render_copy_settings",),
()), ()),
("fr_FR", "Copier les réglages de rendu depuis la scène courante vers dautres", ("fr_FR", "Copier les réglages de rendu depuis la scène courante vers dautres",
(False, ())), (False, ())),
), ),
# ... etc, all messages from your addon. # ... etc, all messages from your addon.
) )
@@ -81,6 +81,7 @@ for msg in translations_tuple:
# Define remaining addon (operators, UI...) here. # Define remaining addon (operators, UI...) here.
def register(): def register():
# Usual operator/UI/etc. registration... # Usual operator/UI/etc. registration...

View File

@@ -14,6 +14,7 @@ class MaterialSettings(bpy.types.PropertyGroup):
my_float = bpy.props.FloatProperty() my_float = bpy.props.FloatProperty()
my_string = bpy.props.StringProperty() my_string = bpy.props.StringProperty()
bpy.utils.register_class(MaterialSettings) bpy.utils.register_class(MaterialSettings)
bpy.types.Material.my_settings = \ bpy.types.Material.my_settings = \

View File

@@ -14,6 +14,7 @@ class SceneSettingItem(bpy.types.PropertyGroup):
name = bpy.props.StringProperty(name="Test Prop", default="Unknown") name = bpy.props.StringProperty(name="Test Prop", default="Unknown")
value = bpy.props.IntProperty(name="Test Prop", default=22) value = bpy.props.IntProperty(name="Test Prop", default=22)
bpy.utils.register_class(SceneSettingItem) bpy.utils.register_class(SceneSettingItem)
bpy.types.Scene.my_settings = \ bpy.types.Scene.my_settings = \

View File

@@ -14,6 +14,7 @@ import bpy
def update_func(self, context): def update_func(self, context):
print("my test function", self) print("my test function", self)
bpy.types.Scene.testprop = bpy.props.FloatProperty(update=update_func) bpy.types.Scene.testprop = bpy.props.FloatProperty(update=update_func)
bpy.context.scene.testprop = 11.0 bpy.context.scene.testprop = 11.0

View File

@@ -19,6 +19,7 @@ def get_float(self):
def set_float(self, value): def set_float(self, value):
self["testprop"] = value self["testprop"] = value
bpy.types.Scene.test_float = bpy.props.FloatProperty(get=get_float, set=set_float) bpy.types.Scene.test_float = bpy.props.FloatProperty(get=get_float, set=set_float)
@@ -27,6 +28,7 @@ def get_date(self):
import datetime import datetime
return str(datetime.datetime.now()) return str(datetime.datetime.now())
bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date) bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date)
@@ -40,6 +42,7 @@ def get_array(self):
def set_array(self, values): def set_array(self, values):
self["somebool"] = values[0] and values[1] self["somebool"] = values[0] and values[1]
bpy.types.Scene.test_array = bpy.props.BoolVectorProperty(size=2, get=get_array, set=set_array) bpy.types.Scene.test_array = bpy.props.BoolVectorProperty(size=2, get=get_array, set=set_array)
@@ -50,7 +53,7 @@ test_items = [
("GREEN", "Green", "", 2), ("GREEN", "Green", "", 2),
("BLUE", "Blue", "", 3), ("BLUE", "Blue", "", 3),
("YELLOW", "Yellow", "", 4), ("YELLOW", "Yellow", "", 4),
] ]
def get_enum(self): def get_enum(self):
@@ -61,6 +64,7 @@ def get_enum(self):
def set_enum(self, value): def set_enum(self, value):
print("setting value", value) print("setting value", value)
bpy.types.Scene.test_enum = bpy.props.EnumProperty(items=test_items, get=get_enum, set=set_enum) bpy.types.Scene.test_enum = bpy.props.EnumProperty(items=test_items, get=get_enum, set=set_enum)

View File

@@ -9,7 +9,7 @@ bl_info = {
"wiki_url": "", "wiki_url": "",
"tracker_url": "", "tracker_url": "",
"category": "Object", "category": "Object",
} }
import bpy import bpy
@@ -23,17 +23,17 @@ class ExampleAddonPreferences(AddonPreferences):
bl_idname = __name__ bl_idname = __name__
filepath = StringProperty( filepath = StringProperty(
name="Example File Path", name="Example File Path",
subtype='FILE_PATH', subtype='FILE_PATH',
) )
number = IntProperty( number = IntProperty(
name="Example Number", name="Example Number",
default=4, default=4,
) )
boolean = BoolProperty( boolean = BoolProperty(
name="Example Boolean", name="Example Boolean",
default=False, default=False,
) )
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout

View File

@@ -14,4 +14,5 @@ import bpy
def menu_draw(self, context): def menu_draw(self, context):
self.layout.operator("wm.save_homefile") self.layout.operator("wm.save_homefile")
bpy.types.INFO_MT_file.append(menu_draw) bpy.types.INFO_MT_file.append(menu_draw)

View File

@@ -32,7 +32,7 @@ class AddPresetObjectDraw(AddPresetBase, Operator):
# variable used for all preset values # variable used for all preset values
preset_defines = [ preset_defines = [
"obj = bpy.context.object" "obj = bpy.context.object"
] ]
# properties to store in the preset # properties to store in the preset
preset_values = [ preset_values = [
@@ -42,7 +42,7 @@ class AddPresetObjectDraw(AddPresetBase, Operator):
"obj.show_name", "obj.show_name",
"obj.show_axis", "obj.show_axis",
"obj.show_wire", "obj.show_wire",
] ]
# where to store the preset # where to store the preset
preset_subdir = "object/draw" preset_subdir = "object/draw"
@@ -61,7 +61,7 @@ def panel_func(self, context):
classes = ( classes = (
OBJECT_MT_draw_presets, OBJECT_MT_draw_presets,
AddPresetObjectDraw, AddPresetObjectDraw,
) )
def register(): def register():

View File

@@ -60,6 +60,7 @@ def menu_func(self, context):
layout.separator() layout.separator()
layout.operator(WM_OT_button_context_test.bl_idname) layout.operator(WM_OT_button_context_test.bl_idname)
classes = ( classes = (
WM_OT_button_context_test, WM_OT_button_context_test,
WM_MT_button_context, WM_MT_button_context,
@@ -77,5 +78,6 @@ def unregister():
bpy.utils.unregister_class(cls) bpy.utils.unregister_class(cls)
bpy.types.WM_MT_button_context.remove(menu_func) bpy.types.WM_MT_button_context.remove(menu_func)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -21,4 +21,5 @@ class CyclesNodeTree(bpy.types.NodeTree):
def poll(cls, context): def poll(cls, context):
return context.scene.render.engine == 'CYCLES' return context.scene.render.engine == 'CYCLES'
bpy.utils.register_class(CyclesNodeTree) bpy.utils.register_class(CyclesNodeTree)

View File

@@ -42,6 +42,7 @@ class SimpleMouseOperator(bpy.types.Operator):
self.y = event.mouse_y self.y = event.mouse_y
return self.execute(context) return self.execute(context)
bpy.utils.register_class(SimpleMouseOperator) bpy.utils.register_class(SimpleMouseOperator)
# Test call to the newly defined operator. # Test call to the newly defined operator.

View File

@@ -42,6 +42,7 @@ def menu_func(self, context):
self.layout.operator_context = 'INVOKE_DEFAULT' self.layout.operator_context = 'INVOKE_DEFAULT'
self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator") self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")
# Register and add to the file selector # Register and add to the file selector
bpy.utils.register_class(ExportSomeData) bpy.utils.register_class(ExportSomeData)
bpy.types.INFO_MT_file_export.append(menu_func) bpy.types.INFO_MT_file_export.append(menu_func)

View File

@@ -41,6 +41,7 @@ class CustomDrawOperator(bpy.types.Operator):
col.prop(self, "my_string") col.prop(self, "my_string")
bpy.utils.register_class(CustomDrawOperator) bpy.utils.register_class(CustomDrawOperator)
# test call # test call

View File

@@ -22,6 +22,7 @@ class HelloWorldOperator(bpy.types.Operator):
print("Hello World") print("Hello World")
return {'FINISHED'} return {'FINISHED'}
bpy.utils.register_class(HelloWorldOperator) bpy.utils.register_class(HelloWorldOperator)
# test call to the newly defined operator # test call to the newly defined operator

View File

@@ -31,6 +31,7 @@ class MyPropertyGroup(bpy.types.PropertyGroup):
custom_1 = bpy.props.FloatProperty(name="My Float") custom_1 = bpy.props.FloatProperty(name="My Float")
custom_2 = bpy.props.IntProperty(name="My Int") custom_2 = bpy.props.IntProperty(name="My Int")
bpy.utils.register_class(MyPropertyGroup) bpy.utils.register_class(MyPropertyGroup)
bpy.types.Object.my_prop_grp = bpy.props.PointerProperty(type=MyPropertyGroup) bpy.types.Object.my_prop_grp = bpy.props.PointerProperty(type=MyPropertyGroup)

View File

@@ -10,4 +10,5 @@ import bpy
def draw(self, context): def draw(self, context):
self.layout.label("Hello World") self.layout.label("Hello World")
bpy.context.window_manager.popup_menu(draw, title="Greeting", icon='INFO') bpy.context.window_manager.popup_menu(draw, title="Greeting", icon='INFO')

View File

@@ -12,6 +12,7 @@ from bpy.props import PointerProperty
class MyPropGroup(bpy.types.PropertyGroup): class MyPropGroup(bpy.types.PropertyGroup):
nested = bpy.props.FloatProperty(name="Nested", default=0.0) nested = bpy.props.FloatProperty(name="Nested", default=0.0)
# register it so its available for all bones # register it so its available for all bones
bpy.utils.register_class(MyPropGroup) bpy.utils.register_class(MyPropGroup)
bpy.types.Bone.my_prop = PointerProperty(type=MyPropGroup, bpy.types.Bone.my_prop = PointerProperty(type=MyPropGroup,

View File

@@ -23,9 +23,9 @@ class OffScreenDraw(bpy.types.Operator):
@staticmethod @staticmethod
def handle_add(self, context): def handle_add(self, context):
OffScreenDraw._handle_draw = bpy.types.SpaceView3D.draw_handler_add( OffScreenDraw._handle_draw = bpy.types.SpaceView3D.draw_handler_add(
self.draw_callback_px, (self, context), self.draw_callback_px, (self, context),
'WINDOW', 'POST_PIXEL', 'WINDOW', 'POST_PIXEL',
) )
@staticmethod @staticmethod
def handle_remove(): def handle_remove():
@@ -58,20 +58,20 @@ class OffScreenDraw(bpy.types.Operator):
modelview_matrix = camera.matrix_world.inverted() modelview_matrix = camera.matrix_world.inverted()
projection_matrix = camera.calc_matrix_camera( projection_matrix = camera.calc_matrix_camera(
render.resolution_x, render.resolution_x,
render.resolution_y, render.resolution_y,
render.pixel_aspect_x, render.pixel_aspect_x,
render.pixel_aspect_y, render.pixel_aspect_y,
) )
offscreen.draw_view3d( offscreen.draw_view3d(
scene, scene,
render_layer, render_layer,
context.space_data, context.space_data,
context.region, context.region,
projection_matrix, projection_matrix,
modelview_matrix, modelview_matrix,
) )
@staticmethod @staticmethod
def _opengl_draw(context, texture, aspect_ratio, scale): def _opengl_draw(context, texture, aspect_ratio, scale):

View File

@@ -48,7 +48,7 @@ _modules = [
"vertexpaint_dirt", "vertexpaint_dirt",
"view3d", "view3d",
"wm", "wm",
] ]
import bpy import bpy

View File

@@ -135,63 +135,63 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
self.abso_minor_rad = self.major_radius - self.minor_radius self.abso_minor_rad = self.major_radius - self.minor_radius
major_segments = IntProperty( major_segments = IntProperty(
name="Major Segments", name="Major Segments",
description="Number of segments for the main ring of the torus", description="Number of segments for the main ring of the torus",
min=3, max=256, min=3, max=256,
default=48, default=48,
) )
minor_segments = IntProperty( minor_segments = IntProperty(
name="Minor Segments", name="Minor Segments",
description="Number of segments for the minor ring of the torus", description="Number of segments for the minor ring of the torus",
min=3, max=256, min=3, max=256,
default=12, default=12,
) )
mode = bpy.props.EnumProperty( mode = bpy.props.EnumProperty(
name="Torus Dimensions", name="Torus Dimensions",
items=(("MAJOR_MINOR", "Major/Minor", items=(("MAJOR_MINOR", "Major/Minor",
"Use the major/minor radii for torus dimensions"), "Use the major/minor radii for torus dimensions"),
("EXT_INT", "Exterior/Interior", ("EXT_INT", "Exterior/Interior",
"Use the exterior/interior radii for torus dimensions")), "Use the exterior/interior radii for torus dimensions")),
update=mode_update_callback, update=mode_update_callback,
) )
major_radius = FloatProperty( major_radius = FloatProperty(
name="Major Radius", name="Major Radius",
description=("Radius from the origin to the " description=("Radius from the origin to the "
"center of the cross sections"), "center of the cross sections"),
min=0.01, max=100.0, min=0.01, max=100.0,
default=1.0, default=1.0,
subtype='DISTANCE', subtype='DISTANCE',
unit='LENGTH', unit='LENGTH',
) )
minor_radius = FloatProperty( minor_radius = FloatProperty(
name="Minor Radius", name="Minor Radius",
description="Radius of the torus' cross section", description="Radius of the torus' cross section",
min=0.01, max=100.0, min=0.01, max=100.0,
default=0.25, default=0.25,
subtype='DISTANCE', subtype='DISTANCE',
unit='LENGTH', unit='LENGTH',
) )
abso_major_rad = FloatProperty( abso_major_rad = FloatProperty(
name="Exterior Radius", name="Exterior Radius",
description="Total Exterior Radius of the torus", description="Total Exterior Radius of the torus",
min=0.01, max=100.0, min=0.01, max=100.0,
default=1.25, default=1.25,
subtype='DISTANCE', subtype='DISTANCE',
unit='LENGTH', unit='LENGTH',
) )
abso_minor_rad = FloatProperty( abso_minor_rad = FloatProperty(
name="Interior Radius", name="Interior Radius",
description="Total Interior Radius of the torus", description="Total Interior Radius of the torus",
min=0.01, max=100.0, min=0.01, max=100.0,
default=0.75, default=0.75,
subtype='DISTANCE', subtype='DISTANCE',
unit='LENGTH', unit='LENGTH',
) )
generate_uvs = BoolProperty( generate_uvs = BoolProperty(
name="Generate UVs", name="Generate UVs",
description="Generate a default UV map", description="Generate a default UV map",
default=False, default=False,
) )
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout

View File

@@ -41,23 +41,23 @@ class ANIM_OT_keying_set_export(Operator):
bl_label = "Export Keying Set..." bl_label = "Export Keying Set..."
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
name="Filter folders", name="Filter folders",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_text = BoolProperty( filter_text = BoolProperty(
name="Filter text", name="Filter text",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_python = BoolProperty( filter_python = BoolProperty(
name="Filter python", name="Filter python",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
def execute(self, context): def execute(self, context):
if not self.filepath: if not self.filepath:
@@ -204,58 +204,59 @@ class BakeAction(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
frame_start = IntProperty( frame_start = IntProperty(
name="Start Frame", name="Start Frame",
description="Start frame for baking", description="Start frame for baking",
min=0, max=300000, min=0, max=300000,
default=1, default=1,
) )
frame_end = IntProperty( frame_end = IntProperty(
name="End Frame", name="End Frame",
description="End frame for baking", description="End frame for baking",
min=1, max=300000, min=1, max=300000,
default=250, default=250,
) )
step = IntProperty( step = IntProperty(
name="Frame Step", name="Frame Step",
description="Frame Step", description="Frame Step",
min=1, max=120, min=1, max=120,
default=1, default=1,
) )
only_selected = BoolProperty( only_selected = BoolProperty(
name="Only Selected Bones", name="Only Selected Bones",
description="Only key selected bones (Pose baking only)", description="Only key selected bones (Pose baking only)",
default=True, default=True,
) )
visual_keying = BoolProperty( visual_keying = BoolProperty(
name="Visual Keying", name="Visual Keying",
description="Keyframe from the final transformations (with constraints applied)", description="Keyframe from the final transformations (with constraints applied)",
default=False, default=False,
) )
clear_constraints = BoolProperty( clear_constraints = BoolProperty(
name="Clear Constraints", name="Clear Constraints",
description="Remove all constraints from keyed object/bones, and do 'visual' keying", description="Remove all constraints from keyed object/bones, and do 'visual' keying",
default=False, default=False,
) )
clear_parents = BoolProperty( clear_parents = BoolProperty(
name="Clear Parents", name="Clear Parents",
description="Bake animation onto the object then clear parents (objects only)", description="Bake animation onto the object then clear parents (objects only)",
default=False, default=False,
) )
use_current_action = BoolProperty( use_current_action = BoolProperty(
name="Overwrite Current Action", name="Overwrite Current Action",
description="Bake animation into current action, instead of creating a new one " description="Bake animation into current action, instead of creating a new one "
"(useful for baking only part of bones in an armature)", "(useful for baking only part of bones in an armature)",
default=False, default=False,
) )
bake_types = EnumProperty( bake_types = EnumProperty(
name="Bake Data", name="Bake Data",
description="Which data's transformations to bake", description="Which data's transformations to bake",
options={'ENUM_FLAG'}, options={'ENUM_FLAG'},
items=(('POSE', "Pose", "Bake bones transformations"), items=(
('OBJECT', "Object", "Bake object transformations"), ('POSE', "Pose", "Bake bones transformations"),
), ('OBJECT', "Object", "Bake object transformations"),
default={'POSE'}, ),
) default={'POSE'},
)
def execute(self, context): def execute(self, context):
from bpy_extras import anim_utils from bpy_extras import anim_utils
@@ -296,16 +297,16 @@ class BakeAction(Operator):
class ClearUselessActions(Operator): class ClearUselessActions(Operator):
"""Mark actions with no F-Curves for deletion after save & reload of """ \ """Mark actions with no F-Curves for deletion after save & reload of """ \
"""file preserving \"action libraries\"""" """file preserving \"action libraries\""""
bl_idname = "anim.clear_useless_actions" bl_idname = "anim.clear_useless_actions"
bl_label = "Clear Useless Actions" bl_label = "Clear Useless Actions"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
only_unused = BoolProperty( only_unused = BoolProperty(
name="Only Unused", name="Only Unused",
description="Only unused (Fake User only) actions get considered", description="Only unused (Fake User only) actions get considered",
default=True, default=True,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -316,8 +317,10 @@ class ClearUselessActions(Operator):
for action in bpy.data.actions: for action in bpy.data.actions:
# if only user is "fake" user... # if only user is "fake" user...
if ((self.only_unused is False) or if (
(action.use_fake_user and action.users == 1)): (self.only_unused is False) or
(action.use_fake_user and action.users == 1)
):
# if it has F-Curves, then it's a "action library" # if it has F-Curves, then it's a "action library"
# (i.e. walk, wave, jump, etc.) # (i.e. walk, wave, jump, etc.)
@@ -339,10 +342,10 @@ class UpdateAnimatedTransformConstraint(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
use_convert_to_radians = BoolProperty( use_convert_to_radians = BoolProperty(
name="Convert To Radians", name="Convert To Radians",
description="Convert fcurves/drivers affecting rotations to radians (Warning: use this only once!)", description="Convert fcurves/drivers affecting rotations to radians (Warning: use this only once!)",
default=True, default=True,
) )
def execute(self, context): def execute(self, context):
import animsys_refactor import animsys_refactor

View File

@@ -134,10 +134,10 @@ class CLIP_OT_filter_tracks(bpy.types.Operator):
bl_options = {'UNDO', 'REGISTER'} bl_options = {'UNDO', 'REGISTER'}
track_threshold = FloatProperty( track_threshold = FloatProperty(
name="Track Threshold", name="Track Threshold",
description="Filter Threshold to select problematic tracks", description="Filter Threshold to select problematic tracks",
default=5.0, default=5.0,
) )
@staticmethod @staticmethod
def _filter_values(context, threshold): def _filter_values(context, threshold):
@@ -165,9 +165,10 @@ class CLIP_OT_filter_tracks(bpy.types.Operator):
# Find tracks with markers in both this frame and the previous one. # Find tracks with markers in both this frame and the previous one.
relevant_tracks = [ relevant_tracks = [
track for track in clip.tracking.tracks track for track in clip.tracking.tracks
if (track.markers.find_frame(frame) and if (track.markers.find_frame(frame) and
track.markers.find_frame(frame - 1))] track.markers.find_frame(frame - 1))
]
if not relevant_tracks: if not relevant_tracks:
continue continue
@@ -399,7 +400,7 @@ class CLIP_OT_delete_proxy(Operator):
class CLIP_OT_set_viewport_background(Operator): class CLIP_OT_set_viewport_background(Operator):
"""Set current movie clip as a camera background in 3D view-port """ \ """Set current movie clip as a camera background in 3D view-port """ \
"""(works only when a 3D view-port is visible)""" """(works only when a 3D view-port is visible)"""
bl_idname = "clip.set_viewport_background" bl_idname = "clip.set_viewport_background"
bl_label = "Set as Background" bl_label = "Set as Background"
@@ -1047,13 +1048,13 @@ class CLIP_OT_track_settings_to_track(bpy.types.Operator):
"use_green_channel", "use_green_channel",
"use_blue_channel", "use_blue_channel",
"weight" "weight"
) )
_attrs_marker = ( _attrs_marker = (
"pattern_corners", "pattern_corners",
"search_min", "search_min",
"search_max", "search_max",
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -38,8 +38,8 @@ class ConsoleExec(Operator):
bl_label = "Console Execute" bl_label = "Console Execute"
interactive = BoolProperty( interactive = BoolProperty(
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -61,7 +61,7 @@ class ConsoleExec(Operator):
class ConsoleAutocomplete(Operator): class ConsoleAutocomplete(Operator):
"""Evaluate the namespace up until the cursor and give a list of """ \ """Evaluate the namespace up until the cursor and give a list of """ \
"""options or complete the name if there is only one""" """options or complete the name if there is only one"""
bl_idname = "console.autocomplete" bl_idname = "console.autocomplete"
bl_label = "Console Autocomplete" bl_label = "Console Autocomplete"
@@ -138,9 +138,9 @@ class ConsoleLanguage(Operator):
bl_label = "Console Language" bl_label = "Console Language"
language = StringProperty( language = StringProperty(
name="Language", name="Language",
maxlen=32, maxlen=32,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -38,59 +38,59 @@ class WM_OT_previews_batch_generate(Operator):
# ----------- # -----------
# File props. # File props.
files = CollectionProperty( files = CollectionProperty(
type=bpy.types.OperatorFileListElement, type=bpy.types.OperatorFileListElement,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
directory = StringProperty( directory = StringProperty(
maxlen=1024, maxlen=1024,
subtype='FILE_PATH', subtype='FILE_PATH',
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
# Show only images/videos, and directories! # Show only images/videos, and directories!
filter_blender = BoolProperty( filter_blender = BoolProperty(
default=True, default=True,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
default=True, default=True,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
# ----------- # -----------
# Own props. # Own props.
use_scenes = BoolProperty( use_scenes = BoolProperty(
default=True, default=True,
name="Scenes", name="Scenes",
description="Generate scenes' previews", description="Generate scenes' previews",
) )
use_collections = BoolProperty( use_collections = BoolProperty(
default=True, default=True,
name="Collections", name="Collections",
description="Generate collections' previews", description="Generate collections' previews",
) )
use_objects = BoolProperty( use_objects = BoolProperty(
default=True, default=True,
name="Objects", name="Objects",
description="Generate objects' previews", description="Generate objects' previews",
) )
use_intern_data = BoolProperty( use_intern_data = BoolProperty(
default=True, default=True,
name="Mat/Tex/...", name="Mat/Tex/...",
description="Generate 'internal' previews (materials, textures, images, etc.)", description="Generate 'internal' previews (materials, textures, images, etc.)",
) )
use_trusted = BoolProperty( use_trusted = BoolProperty(
default=False, default=False,
name="Trusted Blend Files", name="Trusted Blend Files",
description="Enable python evaluation for selected files", description="Enable python evaluation for selected files",
) )
use_backups = BoolProperty( use_backups = BoolProperty(
default=True, default=True,
name="Save Backups", name="Save Backups",
description="Keep a backup (.blend1) version of the files when saving with generated previews", description="Keep a backup (.blend1) version of the files when saving with generated previews",
) )
def invoke(self, context, event): def invoke(self, context, event):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
@@ -148,58 +148,59 @@ class WM_OT_previews_batch_clear(Operator):
# ----------- # -----------
# File props. # File props.
files = CollectionProperty( files = CollectionProperty(
type=bpy.types.OperatorFileListElement, type=bpy.types.OperatorFileListElement,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
directory = StringProperty( directory = StringProperty(
maxlen=1024, maxlen=1024,
subtype='FILE_PATH', subtype='FILE_PATH',
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
# Show only images/videos, and directories! # Show only images/videos, and directories!
filter_blender = BoolProperty( filter_blender = BoolProperty(
default=True, default=True,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
default=True, default=True,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
# ----------- # -----------
# Own props. # Own props.
use_scenes = BoolProperty( use_scenes = BoolProperty(
default=True, default=True,
name="Scenes", name="Scenes",
description="Clear scenes' previews", description="Clear scenes' previews",
) )
use_collections = BoolProperty(default=True, use_collections = BoolProperty(
name="Collections", default=True,
description="Clear collections' previews", name="Collections",
) description="Clear collections' previews",
)
use_objects = BoolProperty( use_objects = BoolProperty(
default=True, default=True,
name="Objects", name="Objects",
description="Clear objects' previews", description="Clear objects' previews",
) )
use_intern_data = BoolProperty( use_intern_data = BoolProperty(
default=True, default=True,
name="Mat/Tex/...", name="Mat/Tex/...",
description="Clear 'internal' previews (materials, textures, images, etc.)", description="Clear 'internal' previews (materials, textures, images, etc.)",
) )
use_trusted = BoolProperty( use_trusted = BoolProperty(
default=False, default=False,
name="Trusted Blend Files", name="Trusted Blend Files",
description="Enable python evaluation for selected files", description="Enable python evaluation for selected files",
) )
use_backups = BoolProperty( use_backups = BoolProperty(
default=True, default=True,
name="Save Backups", name="Save Backups",
description="Keep a backup (.blend1) version of the files when saving with cleared previews", description="Keep a backup (.blend1) version of the files when saving with cleared previews",
) )
def invoke(self, context, event): def invoke(self, context, event):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)

View File

@@ -35,15 +35,15 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
bl_options = {'INTERNAL'} bl_options = {'INTERNAL'}
type = EnumProperty( type = EnumProperty(
name="Type", description="Type of the modifier to work on", name="Type", description="Type of the modifier to work on",
items=(("COLOR", "Color", "Color modifier type"), items=(("COLOR", "Color", "Color modifier type"),
("ALPHA", "Alpha", "Alpha modifier type"), ("ALPHA", "Alpha", "Alpha modifier type"),
("THICKNESS", "Thickness", "Thickness modifier type")), ("THICKNESS", "Thickness", "Thickness modifier type")),
) )
name = StringProperty( name = StringProperty(
name="Name", name="Name",
description="Name of the modifier to work on", description="Name of the modifier to work on",
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -30,8 +30,8 @@ class EditExternally(Operator):
bl_options = {'REGISTER'} bl_options = {'REGISTER'}
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
) )
@staticmethod @staticmethod
def _editor_guess(context): def _editor_guess(context):

View File

@@ -34,18 +34,20 @@ class MeshMirrorUV(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
direction = EnumProperty( direction = EnumProperty(
name="Axis Direction", name="Axis Direction",
items=(('POSITIVE', "Positive", ""), items=(
('NEGATIVE', "Negative", "")), ('POSITIVE', "Positive", ""),
) ('NEGATIVE', "Negative", ""),
),
)
precision = IntProperty( precision = IntProperty(
name="Precision", name="Precision",
description=("Tolerance for finding vertex duplicates"), description=("Tolerance for finding vertex duplicates"),
min=1, max=16, min=1, max=16,
soft_min=1, soft_max=16, soft_min=1, soft_max=16,
default=3, default=3,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -35,31 +35,31 @@ from bpy.props import (
class NodeSetting(PropertyGroup): class NodeSetting(PropertyGroup):
value = StringProperty( value = StringProperty(
name="Value", name="Value",
description="Python expression to be evaluated " description="Python expression to be evaluated "
"as the initial node setting", "as the initial node setting",
default="", default="",
) )
# Base class for node 'Add' operators # Base class for node 'Add' operators
class NodeAddOperator: class NodeAddOperator:
type = StringProperty( type = StringProperty(
name="Node Type", name="Node Type",
description="Node type", description="Node type",
) )
use_transform = BoolProperty( use_transform = BoolProperty(
name="Use Transform", name="Use Transform",
description="Start transform operator after inserting the node", description="Start transform operator after inserting the node",
default=False, default=False,
) )
settings = CollectionProperty( settings = CollectionProperty(
name="Settings", name="Settings",
description="Settings to be applied on the newly created node", description="Settings to be applied on the newly created node",
type=NodeSetting, type=NodeSetting,
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
@staticmethod @staticmethod
def store_mouse_cursor(context, event): def store_mouse_cursor(context, event):
@@ -70,7 +70,7 @@ class NodeAddOperator:
if context.region.type == 'WINDOW': if context.region.type == 'WINDOW':
# convert mouse position to the View2D for later node placement # convert mouse position to the View2D for later node placement
space.cursor_location_from_region( space.cursor_location_from_region(
event.mouse_region_x, event.mouse_region_y) event.mouse_region_x, event.mouse_region_y)
else: else:
space.cursor_location = tree.view_center space.cursor_location = tree.view_center
@@ -99,8 +99,8 @@ class NodeAddOperator:
setattr(node, setting.name, value) setattr(node, setting.name, value)
except AttributeError as e: except AttributeError as e:
self.report( self.report(
{'ERROR_INVALID_INPUT'}, {'ERROR_INVALID_INPUT'},
"Node has no attribute " + setting.name) "Node has no attribute " + setting.name)
print(str(e)) print(str(e))
# Continue despite invalid attribute # Continue despite invalid attribute
@@ -153,9 +153,9 @@ class NODE_OT_add_and_link_node(NodeAddOperator, Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
link_socket_index = IntProperty( link_socket_index = IntProperty(
name="Link Socket Index", name="Link Socket Index",
description="Index of the socket to link", description="Index of the socket to link",
) )
def execute(self, context): def execute(self, context):
space = context.space_data space = context.space_data
@@ -195,11 +195,11 @@ class NODE_OT_add_search(NodeAddOperator, Operator):
nodetype = getattr(bpy.types, item.nodetype, None) nodetype = getattr(bpy.types, item.nodetype, None)
if nodetype: if nodetype:
enum_items.append( enum_items.append(
(str(index), (str(index),
item.label, item.label,
nodetype.bl_rna.description, nodetype.bl_rna.description,
index, index,
)) ))
return enum_items return enum_items
# Look up the item based on index # Look up the item based on index
@@ -211,10 +211,10 @@ class NODE_OT_add_search(NodeAddOperator, Operator):
return None return None
node_item = EnumProperty( node_item = EnumProperty(
name="Node Type", name="Node Type",
description="Node type", description="Node type",
items=node_enum_items, items=node_enum_items,
) )
def execute(self, context): def execute(self, context):
item = self.find_node_item(context) item = self.find_node_item(context)
@@ -233,7 +233,7 @@ class NODE_OT_add_search(NodeAddOperator, Operator):
if self.use_transform: if self.use_transform:
bpy.ops.node.translate_attach_remove_on_cancel( bpy.ops.node.translate_attach_remove_on_cancel(
'INVOKE_DEFAULT') 'INVOKE_DEFAULT')
return {'FINISHED'} return {'FINISHED'}
else: else:

View File

@@ -36,22 +36,22 @@ class SelectPattern(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
pattern = StringProperty( pattern = StringProperty(
name="Pattern", name="Pattern",
description="Name filter using '*', '?' and " description="Name filter using '*', '?' and "
"'[abc]' unix style wildcards", "'[abc]' unix style wildcards",
maxlen=64, maxlen=64,
default="*", default="*",
) )
case_sensitive = BoolProperty( case_sensitive = BoolProperty(
name="Case Sensitive", name="Case Sensitive",
description="Do a case sensitive compare", description="Do a case sensitive compare",
default=False, default=False,
) )
extend = BoolProperty( extend = BoolProperty(
name="Extend", name="Extend",
description="Extend the existing selection", description="Extend the existing selection",
default=True, default=True,
) )
def execute(self, context): def execute(self, context):
@@ -116,10 +116,10 @@ class SelectCamera(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
extend = BoolProperty( extend = BoolProperty(
name="Extend", name="Extend",
description="Extend the selection", description="Extend the selection",
default=False default=False
) )
def execute(self, context): def execute(self, context):
scene = context.scene scene = context.scene
@@ -147,24 +147,24 @@ class SelectCamera(Operator):
class SelectHierarchy(Operator): class SelectHierarchy(Operator):
"""Select object relative to the active object's position """ \ """Select object relative to the active object's position """ \
"""in the hierarchy""" """in the hierarchy"""
bl_idname = "object.select_hierarchy" bl_idname = "object.select_hierarchy"
bl_label = "Select Hierarchy" bl_label = "Select Hierarchy"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
direction = EnumProperty( direction = EnumProperty(
items=(('PARENT', "Parent", ""), items=(('PARENT', "Parent", ""),
('CHILD', "Child", ""), ('CHILD', "Child", ""),
), ),
name="Direction", name="Direction",
description="Direction to select in the hierarchy", description="Direction to select in the hierarchy",
default='PARENT') default='PARENT')
extend = BoolProperty( extend = BoolProperty(
name="Extend", name="Extend",
description="Extend the existing selection", description="Extend the existing selection",
default=False, default=False,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -222,18 +222,18 @@ class SubdivisionSet(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
level = IntProperty( level = IntProperty(
name="Level", name="Level",
min=-100, max=100, min=-100, max=100,
soft_min=-6, soft_max=6, soft_min=-6, soft_max=6,
default=1, default=1,
) )
relative = BoolProperty( relative = BoolProperty(
name="Relative", name="Relative",
description=("Apply the subsurf level as an offset " description=("Apply the subsurf level as an offset "
"relative to the current level"), "relative to the current level"),
default=False, default=False,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -306,36 +306,36 @@ class SubdivisionSet(Operator):
class ShapeTransfer(Operator): class ShapeTransfer(Operator):
"""Copy another selected objects active shape to this one by """ \ """Copy another selected objects active shape to this one by """ \
"""applying the relative offsets""" """applying the relative offsets"""
bl_idname = "object.shape_key_transfer" bl_idname = "object.shape_key_transfer"
bl_label = "Transfer Shape Key" bl_label = "Transfer Shape Key"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
mode = EnumProperty( mode = EnumProperty(
items=(('OFFSET', items=(('OFFSET',
"Offset", "Offset",
"Apply the relative positional offset", "Apply the relative positional offset",
), ),
('RELATIVE_FACE', ('RELATIVE_FACE',
"Relative Face", "Relative Face",
"Calculate relative position (using faces)", "Calculate relative position (using faces)",
), ),
('RELATIVE_EDGE', ('RELATIVE_EDGE',
"Relative Edge", "Relative Edge",
"Calculate relative position (using edges)", "Calculate relative position (using edges)",
), ),
), ),
name="Transformation Mode", name="Transformation Mode",
description="Relative shape positions to the new shape method", description="Relative shape positions to the new shape method",
default='OFFSET', default='OFFSET',
) )
use_clamp = BoolProperty( use_clamp = BoolProperty(
name="Clamp Offset", name="Clamp Offset",
description=("Clamp the transformation to the distance each " description=("Clamp the transformation to the distance each "
"vertex moves in the original shape"), "vertex moves in the original shape"),
default=False, default=False,
) )
def _main(self, ob_act, objects, mode='OFFSET', use_clamp=False): def _main(self, ob_act, objects, mode='OFFSET', use_clamp=False):
@@ -368,7 +368,7 @@ class ShapeTransfer(Operator):
orig_normals = me_nos(me.vertices) orig_normals = me_nos(me.vertices)
# actual mesh vertex location isn't as reliable as the base shape :S # actual mesh vertex location isn't as reliable as the base shape :S
#~ orig_coords = me_cos(me.vertices) # orig_coords = me_cos(me.vertices)
orig_coords = me_cos(me.shape_keys.key_blocks[0].data) orig_coords = me_cos(me.shape_keys.key_blocks[0].data)
for ob_other in objects: for ob_other in objects:
@@ -498,7 +498,7 @@ class ShapeTransfer(Operator):
class JoinUVs(Operator): class JoinUVs(Operator):
"""Transfer UV Maps from active to selected objects """ \ """Transfer UV Maps from active to selected objects """ \
"""(needs matching geometry)""" """(needs matching geometry)"""
bl_idname = "object.join_uvs" bl_idname = "object.join_uvs"
bl_label = "Transfer UV Maps" bl_label = "Transfer UV Maps"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
@@ -658,7 +658,7 @@ class MakeDupliFace(Operator):
class IsolateTypeRender(Operator): class IsolateTypeRender(Operator):
"""Hide unselected render objects of same type as active """ \ """Hide unselected render objects of same type as active """ \
"""by setting the hide render flag""" """by setting the hide render flag"""
bl_idname = "object.isolate_type_render" bl_idname = "object.isolate_type_render"
bl_label = "Restrict Render Unselected" bl_label = "Restrict Render Unselected"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
@@ -691,38 +691,27 @@ class ClearAllRestrictRender(Operator):
class TransformsToDeltas(Operator): class TransformsToDeltas(Operator):
"""Convert normal object transforms to delta transforms, """ \ """Convert normal object transforms to delta transforms, """ \
"""any existing delta transforms will be included as well""" """any existing delta transforms will be included as well"""
bl_idname = "object.transforms_to_deltas" bl_idname = "object.transforms_to_deltas"
bl_label = "Transforms to Deltas" bl_label = "Transforms to Deltas"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
mode = EnumProperty( mode = EnumProperty(
items=(('ALL', items=(
"All Transforms", ('ALL', "All Transforms", "Transfer location, rotation, and scale transforms"),
"Transfer location, rotation, and scale transforms", ('LOC', "Location", "Transfer location transforms only"),
), ('ROT', "Rotation", "Transfer rotation transforms only"),
('LOC', ('SCALE', "Scale", "Transfer scale transforms only"),
"Location", ),
"Transfer location transforms only", name="Mode",
), description="Which transforms to transfer",
('ROT', default='ALL',
"Rotation", )
"Transfer rotation transforms only",
),
('SCALE',
"Scale",
"Transfer scale transforms only",
),
),
name="Mode",
description="Which transforms to transfer",
default='ALL',
)
reset_values = BoolProperty( reset_values = BoolProperty(
name="Reset Values", name="Reset Values",
description=("Clear transform values after transferring to deltas"), description=("Clear transform values after transferring to deltas"),
default=True, default=True,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -788,11 +777,11 @@ class TransformsToDeltasAnim(Operator):
def execute(self, context): def execute(self, context):
# map from standard transform paths to "new" transform paths # map from standard transform paths to "new" transform paths
STANDARD_TO_DELTA_PATHS = { STANDARD_TO_DELTA_PATHS = {
"location" : "delta_location", "location": "delta_location",
"rotation_euler" : "delta_rotation_euler", "rotation_euler": "delta_rotation_euler",
"rotation_quaternion" : "delta_rotation_quaternion", "rotation_quaternion": "delta_rotation_quaternion",
#"rotation_axis_angle" : "delta_rotation_axis_angle", # "rotation_axis_angle" : "delta_rotation_axis_angle",
"scale" : "delta_scale" "scale": "delta_scale"
} }
DELTA_PATHS = STANDARD_TO_DELTA_PATHS.values() DELTA_PATHS = STANDARD_TO_DELTA_PATHS.values()
@@ -852,8 +841,8 @@ class TransformsToDeltasAnim(Operator):
fcu.data_path = "delta_rotation_quaternion" fcu.data_path = "delta_rotation_quaternion"
obj.rotation_quaternion.identity() obj.rotation_quaternion.identity()
# XXX: currently not implemented # XXX: currently not implemented
#~ elif fcu.data_path == "rotation_axis_angle": # ~ elif fcu.data_path == "rotation_axis_angle":
#~ fcu.data_path = "delta_rotation_axis_angle" # ~ fcu.data_path = "delta_rotation_axis_angle"
elif fcu.data_path == "scale": elif fcu.data_path == "scale":
fcu.data_path = "delta_scale" fcu.data_path = "delta_scale"
obj.scale = 1.0, 1.0, 1.0 obj.scale = 1.0, 1.0, 1.0

View File

@@ -364,40 +364,45 @@ class AlignObjects(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
bb_quality = BoolProperty( bb_quality = BoolProperty(
name="High Quality", name="High Quality",
description=("Enables high quality calculation of the " description=(
"bounding box for perfect results on complex " "Enables high quality calculation of the "
"shape meshes with rotation/scale (Slow)"), "bounding box for perfect results on complex "
default=True, "shape meshes with rotation/scale (Slow)"
) ),
default=True,
)
align_mode = EnumProperty( align_mode = EnumProperty(
name="Align Mode:", name="Align Mode:",
description="Side of object to use for alignment", description="Side of object to use for alignment",
items=(('OPT_1', "Negative Sides", ""), items=(
('OPT_2', "Centers", ""), ('OPT_1', "Negative Sides", ""),
('OPT_3', "Positive Sides", ""), ('OPT_2', "Centers", ""),
), ('OPT_3', "Positive Sides", ""),
default='OPT_2', ),
) default='OPT_2',
)
relative_to = EnumProperty( relative_to = EnumProperty(
name="Relative To:", name="Relative To:",
description="Reference location to align to", description="Reference location to align to",
items=(('OPT_1', "Scene Origin", "Use the Scene Origin as the position for the selected objects to align to"), items=(
('OPT_2', "3D Cursor", "Use the 3D cursor as the position for the selected objects to align to"), ('OPT_1', "Scene Origin", "Use the Scene Origin as the position for the selected objects to align to"),
('OPT_3', "Selection", "Use the selected objects as the position for the selected objects to align to"), ('OPT_2', "3D Cursor", "Use the 3D cursor as the position for the selected objects to align to"),
('OPT_4', "Active", "Use the active object as the position for the selected objects to align to"), ('OPT_3', "Selection", "Use the selected objects as the position for the selected objects to align to"),
), ('OPT_4', "Active", "Use the active object as the position for the selected objects to align to"),
default='OPT_4', ),
) default='OPT_4',
)
align_axis = EnumProperty( align_axis = EnumProperty(
name="Align", name="Align",
description="Align to axis", description="Align to axis",
items=(('X', "X", ""), items=(
('Y', "Y", ""), ('X', "X", ""),
('Z', "Z", ""), ('Y', "Y", ""),
), ('Z', "Z", ""),
options={'ENUM_FLAG'}, ),
) options={'ENUM_FLAG'},
)
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -53,24 +53,26 @@ class QuickFur(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
density = EnumProperty( density = EnumProperty(
name="Fur Density", name="Fur Density",
items=(('LIGHT', "Light", ""), items=(
('MEDIUM', "Medium", ""), ('LIGHT', "Light", ""),
('HEAVY', "Heavy", "")), ('MEDIUM', "Medium", ""),
default='MEDIUM', ('HEAVY', "Heavy", "")
) ),
default='MEDIUM',
)
view_percentage = IntProperty( view_percentage = IntProperty(
name="View %", name="View %",
min=1, max=100, min=1, max=100,
soft_min=1, soft_max=100, soft_min=1, soft_max=100,
default=10, default=10,
) )
length = FloatProperty( length = FloatProperty(
name="Length", name="Length",
min=0.001, max=100, min=0.001, max=100,
soft_min=0.01, soft_max=10, soft_min=0.01, soft_max=10,
default=0.1, default=0.1,
) )
def execute(self, context): def execute(self, context):
fake_context = context.copy() fake_context = context.copy()
@@ -117,49 +119,51 @@ class QuickExplode(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
style = EnumProperty( style = EnumProperty(
name="Explode Style", name="Explode Style",
items=(('EXPLODE', "Explode", ""), items=(
('BLEND', "Blend", "")), ('EXPLODE', "Explode", ""),
default='EXPLODE', ('BLEND', "Blend", ""),
) ),
default='EXPLODE',
)
amount = IntProperty( amount = IntProperty(
name="Amount of pieces", name="Amount of pieces",
min=2, max=10000, min=2, max=10000,
soft_min=2, soft_max=10000, soft_min=2, soft_max=10000,
default=100, default=100,
) )
frame_duration = IntProperty( frame_duration = IntProperty(
name="Duration", name="Duration",
min=1, max=300000, min=1, max=300000,
soft_min=1, soft_max=10000, soft_min=1, soft_max=10000,
default=50, default=50,
) )
frame_start = IntProperty( frame_start = IntProperty(
name="Start Frame", name="Start Frame",
min=1, max=300000, min=1, max=300000,
soft_min=1, soft_max=10000, soft_min=1, soft_max=10000,
default=1, default=1,
) )
frame_end = IntProperty( frame_end = IntProperty(
name="End Frame", name="End Frame",
min=1, max=300000, min=1, max=300000,
soft_min=1, soft_max=10000, soft_min=1, soft_max=10000,
default=10, default=10,
) )
velocity = FloatProperty( velocity = FloatProperty(
name="Outwards Velocity", name="Outwards Velocity",
min=0, max=300000, min=0, max=300000,
soft_min=0, soft_max=10, soft_min=0, soft_max=10,
default=1, default=1,
) )
fade = BoolProperty( fade = BoolProperty(
name="Fade", name="Fade",
description="Fade the pieces over time", description="Fade the pieces over time",
default=True, default=True,
) )
def execute(self, context): def execute(self, context):
fake_context = context.copy() fake_context = context.copy()
@@ -303,19 +307,20 @@ class QuickSmoke(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
style = EnumProperty( style = EnumProperty(
name="Smoke Style", name="Smoke Style",
items=(('SMOKE', "Smoke", ""), items=(
('FIRE', "Fire", ""), ('SMOKE', "Smoke", ""),
('BOTH', "Smoke + Fire", ""), ('FIRE', "Fire", ""),
), ('BOTH', "Smoke + Fire", ""),
default='SMOKE', ),
) default='SMOKE',
)
show_flows = BoolProperty( show_flows = BoolProperty(
name="Render Smoke Objects", name="Render Smoke Objects",
description="Keep the smoke objects visible during rendering", description="Keep the smoke objects visible during rendering",
default=False, default=False,
) )
def execute(self, context): def execute(self, context):
if not bpy.app.build_options.mod_smoke: if not bpy.app.build_options.mod_smoke:
@@ -390,7 +395,7 @@ class QuickSmoke(Operator):
node_principled = nodes.new(type='ShaderNodeVolumePrincipled') node_principled = nodes.new(type='ShaderNodeVolumePrincipled')
node_principled.location = grid_location(4, 1) node_principled.location = grid_location(4, 1)
links.new(node_principled.outputs["Volume"], links.new(node_principled.outputs["Volume"],
node_out.inputs["Volume"]) node_out.inputs["Volume"])
node_principled.inputs["Density"].default_value = 5.0 node_principled.inputs["Density"].default_value = 5.0
@@ -406,29 +411,31 @@ class QuickFluid(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
style = EnumProperty( style = EnumProperty(
name="Fluid Style", name="Fluid Style",
items=(('INFLOW', "Inflow", ""), items=(
('BASIC', "Basic", "")), ('INFLOW', "Inflow", ""),
default='BASIC', ('BASIC', "Basic", ""),
) ),
default='BASIC',
)
initial_velocity = FloatVectorProperty( initial_velocity = FloatVectorProperty(
name="Initial Velocity", name="Initial Velocity",
description="Initial velocity of the fluid", description="Initial velocity of the fluid",
min=-100.0, max=100.0, min=-100.0, max=100.0,
default=(0.0, 0.0, 0.0), default=(0.0, 0.0, 0.0),
subtype='VELOCITY', subtype='VELOCITY',
) )
show_flows = BoolProperty( show_flows = BoolProperty(
name="Render Fluid Objects", name="Render Fluid Objects",
description="Keep the fluid objects visible during rendering", description="Keep the fluid objects visible during rendering",
default=False, default=False,
) )
start_baking = BoolProperty( start_baking = BoolProperty(
name="Start Fluid Bake", name="Start Fluid Bake",
description=("Start baking the fluid immediately " description=("Start baking the fluid immediately "
"after creating the domain object"), "after creating the domain object"),
default=False, default=False,
) )
def execute(self, context): def execute(self, context):
if not bpy.app.build_options.mod_fluid: if not bpy.app.build_options.mod_fluid:

View File

@@ -104,55 +104,55 @@ class RandomizeLocRotSize(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
random_seed = IntProperty( random_seed = IntProperty(
name="Random Seed", name="Random Seed",
description="Seed value for the random generator", description="Seed value for the random generator",
min=0, min=0,
max=10000, max=10000,
default=0, default=0,
) )
use_delta = BoolProperty( use_delta = BoolProperty(
name="Transform Delta", name="Transform Delta",
description=("Randomize delta transform values " description=("Randomize delta transform values "
"instead of regular transform"), "instead of regular transform"),
default=False, default=False,
) )
use_loc = BoolProperty( use_loc = BoolProperty(
name="Randomize Location", name="Randomize Location",
description="Randomize the location values", description="Randomize the location values",
default=True, default=True,
) )
loc = FloatVectorProperty( loc = FloatVectorProperty(
name="Location", name="Location",
description=("Maximum distance the objects " description=("Maximum distance the objects "
"can spread over each axis"), "can spread over each axis"),
min=-100.0, min=-100.0,
max=100.0, max=100.0,
default=(0.0, 0.0, 0.0), default=(0.0, 0.0, 0.0),
subtype='TRANSLATION', subtype='TRANSLATION',
) )
use_rot = BoolProperty( use_rot = BoolProperty(
name="Randomize Rotation", name="Randomize Rotation",
description="Randomize the rotation values", description="Randomize the rotation values",
default=True, default=True,
) )
rot = FloatVectorProperty( rot = FloatVectorProperty(
name="Rotation", name="Rotation",
description="Maximum rotation over each axis", description="Maximum rotation over each axis",
min=-3.141592, # math.pi min=-3.141592, # math.pi
max=+3.141592, max=+3.141592,
default=(0.0, 0.0, 0.0), default=(0.0, 0.0, 0.0),
subtype='EULER', subtype='EULER',
) )
use_scale = BoolProperty( use_scale = BoolProperty(
name="Randomize Scale", name="Randomize Scale",
description="Randomize the scale values", description="Randomize the scale values",
default=True, default=True,
) )
scale_even = BoolProperty( scale_even = BoolProperty(
name="Scale Even", name="Scale Even",
description="Use the same scale value for all axis", description="Use the same scale value for all axis",
default=False, default=False,
) )
'''scale_min = FloatProperty( '''scale_min = FloatProperty(
name="Minimun Scale Factor", name="Minimun Scale Factor",
@@ -162,13 +162,13 @@ class RandomizeLocRotSize(Operator):
)''' )'''
scale = FloatVectorProperty( scale = FloatVectorProperty(
name="Scale", name="Scale",
description="Maximum scale randomization over each axis", description="Maximum scale randomization over each axis",
min=-100.0, min=-100.0,
max=100.0, max=100.0,
default=(1.0, 1.0, 1.0), default=(1.0, 1.0, 1.0),
subtype='TRANSLATION', subtype='TRANSLATION',
) )
def execute(self, context): def execute(self, context):
seed = self.random_seed seed = self.random_seed

View File

@@ -29,6 +29,7 @@ WindowManager.preset_name = StringProperty(
default="New Preset" default="New Preset"
) )
class AddPresetBase: class AddPresetBase:
"""Base preset class, only for subclassing """Base preset class, only for subclassing
subclasses must define subclasses must define
@@ -41,26 +42,26 @@ class AddPresetBase:
bl_options = {'REGISTER', 'INTERNAL'} bl_options = {'REGISTER', 'INTERNAL'}
name = StringProperty( name = StringProperty(
name="Name", name="Name",
description="Name of the preset, used to make the path name", description="Name of the preset, used to make the path name",
maxlen=64, maxlen=64,
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
remove_name = BoolProperty( remove_name = BoolProperty(
default=False, default=False,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
remove_active = BoolProperty( remove_active = BoolProperty(
default=False, default=False,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
# needed for mix-ins # needed for mix-ins
order = [ order = [
"name", "name",
"remove_name", "remove_name",
"remove_active", "remove_active",
] ]
@staticmethod @staticmethod
def as_filename(name): # could reuse for other presets def as_filename(name): # could reuse for other presets
@@ -225,14 +226,14 @@ class ExecutePreset(Operator):
bl_label = "Execute a Python Preset" bl_label = "Execute a Python Preset"
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
menu_idname = StringProperty( menu_idname = StringProperty(
name="Menu ID Name", name="Menu ID Name",
description="ID name of the menu this was called from", description="ID name of the menu this was called from",
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
def execute(self, context): def execute(self, context):
from os.path import basename, splitext from os.path import basename, splitext
@@ -268,22 +269,26 @@ class PresetMenu(Panel):
@classmethod @classmethod
def draw_panel_header(cls, layout): def draw_panel_header(cls, layout):
layout.emboss = 'NONE' layout.emboss = 'NONE'
layout.popover(cls.bl_space_type, layout.popover(
cls.bl_region_type, cls.bl_space_type,
cls.__name__, cls.bl_region_type,
icon='PRESET', cls.__name__,
text='') icon='PRESET',
text="",
)
@classmethod @classmethod
def draw_menu(cls, layout, text=None): def draw_menu(cls, layout, text=None):
if text == None: if text is None:
text = cls.bl_label text = cls.bl_label
layout.popover(cls.bl_space_type, layout.popover(
cls.bl_region_type, cls.bl_space_type,
cls.__name__, cls.bl_region_type,
icon='PRESET', cls.__name__,
text=text) icon='PRESET',
text=text,
)
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@@ -329,10 +334,10 @@ class AddPresetCamera(AddPresetBase, Operator):
preset_subdir = "camera" preset_subdir = "camera"
use_focal_length = BoolProperty( use_focal_length = BoolProperty(
name="Include Focal Length", name="Include Focal Length",
description="Include focal length into the preset", description="Include focal length into the preset",
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
@property @property
def preset_values(self): def preset_values(self):
@@ -397,12 +402,12 @@ class AddPresetFluid(AddPresetBase, Operator):
preset_defines = [ preset_defines = [
"fluid = bpy.context.fluid" "fluid = bpy.context.fluid"
] ]
preset_values = [ preset_values = [
"fluid.settings.viscosity_base", "fluid.settings.viscosity_base",
"fluid.settings.viscosity_exponent", "fluid.settings.viscosity_exponent",
] ]
preset_subdir = "fluid" preset_subdir = "fluid"
@@ -434,7 +439,7 @@ class AddPresetHairDynamics(AddPresetBase, Operator):
"settings.density_strength", "settings.density_strength",
"settings.voxel_cell_size", "settings.voxel_cell_size",
"settings.pin_stiffness", "settings.pin_stiffness",
] ]
class AddPresetInteraction(AddPresetBase, Operator): class AddPresetInteraction(AddPresetBase, Operator):
@@ -476,11 +481,11 @@ class AddPresetTrackingCamera(AddPresetBase, Operator):
preset_subdir = "tracking_camera" preset_subdir = "tracking_camera"
use_focal_length = BoolProperty( use_focal_length = BoolProperty(
name="Include Focal Length", name="Include Focal Length",
description="Include focal length into the preset", description="Include focal length into the preset",
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
default=True default=True
) )
@property @property
def preset_values(self): def preset_values(self):
@@ -601,10 +606,10 @@ class AddPresetOperator(AddPresetBase, Operator):
preset_menu = "WM_MT_operator_presets" preset_menu = "WM_MT_operator_presets"
operator = StringProperty( operator = StringProperty(
name="Operator", name="Operator",
maxlen=64, maxlen=64,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
preset_defines = [ preset_defines = [
"op = bpy.context.active_operator", "op = bpy.context.active_operator",

View File

@@ -51,7 +51,7 @@ class CopyRigidbodySettings(Operator):
"mesh_source", "mesh_source",
"use_deform", "use_deform",
"enabled", "enabled",
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -93,23 +93,23 @@ class BakeToKeyframes(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
frame_start = IntProperty( frame_start = IntProperty(
name="Start Frame", name="Start Frame",
description="Start frame for baking", description="Start frame for baking",
min=0, max=300000, min=0, max=300000,
default=1, default=1,
) )
frame_end = IntProperty( frame_end = IntProperty(
name="End Frame", name="End Frame",
description="End frame for baking", description="End frame for baking",
min=1, max=300000, min=1, max=300000,
default=250, default=250,
) )
step = IntProperty( step = IntProperty(
name="Frame Step", name="Frame Step",
description="Frame Step", description="Frame Step",
min=1, max=120, min=1, max=120,
default=1, default=1,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -217,28 +217,34 @@ class ConnectRigidBodies(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
con_type = EnumProperty( con_type = EnumProperty(
name="Type", name="Type",
description="Type of generated constraint", description="Type of generated constraint",
# XXX Would be nice to get icons too, but currently not possible ;) # XXX Would be nice to get icons too, but currently not possible ;)
items=tuple((e.identifier, e.name, e.description, e. value) items=tuple(
for e in bpy.types.RigidBodyConstraint.bl_rna.properties["type"].enum_items), (e.identifier, e.name, e.description, e. value)
default='FIXED', for e in bpy.types.RigidBodyConstraint.bl_rna.properties["type"].enum_items
) ),
default='FIXED',
)
pivot_type = EnumProperty( pivot_type = EnumProperty(
name="Location", name="Location",
description="Constraint pivot location", description="Constraint pivot location",
items=(('CENTER', "Center", "Pivot location is between the constrained rigid bodies"), items=(
('ACTIVE', "Active", "Pivot location is at the active object position"), ('CENTER', "Center", "Pivot location is between the constrained rigid bodies"),
('SELECTED', "Selected", "Pivot location is at the selected object position")), ('ACTIVE', "Active", "Pivot location is at the active object position"),
default='CENTER', ('SELECTED', "Selected", "Pivot location is at the selected object position"),
) ),
default='CENTER',
)
connection_pattern = EnumProperty( connection_pattern = EnumProperty(
name="Connection Pattern", name="Connection Pattern",
description="Pattern used to connect objects", description="Pattern used to connect objects",
items=(('SELECTED_TO_ACTIVE', "Selected to Active", "Connect selected objects to the active object"), items=(
('CHAIN_DISTANCE', "Chain by Distance", "Connect objects as a chain based on distance, starting at the active object")), ('SELECTED_TO_ACTIVE', "Selected to Active", "Connect selected objects to the active object"),
default='SELECTED_TO_ACTIVE', ('CHAIN_DISTANCE', "Chain by Distance", "Connect objects as a chain based on distance, starting at the active object"),
) ),
default='SELECTED_TO_ACTIVE',
)
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -103,7 +103,7 @@ class PlayRenderedAnim(Operator):
file_b = rd.frame_path(frame=int(frame_tmp / 10)) file_b = rd.frame_path(frame=int(frame_tmp / 10))
file = ("".join((c if file_b[i] == c else "#") file = ("".join((c if file_b[i] == c else "#")
for i, c in enumerate(file_a))) for i, c in enumerate(file_a)))
del file_a, file_b, frame_tmp del file_a, file_b, frame_tmp
file = bpy.path.abspath(file) # expand '//' file = bpy.path.abspath(file) # expand '//'
else: else:
@@ -115,7 +115,7 @@ class PlayRenderedAnim(Operator):
self.report({'WARNING'}, "File %r not found" % file) self.report({'WARNING'}, "File %r not found" % file)
path_valid = False path_valid = False
#one last try for full range if we used preview range # one last try for full range if we used preview range
if scene.use_preview_range and not path_valid: if scene.use_preview_range and not path_valid:
file = rd.frame_path(frame=scene.frame_start, preview=False) file = rd.frame_path(frame=scene.frame_start, preview=False)
file = bpy.path.abspath(file) # expand '//' file = bpy.path.abspath(file) # expand '//'

View File

@@ -83,11 +83,11 @@ class SequencerCutMulticam(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
camera = IntProperty( camera = IntProperty(
name="Camera", name="Camera",
min=1, max=32, min=1, max=32,
soft_min=1, soft_max=32, soft_min=1, soft_max=32,
default=1, default=1,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -18,7 +18,7 @@
# <pep8 compliant> # <pep8 compliant>
#for full docs see... # for full docs see...
# http://mediawiki.blender.org/index.php/Scripts/Manual/UV_Calculate/Follow_active_quads # http://mediawiki.blender.org/index.php/Scripts/Manual/UV_Calculate/Follow_active_quads
import bpy import bpy
@@ -227,14 +227,14 @@ class FollowActiveQuads(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
mode = bpy.props.EnumProperty( mode = bpy.props.EnumProperty(
name="Edge Length Mode", name="Edge Length Mode",
description="Method to space UV edge loops", description="Method to space UV edge loops",
items=(('EVEN', "Even", "Space all UVs evenly"), items=(('EVEN', "Even", "Space all UVs evenly"),
('LENGTH', "Length", "Average space UVs edge length of each loop"), ('LENGTH', "Length", "Average space UVs edge length of each loop"),
('LENGTH_AVERAGE', "Length Average", "Average space UVs edge length of each loop"), ('LENGTH_AVERAGE', "Length Average", "Average space UVs edge length of each loop"),
), ),
default='LENGTH_AVERAGE', default='LENGTH_AVERAGE',
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -33,7 +33,7 @@ class prettyface:
"yoff", "yoff",
"has_parent", "has_parent",
"rot", "rot",
) )
def __init__(self, data): def __init__(self, data):
self.has_parent = False self.has_parent = False
@@ -63,9 +63,9 @@ class prettyface:
self.width = self.height = d * 2 self.width = self.height = d * 2
#else: # else:
# print(len(data), data) # print(len(data), data)
# raise "Error" # raise "Error"
for pf in data: for pf in data:
pf.has_parent = True pf.has_parent = True
@@ -460,7 +460,7 @@ def lightmap_uvpack(meshes,
# Tall boxes in groups of 2 # Tall boxes in groups of 2
for d, boxes in list(odd_dict.items()): for d, boxes in list(odd_dict.items()):
if d[1] < max_int_dimension: if d[1] < max_int_dimension:
#\boxes.sort(key = lambda a: len(a.children)) # boxes.sort(key=lambda a: len(a.children))
while len(boxes) >= 2: while len(boxes) >= 2:
# print("foo", len(boxes)) # print("foo", len(boxes))
ok = True ok = True
@@ -597,6 +597,7 @@ def unwrap(operator, context, **kwargs):
return {'FINISHED'} return {'FINISHED'}
from bpy.props import BoolProperty, FloatProperty, IntProperty from bpy.props import BoolProperty, FloatProperty, IntProperty
@@ -616,50 +617,55 @@ class LightMapPack(Operator):
bl_options = {'UNDO'} bl_options = {'UNDO'}
PREF_CONTEXT = bpy.props.EnumProperty( PREF_CONTEXT = bpy.props.EnumProperty(
name="Selection", name="Selection",
items=(('SEL_FACES', "Selected Faces", "Space all UVs evenly"), items=(
('ALL_FACES', "All Faces", "Average space UVs edge length of each loop"), ('SEL_FACES', "Selected Faces", "Space all UVs evenly"),
('ALL_OBJECTS', "Selected Mesh Object", "Average space UVs edge length of each loop") ('ALL_FACES', "All Faces", "Average space UVs edge length of each loop"),
), ('ALL_OBJECTS', "Selected Mesh Object", "Average space UVs edge length of each loop")
) ),
)
# Image & UVs... # Image & UVs...
PREF_PACK_IN_ONE = BoolProperty( PREF_PACK_IN_ONE = BoolProperty(
name="Share Tex Space", name="Share Tex Space",
description=("Objects Share texture space, map all objects " description=(
"into 1 uvmap"), "Objects Share texture space, map all objects "
default=True, "into 1 uvmap"
) ),
default=True,
)
PREF_NEW_UVLAYER = BoolProperty( PREF_NEW_UVLAYER = BoolProperty(
name="New UV Map", name="New UV Map",
description="Create a new UV map for every mesh packed", description="Create a new UV map for every mesh packed",
default=False, default=False,
) )
PREF_APPLY_IMAGE = BoolProperty( PREF_APPLY_IMAGE = BoolProperty(
name="New Image", name="New Image",
description=("Assign new images for every mesh (only one if " description=(
"shared tex space enabled)"), "Assign new images for every mesh (only one if "
default=False, "shared tex space enabled)"
) ),
default=False,
)
PREF_IMG_PX_SIZE = IntProperty( PREF_IMG_PX_SIZE = IntProperty(
name="Image Size", name="Image Size",
description="Width and Height for the new image", description="Width and Height for the new image",
min=64, max=5000, min=64, max=5000,
default=512, default=512,
) )
# UV Packing... # UV Packing...
PREF_BOX_DIV = IntProperty( PREF_BOX_DIV = IntProperty(
name="Pack Quality", name="Pack Quality",
description="Pre Packing before the complex boxpack", description="Pre Packing before the complex boxpack",
min=1, max=48, min=1, max=48,
default=12, default=12,
) )
PREF_MARGIN_DIV = FloatProperty( PREF_MARGIN_DIV = FloatProperty(
name="Margin", name="Margin",
description="Size of the margin as a division of the UV", description="Size of the margin as a division of the UV",
min=0.001, max=1.0, min=0.001, max=1.0,
default=0.1, default=0.1,
) )
def execute(self, context): def execute(self, context):
kwargs = self.as_keywords() kwargs = self.as_keywords()

View File

@@ -26,7 +26,7 @@ from mathutils import (
import bpy import bpy
from bpy.types import Operator from bpy.types import Operator
DEG_TO_RAD = 0.017453292519943295 # pi/180.0 DEG_TO_RAD = 0.017453292519943295 # pi/180.0
# see bugs: # see bugs:
# - T31598 (when too small). # - T31598 (when too small).
# - T48086 (when too big). # - T48086 (when too big).
@@ -38,6 +38,7 @@ global USER_FILL_HOLES_QUALITY
USER_FILL_HOLES = None USER_FILL_HOLES = None
USER_FILL_HOLES_QUALITY = None USER_FILL_HOLES_QUALITY = None
def pointInTri2D(v, v1, v2, v3): def pointInTri2D(v, v1, v2, v3):
key = v1.x, v1.y, v2.x, v2.y, v3.x, v3.y key = v1.x, v1.y, v2.x, v2.y, v3.x, v3.y
@@ -93,20 +94,25 @@ def pointInTri2D(v, v1, v2, v3):
def boundsIsland(faces): def boundsIsland(faces):
minx = maxx = faces[0].uv[0][0] # Set initial bounds. minx = maxx = faces[0].uv[0][0] # Set initial bounds.
miny = maxy = faces[0].uv[0][1] miny = maxy = faces[0].uv[0][1]
# print len(faces), minx, maxx, miny , maxy # print len(faces), minx, maxx, miny , maxy
for f in faces: for f in faces:
for uv in f.uv: for uv in f.uv:
x= uv.x x = uv.x
y= uv.y y = uv.y
if x<minx: minx= x if x < minx:
if y<miny: miny= y minx = x
if x>maxx: maxx= x if y < miny:
if y>maxy: maxy= y miny = y
if x > maxx:
maxx = x
if y > maxy:
maxy = y
return minx, miny, maxx, maxy return minx, miny, maxx, maxy
""" """
def boundsEdgeLoop(edges): def boundsEdgeLoop(edges):
minx = maxx = edges[0][0] # Set initial bounds. minx = maxx = edges[0][0] # Set initial bounds.
@@ -128,45 +134,51 @@ def boundsEdgeLoop(edges):
# Only for UV's # Only for UV's
# only returns outline edges for intersection tests. and unique points. # only returns outline edges for intersection tests. and unique points.
def island2Edge(island): def island2Edge(island):
# Vert index edges # Vert index edges
edges = {} edges = {}
unique_points= {} unique_points = {}
for f in island: for f in island:
f_uvkey= map(tuple, f.uv) f_uvkey = map(tuple, f.uv)
for vIdx, edkey in enumerate(f.edge_keys): for vIdx, edkey in enumerate(f.edge_keys):
unique_points[f_uvkey[vIdx]] = f.uv[vIdx] unique_points[f_uvkey[vIdx]] = f.uv[vIdx]
if f.v[vIdx].index > f.v[vIdx-1].index: if f.v[vIdx].index > f.v[vIdx - 1].index:
i1= vIdx-1; i2= vIdx i1 = vIdx - 1
i2 = vIdx
else: else:
i1= vIdx; i2= vIdx-1 i1 = vIdx
i2 = vIdx - 1
try: edges[ f_uvkey[i1], f_uvkey[i2] ] *= 0 # sets any edge with more than 1 user to 0 are not returned. try:
except: edges[ f_uvkey[i1], f_uvkey[i2] ] = (f.uv[i1] - f.uv[i2]).length, edges[f_uvkey[i1], f_uvkey[i2]] *= 0 # sets any edge with more than 1 user to 0 are not returned.
except:
edges[f_uvkey[i1], f_uvkey[i2]] = (f.uv[i1] - f.uv[i2]).length,
# If 2 are the same then they will be together, but full [a,b] order is not correct. # If 2 are the same then they will be together, but full [a,b] order is not correct.
# Sort by length # Sort by length
length_sorted_edges = [(Vector(key[0]), Vector(key[1]), value) for key, value in edges.items() if value != 0] length_sorted_edges = [(Vector(key[0]), Vector(key[1]), value) for key, value in edges.items() if value != 0]
try: length_sorted_edges.sort(key = lambda A: -A[2]) # largest first try:
except: length_sorted_edges.sort(lambda A, B: cmp(B[2], A[2])) length_sorted_edges.sort(key=lambda A: -A[2]) # largest first
except:
length_sorted_edges.sort(lambda A, B: cmp(B[2], A[2]))
# Its okay to leave the length in there. # Its okay to leave the length in there.
#for e in length_sorted_edges: # for e in length_sorted_edges:
# e.pop(2) # e.pop(2)
# return edges and unique points # return edges and unique points
return length_sorted_edges, [v.to_3d() for v in unique_points.values()] return length_sorted_edges, [v.to_3d() for v in unique_points.values()]
# ========================= NOT WORKING???? # ========================= NOT WORKING????
# Find if a points inside an edge loop, unordered. # Find if a points inside an edge loop, unordered.
# pt is and x/y # pt is and x/y
@@ -190,6 +202,7 @@ def pointInEdges(pt, edges):
return intersectCount % 2 return intersectCount % 2
""" """
def pointInIsland(pt, island): def pointInIsland(pt, island):
vec1, vec2, vec3 = Vector(), Vector(), Vector() vec1, vec2, vec3 = Vector(), Vector(), Vector()
for f in island: for f in island:
@@ -212,7 +225,7 @@ def pointInIsland(pt, island):
# box is (left,bottom, right, top) # box is (left,bottom, right, top)
def islandIntersectUvIsland(source, target, SourceOffset): def islandIntersectUvIsland(source, target, SourceOffset):
# Is 1 point in the box, inside the vertLoops # Is 1 point in the box, inside the vertLoops
edgeLoopsSource = source[6] # Pretend this is offset edgeLoopsSource = source[6] # Pretend this is offset
edgeLoopsTarget = target[6] edgeLoopsTarget = target[6]
# Edge intersect test # Edge intersect test
@@ -220,24 +233,24 @@ def islandIntersectUvIsland(source, target, SourceOffset):
for seg in edgeLoopsTarget: for seg in edgeLoopsTarget:
i = geometry.intersect_line_line_2d(seg[0], i = geometry.intersect_line_line_2d(seg[0],
seg[1], seg[1],
SourceOffset+ed[0], SourceOffset + ed[0],
SourceOffset+ed[1], SourceOffset + ed[1],
) )
if i: if i:
return 1 # LINE INTERSECTION return 1 # LINE INTERSECTION
# 1 test for source being totally inside target # 1 test for source being totally inside target
SourceOffset.resize_3d() SourceOffset.resize_3d()
for pv in source[7]: for pv in source[7]:
if pointInIsland(pv+SourceOffset, target[0]): if pointInIsland(pv + SourceOffset, target[0]):
return 2 # SOURCE INSIDE TARGET return 2 # SOURCE INSIDE TARGET
# 2 test for a part of the target being totally inside the source. # 2 test for a part of the target being totally inside the source.
for pv in target[7]: for pv in target[7]:
if pointInIsland(pv-SourceOffset, source[0]): if pointInIsland(pv - SourceOffset, source[0]):
return 3 # PART OF TARGET INSIDE SOURCE. return 3 # PART OF TARGET INSIDE SOURCE.
return 0 # NO INTERSECTION return 0 # NO INTERSECTION
def rotate_uvs(uv_points, angle): def rotate_uvs(uv_points, angle):
@@ -249,7 +262,7 @@ def rotate_uvs(uv_points, angle):
def optiRotateUvIsland(faces): def optiRotateUvIsland(faces):
uv_points = [uv for f in faces for uv in f.uv] uv_points = [uv for f in faces for uv in f.uv]
angle = geometry.box_fit_2d(uv_points) angle = geometry.box_fit_2d(uv_points)
if angle != 0.0: if angle != 0.0:
@@ -270,81 +283,78 @@ def mergeUvIslands(islandList):
global USER_FILL_HOLES global USER_FILL_HOLES
global USER_FILL_HOLES_QUALITY global USER_FILL_HOLES_QUALITY
# Pack islands to bottom LHS # Pack islands to bottom LHS
# Sync with island # Sync with island
#islandTotFaceArea = [] # A list of floats, each island area # islandTotFaceArea = [] # A list of floats, each island area
#islandArea = [] # a list of tuples ( area, w,h) # islandArea = [] # a list of tuples ( area, w,h)
decoratedIslandList = [] decoratedIslandList = []
islandIdx = len(islandList) islandIdx = len(islandList)
while islandIdx: while islandIdx:
islandIdx-=1 islandIdx -= 1
minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx]) minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx])
w, h = maxx-minx, maxy-miny w, h = maxx - minx, maxy - miny
totFaceArea = 0 totFaceArea = 0
offset= Vector((minx, miny)) offset = Vector((minx, miny))
for f in islandList[islandIdx]: for f in islandList[islandIdx]:
for uv in f.uv: for uv in f.uv:
uv -= offset uv -= offset
totFaceArea += f.area totFaceArea += f.area
islandBoundsArea = w*h islandBoundsArea = w * h
efficiency = abs(islandBoundsArea - totFaceArea) efficiency = abs(islandBoundsArea - totFaceArea)
# UV Edge list used for intersections as well as unique points. # UV Edge list used for intersections as well as unique points.
edges, uniqueEdgePoints = island2Edge(islandList[islandIdx]) edges, uniqueEdgePoints = island2Edge(islandList[islandIdx])
decoratedIslandList.append([islandList[islandIdx], totFaceArea, efficiency, islandBoundsArea, w,h, edges, uniqueEdgePoints]) decoratedIslandList.append([islandList[islandIdx], totFaceArea, efficiency, islandBoundsArea, w, h, edges, uniqueEdgePoints])
# Sort by island bounding box area, smallest face area first. # Sort by island bounding box area, smallest face area first.
# no.. chance that to most simple edge loop first. # no.. chance that to most simple edge loop first.
decoratedIslandListAreaSort =decoratedIslandList[:] decoratedIslandListAreaSort = decoratedIslandList[:]
decoratedIslandListAreaSort.sort(key = lambda A: A[3]) decoratedIslandListAreaSort.sort(key=lambda A: A[3])
# sort by efficiency, Least Efficient first. # sort by efficiency, Least Efficient first.
decoratedIslandListEfficSort = decoratedIslandList[:] decoratedIslandListEfficSort = decoratedIslandList[:]
# decoratedIslandListEfficSort.sort(lambda A, B: cmp(B[2], A[2])) # decoratedIslandListEfficSort.sort(lambda A, B: cmp(B[2], A[2]))
decoratedIslandListEfficSort.sort(key = lambda A: -A[2]) decoratedIslandListEfficSort.sort(key=lambda A: -A[2])
# ================================================== THESE CAN BE TWEAKED. # ================================================== THESE CAN BE TWEAKED.
# This is a quality value for the number of tests. # This is a quality value for the number of tests.
# from 1 to 4, generic quality value is from 1 to 100 # from 1 to 4, generic quality value is from 1 to 100
USER_STEP_QUALITY = ((USER_FILL_HOLES_QUALITY - 1) / 25.0) + 1 USER_STEP_QUALITY = ((USER_FILL_HOLES_QUALITY - 1) / 25.0) + 1
# If 100 will test as long as there is enough free space. # If 100 will test as long as there is enough free space.
# this is rarely enough, and testing takes a while, so lower quality speeds this up. # this is rarely enough, and testing takes a while, so lower quality speeds this up.
# 1 means they have the same quality # 1 means they have the same quality
USER_FREE_SPACE_TO_TEST_QUALITY = 1 + (((100 - USER_FILL_HOLES_QUALITY)/100.0) *5) USER_FREE_SPACE_TO_TEST_QUALITY = 1 + (((100 - USER_FILL_HOLES_QUALITY) / 100.0) * 5)
#print 'USER_STEP_QUALITY', USER_STEP_QUALITY # print 'USER_STEP_QUALITY', USER_STEP_QUALITY
#print 'USER_FREE_SPACE_TO_TEST_QUALITY', USER_FREE_SPACE_TO_TEST_QUALITY # print 'USER_FREE_SPACE_TO_TEST_QUALITY', USER_FREE_SPACE_TO_TEST_QUALITY
removedCount = 0 removedCount = 0
areaIslandIdx = 0 areaIslandIdx = 0
ctrl = Window.Qual.CTRL ctrl = Window.Qual.CTRL
BREAK= False BREAK = False
while areaIslandIdx < len(decoratedIslandListAreaSort) and not BREAK: while areaIslandIdx < len(decoratedIslandListAreaSort) and not BREAK:
sourceIsland = decoratedIslandListAreaSort[areaIslandIdx] sourceIsland = decoratedIslandListAreaSort[areaIslandIdx]
# Already packed? # Already packed?
if not sourceIsland[0]: if not sourceIsland[0]:
areaIslandIdx+=1 areaIslandIdx += 1
else: else:
efficIslandIdx = 0 efficIslandIdx = 0
while efficIslandIdx < len(decoratedIslandListEfficSort) and not BREAK: while efficIslandIdx < len(decoratedIslandListEfficSort) and not BREAK:
if Window.GetKeyQualifiers() & ctrl: if Window.GetKeyQualifiers() & ctrl:
BREAK= True BREAK = True
break break
# Now we have 2 islands, if the efficiency of the islands lowers theres an # Now we have 2 islands, if the efficiency of the islands lowers theres an
@@ -355,64 +365,60 @@ def mergeUvIslands(islandList):
targetIsland = decoratedIslandListEfficSort[efficIslandIdx] targetIsland = decoratedIslandListEfficSort[efficIslandIdx]
if sourceIsland[0] == targetIsland[0] or\ if sourceIsland[0] == targetIsland[0] or\
not targetIsland[0] or\ not targetIsland[0] or\
not sourceIsland[0]: not sourceIsland[0]:
pass pass
else: else:
#~ ([island, totFaceArea, efficiency, islandArea, w,h]) #~ ([island, totFaceArea, efficiency, islandArea, w,h])
# Wasted space on target is greater then UV bounding island area. # Wasted space on target is greater then UV bounding island area.
#~ if targetIsland[3] > (sourceIsland[2]) and\ # #~ if targetIsland[3] > (sourceIsland[2]) and\ #
#~ print USER_FREE_SPACE_TO_TEST_QUALITY # ~ print USER_FREE_SPACE_TO_TEST_QUALITY
if targetIsland[2] > (sourceIsland[1] * USER_FREE_SPACE_TO_TEST_QUALITY) and\ if targetIsland[2] > (sourceIsland[1] * USER_FREE_SPACE_TO_TEST_QUALITY) and\
targetIsland[4] > sourceIsland[4] and\ targetIsland[4] > sourceIsland[4] and\
targetIsland[5] > sourceIsland[5]: targetIsland[5] > sourceIsland[5]:
# DEBUG # print '%.10f %.10f' % (targetIsland[3], sourceIsland[1]) # DEBUG # print '%.10f %.10f' % (targetIsland[3], sourceIsland[1])
# These enough spare space lets move the box until it fits # These enough spare space lets move the box until it fits
# How many times does the source fit into the target x/y # How many times does the source fit into the target x/y
blockTestXUnit = targetIsland[4]/sourceIsland[4] blockTestXUnit = targetIsland[4] / sourceIsland[4]
blockTestYUnit = targetIsland[5]/sourceIsland[5] blockTestYUnit = targetIsland[5] / sourceIsland[5]
boxLeft = 0 boxLeft = 0
# Distance we can move between whilst staying inside the targets bounds. # Distance we can move between whilst staying inside the targets bounds.
testWidth = targetIsland[4] - sourceIsland[4] testWidth = targetIsland[4] - sourceIsland[4]
testHeight = targetIsland[5] - sourceIsland[5] testHeight = targetIsland[5] - sourceIsland[5]
# Increment we move each test. x/y # Increment we move each test. x/y
xIncrement = (testWidth / (blockTestXUnit * ((USER_STEP_QUALITY/50)+0.1))) xIncrement = (testWidth / (blockTestXUnit * ((USER_STEP_QUALITY / 50) + 0.1)))
yIncrement = (testHeight / (blockTestYUnit * ((USER_STEP_QUALITY/50)+0.1))) yIncrement = (testHeight / (blockTestYUnit * ((USER_STEP_QUALITY / 50) + 0.1)))
# Make sure were not moving less then a 3rg of our width/height # Make sure were not moving less then a 3rg of our width/height
if xIncrement<sourceIsland[4]/3: if xIncrement < sourceIsland[4] / 3:
xIncrement= sourceIsland[4] xIncrement = sourceIsland[4]
if yIncrement<sourceIsland[5]/3: if yIncrement < sourceIsland[5] / 3:
yIncrement= sourceIsland[5] yIncrement = sourceIsland[5]
boxLeft = 0 # Start 1 back so we can jump into the loop.
boxBottom = 0 # -yIncrement
boxLeft = 0 # Start 1 back so we can jump into the loop. # ~ testcount= 0
boxBottom= 0 #-yIncrement
#~ testcount= 0
while boxBottom <= testHeight: while boxBottom <= testHeight:
# Should we use this? - not needed for now. # Should we use this? - not needed for now.
#~ if Window.GetKeyQualifiers() & ctrl: # ~ if Window.GetKeyQualifiers() & ctrl:
#~ BREAK= True # ~ BREAK= True
#~ break # ~ break
##testcount+=1 # testcount+=1
#print 'Testing intersect' # print 'Testing intersect'
Intersect = islandIntersectUvIsland(sourceIsland, targetIsland, Vector((boxLeft, boxBottom))) Intersect = islandIntersectUvIsland(sourceIsland, targetIsland, Vector((boxLeft, boxBottom)))
#print 'Done', Intersect # print 'Done', Intersect
if Intersect == 1: # Line intersect, don't bother with this any more if Intersect == 1: # Line intersect, don't bother with this any more
pass pass
@@ -429,93 +435,92 @@ def mergeUvIslands(islandList):
# Move the test along its width + SMALL_NUM # Move the test along its width + SMALL_NUM
#boxLeft += sourceIsland[4] + SMALL_NUM #boxLeft += sourceIsland[4] + SMALL_NUM
boxLeft += sourceIsland[4] boxLeft += sourceIsland[4]
elif Intersect == 0: # No intersection?? Place it. elif Intersect == 0: # No intersection?? Place it.
# Progress # Progress
removedCount +=1 removedCount += 1
#XXX Window.DrawProgressBar(0.0, 'Merged: %i islands, Ctrl to finish early.' % removedCount) # XXX Window.DrawProgressBar(0.0, 'Merged: %i islands, Ctrl to finish early.' % removedCount)
# Move faces into new island and offset # Move faces into new island and offset
targetIsland[0].extend(sourceIsland[0]) targetIsland[0].extend(sourceIsland[0])
offset= Vector((boxLeft, boxBottom)) offset = Vector((boxLeft, boxBottom))
for f in sourceIsland[0]: for f in sourceIsland[0]:
for uv in f.uv: for uv in f.uv:
uv+= offset uv += offset
del sourceIsland[0][:] # Empty del sourceIsland[0][:] # Empty
# Move edge loop into new and offset. # Move edge loop into new and offset.
# targetIsland[6].extend(sourceIsland[6]) # targetIsland[6].extend(sourceIsland[6])
#while sourceIsland[6]: # while sourceIsland[6]:
targetIsland[6].extend( [ (\ targetIsland[6].extend([(
(e[0]+offset, e[1]+offset, e[2])\ (e[0] + offset, e[1] + offset, e[2])
) for e in sourceIsland[6] ] ) ) for e in sourceIsland[6]])
del sourceIsland[6][:] # Empty del sourceIsland[6][:] # Empty
# Sort by edge length, reverse so biggest are first. # Sort by edge length, reverse so biggest are first.
try: targetIsland[6].sort(key = lambda A: A[2]) try:
except: targetIsland[6].sort(lambda B,A: cmp(A[2], B[2] )) targetIsland[6].sort(key=lambda A: A[2])
except:
targetIsland[6].sort(lambda B, A: cmp(A[2], B[2]))
targetIsland[7].extend(sourceIsland[7]) targetIsland[7].extend(sourceIsland[7])
offset= Vector((boxLeft, boxBottom, 0.0)) offset = Vector((boxLeft, boxBottom, 0.0))
for p in sourceIsland[7]: for p in sourceIsland[7]:
p+= offset p += offset
del sourceIsland[7][:] del sourceIsland[7][:]
# Decrement the efficiency # Decrement the efficiency
targetIsland[1]+=sourceIsland[1] # Increment totFaceArea targetIsland[1] += sourceIsland[1] # Increment totFaceArea
targetIsland[2]-=sourceIsland[1] # Decrement efficiency targetIsland[2] -= sourceIsland[1] # Decrement efficiency
# IF we ever used these again, should set to 0, eg # IF we ever used these again, should set to 0, eg
sourceIsland[2] = 0 # No area if anyone wants to know sourceIsland[2] = 0 # No area if anyone wants to know
break break
# INCREMENT NEXT LOCATION # INCREMENT NEXT LOCATION
if boxLeft > testWidth: if boxLeft > testWidth:
boxBottom += yIncrement boxBottom += yIncrement
boxLeft = 0.0 boxLeft = 0.0
else: else:
boxLeft += xIncrement boxLeft += xIncrement
##print testcount # print testcount
efficIslandIdx+=1 efficIslandIdx += 1
areaIslandIdx+=1 areaIslandIdx += 1
# Remove empty islands # Remove empty islands
i = len(islandList) i = len(islandList)
while i: while i:
i-=1 i -= 1
if not islandList[i]: if not islandList[i]:
del islandList[i] # Can increment islands removed here. del islandList[i] # Can increment islands removed here.
# Takes groups of faces. assumes face groups are UV groups. # Takes groups of faces. assumes face groups are UV groups.
def getUvIslands(faceGroups, me): def getUvIslands(faceGroups, me):
# Get seams so we don't cross over seams # Get seams so we don't cross over seams
edge_seams = {} # should be a set edge_seams = {} # should be a set
for ed in me.edges: for ed in me.edges:
if ed.use_seam: if ed.use_seam:
edge_seams[ed.key] = None # dummy var- use sets! edge_seams[ed.key] = None # dummy var- use sets!
# Done finding seams # Done finding seams
islandList = [] islandList = []
#XXX Window.DrawProgressBar(0.0, 'Splitting %d projection groups into UV islands:' % len(faceGroups)) # XXX Window.DrawProgressBar(0.0, 'Splitting %d projection groups into UV islands:' % len(faceGroups))
#print '\tSplitting %d projection groups into UV islands:' % len(faceGroups), # print '\tSplitting %d projection groups into UV islands:' % len(faceGroups),
# Find grouped faces # Find grouped faces
faceGroupIdx = len(faceGroups) faceGroupIdx = len(faceGroups)
while faceGroupIdx: while faceGroupIdx:
faceGroupIdx-=1 faceGroupIdx -= 1
faces = faceGroups[faceGroupIdx] faces = faceGroups[faceGroupIdx]
if not faces: if not faces:
@@ -526,37 +531,38 @@ def getUvIslands(faceGroups, me):
for i, f in enumerate(faces): for i, f in enumerate(faces):
for ed_key in f.edge_keys: for ed_key in f.edge_keys:
if ed_key in edge_seams: # DELIMIT SEAMS! ;) if ed_key in edge_seams: # DELIMIT SEAMS! ;)
edge_users[ed_key] = [] # so as not to raise an error edge_users[ed_key] = [] # so as not to raise an error
else: else:
try: edge_users[ed_key].append(i) try:
except: edge_users[ed_key] = [i] edge_users[ed_key].append(i)
except:
edge_users[ed_key] = [i]
# Modes # Modes
# 0 - face not yet touched. # 0 - face not yet touched.
# 1 - added to island list, and need to search # 1 - added to island list, and need to search
# 2 - touched and searched - don't touch again. # 2 - touched and searched - don't touch again.
face_modes = [0] * len(faces) # initialize zero - untested. face_modes = [0] * len(faces) # initialize zero - untested.
face_modes[0] = 1 # start the search with face 1 face_modes[0] = 1 # start the search with face 1
newIsland = [] newIsland = []
newIsland.append(faces[0]) newIsland.append(faces[0])
ok = True ok = True
while ok: while ok:
ok = True ok = True
while ok: while ok:
ok= False ok = False
for i in range(len(faces)): for i in range(len(faces)):
if face_modes[i] == 1: # search if face_modes[i] == 1: # search
for ed_key in faces[i].edge_keys: for ed_key in faces[i].edge_keys:
for ii in edge_users[ed_key]: for ii in edge_users[ed_key]:
if i != ii and face_modes[ii] == 0: if i != ii and face_modes[ii] == 0:
face_modes[ii] = ok = 1 # mark as searched face_modes[ii] = ok = 1 # mark as searched
newIsland.append(faces[ii]) newIsland.append(faces[ii])
# mark as searched, don't look again. # mark as searched, don't look again.
@@ -574,7 +580,7 @@ def getUvIslands(faceGroups, me):
break break
# if not ok will stop looping # if not ok will stop looping
#XXX Window.DrawProgressBar(0.1, 'Optimizing Rotation for %i UV Islands' % len(islandList)) # XXX Window.DrawProgressBar(0.1, 'Optimizing Rotation for %i UV Islands' % len(islandList))
for island in islandList: for island in islandList:
optiRotateUvIsland(island) optiRotateUvIsland(island)
@@ -584,9 +590,8 @@ def getUvIslands(faceGroups, me):
def packIslands(islandList): def packIslands(islandList):
if USER_FILL_HOLES: if USER_FILL_HOLES:
#XXX Window.DrawProgressBar(0.1, 'Merging Islands (Ctrl: skip merge)...') # XXX Window.DrawProgressBar(0.1, 'Merging Islands (Ctrl: skip merge)...')
mergeUvIslands(islandList) # Modify in place mergeUvIslands(islandList) # Modify in place
# Now we have UV islands, we need to pack them. # Now we have UV islands, we need to pack them.
@@ -603,16 +608,16 @@ def packIslands(islandList):
while islandIdx < len(islandList): while islandIdx < len(islandList):
minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx]) minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx])
w, h = maxx-minx, maxy-miny w, h = maxx - minx, maxy - miny
if USER_ISLAND_MARGIN: if USER_ISLAND_MARGIN:
minx -= USER_ISLAND_MARGIN# *w minx -= USER_ISLAND_MARGIN # *w
miny -= USER_ISLAND_MARGIN# *h miny -= USER_ISLAND_MARGIN # *h
maxx += USER_ISLAND_MARGIN# *w maxx += USER_ISLAND_MARGIN # *w
maxy += USER_ISLAND_MARGIN# *h maxy += USER_ISLAND_MARGIN # *h
# recalc width and height # recalc width and height
w, h = maxx-minx, maxy-miny w, h = maxx - minx, maxy - miny
if w < SMALL_NUM: if w < SMALL_NUM:
w = SMALL_NUM w = SMALL_NUM
@@ -628,24 +633,24 @@ def packIslands(islandList):
# Add to boxList. use the island idx for the BOX id. # Add to boxList. use the island idx for the BOX id.
packBoxes.append([0, 0, w, h]) packBoxes.append([0, 0, w, h])
islandIdx+=1 islandIdx += 1
# Now we have a list of boxes to pack that syncs # Now we have a list of boxes to pack that syncs
# with the islands. # with the islands.
#print '\tPacking UV Islands...' # print '\tPacking UV Islands...'
#XXX Window.DrawProgressBar(0.7, "Packing %i UV Islands..." % len(packBoxes) ) # XXX Window.DrawProgressBar(0.7, "Packing %i UV Islands..." % len(packBoxes) )
# time1 = time.time() # time1 = time.time()
packWidth, packHeight = geometry.box_pack_2d(packBoxes) packWidth, packHeight = geometry.box_pack_2d(packBoxes)
# print 'Box Packing Time:', time.time() - time1 # print 'Box Packing Time:', time.time() - time1
#if len(pa ckedLs) != len(islandList): # if len(pa ckedLs) != len(islandList):
# raise ValueError("Packed boxes differs from original length") # raise ValueError("Packed boxes differs from original length")
#print '\tWriting Packed Data to faces' # print '\tWriting Packed Data to faces'
#XXX Window.DrawProgressBar(0.8, "Writing Packed Data to faces") # XXX Window.DrawProgressBar(0.8, "Writing Packed Data to faces")
# Sort by ID, so there in sync again # Sort by ID, so there in sync again
islandIdx = len(islandList) islandIdx = len(islandList)
@@ -661,16 +666,16 @@ def packIslands(islandList):
xfactor = yfactor = 1.0 / max(packWidth, packHeight) xfactor = yfactor = 1.0 / max(packWidth, packHeight)
while islandIdx: while islandIdx:
islandIdx -=1 islandIdx -= 1
# Write the packed values to the UV's # Write the packed values to the UV's
xoffset = packBoxes[islandIdx][0] - islandOffsetList[islandIdx][0] xoffset = packBoxes[islandIdx][0] - islandOffsetList[islandIdx][0]
yoffset = packBoxes[islandIdx][1] - islandOffsetList[islandIdx][1] yoffset = packBoxes[islandIdx][1] - islandOffsetList[islandIdx][1]
for f in islandList[islandIdx]: # Offsetting the UV's so they fit in there packed box for f in islandList[islandIdx]: # Offsetting the UV's so they fit in there packed box
for uv in f.uv: for uv in f.uv:
uv.x= (uv.x+xoffset) * xfactor uv.x = (uv.x + xoffset) * xfactor
uv.y= (uv.y+yoffset) * yfactor uv.y = (uv.y + yoffset) * yfactor
def VectoQuat(vec): def VectoQuat(vec):
@@ -679,7 +684,8 @@ def VectoQuat(vec):
class thickface: class thickface:
__slost__= "v", "uv", "no", "area", "edge_keys" __slost__ = "v", "uv", "no", "area", "edge_keys"
def __init__(self, face, uv_layer, mesh_verts): def __init__(self, face, uv_layer, mesh_verts):
self.v = [mesh_verts[i] for i in face.vertices] self.v = [mesh_verts[i] for i in face.vertices]
self.uv = [uv_layer[i].uv for i in face.loop_indices] self.uv = [uv_layer[i].uv for i in face.loop_indices]
@@ -700,18 +706,20 @@ def main_consts():
ROTMAT_2D_POS_45D = Matrix.Rotation(radians(45.0), 2) ROTMAT_2D_POS_45D = Matrix.Rotation(radians(45.0), 2)
RotMatStepRotation = [] RotMatStepRotation = []
rot_angle = 22.5 #45.0/2 rot_angle = 22.5 # 45.0/2
while rot_angle > 0.1: while rot_angle > 0.1:
RotMatStepRotation.append([ RotMatStepRotation.append([
Matrix.Rotation(radians(+rot_angle), 2), Matrix.Rotation(radians(+rot_angle), 2),
Matrix.Rotation(radians(-rot_angle), 2), Matrix.Rotation(radians(-rot_angle), 2),
]) ])
rot_angle = rot_angle/2.0 rot_angle = rot_angle / 2.0
global ob global ob
ob = None ob = None
def main(context, def main(context,
island_margin, island_margin,
projection_limit, projection_limit,
@@ -741,18 +749,18 @@ def main(context,
# Create the variables. # Create the variables.
USER_PROJECTION_LIMIT = projection_limit USER_PROJECTION_LIMIT = projection_limit
USER_ONLY_SELECTED_FACES = True USER_ONLY_SELECTED_FACES = True
USER_SHARE_SPACE = 1 # Only for hole filling. USER_SHARE_SPACE = 1 # Only for hole filling.
USER_STRETCH_ASPECT = stretch_to_bounds USER_STRETCH_ASPECT = stretch_to_bounds
USER_ISLAND_MARGIN = island_margin # Only for hole filling. USER_ISLAND_MARGIN = island_margin # Only for hole filling.
USER_FILL_HOLES = 0 USER_FILL_HOLES = 0
USER_FILL_HOLES_QUALITY = 50 # Only for hole filling. USER_FILL_HOLES_QUALITY = 50 # Only for hole filling.
USER_VIEW_INIT = 0 # Only for hole filling. USER_VIEW_INIT = 0 # Only for hole filling.
is_editmode = (context.active_object.mode == 'EDIT') is_editmode = (context.active_object.mode == 'EDIT')
if is_editmode: if is_editmode:
obList = [ob for ob in [context.active_object] if ob and ob.type == 'MESH'] obList = [ob for ob in [context.active_object] if ob and ob.type == 'MESH']
else: else:
obList = [ob for ob in context.selected_editable_objects if ob and ob.type == 'MESH'] obList = [ob for ob in context.selected_editable_objects if ob and ob.type == 'MESH']
USER_ONLY_SELECTED_FACES = False USER_ONLY_SELECTED_FACES = False
if not obList: if not obList:
@@ -770,15 +778,14 @@ def main(context,
time.sleep(10) time.sleep(10)
''' '''
#~ XXX if not Draw.PupBlock(ob % len(obList), pup_block): # ~ XXX if not Draw.PupBlock(ob % len(obList), pup_block):
#~ XXX return # ~ XXX return
#~ XXX del ob # ~ XXX del ob
# Convert from being button types # Convert from being button types
USER_PROJECTION_LIMIT_CONVERTED = cos(USER_PROJECTION_LIMIT * DEG_TO_RAD) USER_PROJECTION_LIMIT_CONVERTED = cos(USER_PROJECTION_LIMIT * DEG_TO_RAD)
USER_PROJECTION_LIMIT_HALF_CONVERTED = cos((USER_PROJECTION_LIMIT/2) * DEG_TO_RAD) USER_PROJECTION_LIMIT_HALF_CONVERTED = cos((USER_PROJECTION_LIMIT / 2) * DEG_TO_RAD)
# Toggle Edit mode # Toggle Edit mode
is_editmode = (context.active_object.mode == 'EDIT') is_editmode = (context.active_object.mode == 'EDIT')
@@ -788,19 +795,18 @@ def main(context,
if USER_SHARE_SPACE: if USER_SHARE_SPACE:
# Sort by data name so we get consistent results # Sort by data name so we get consistent results
obList.sort(key = lambda ob: ob.data.name) obList.sort(key=lambda ob: ob.data.name)
collected_islandList= [] collected_islandList = []
#XXX Window.WaitCursor(1) # XXX Window.WaitCursor(1)
time1 = time.time() time1 = time.time()
# Tag as False so we don't operate on the same mesh twice. # Tag as False so we don't operate on the same mesh twice.
#XXX bpy.data.meshes.tag = False # XXX bpy.data.meshes.tag = False
for me in bpy.data.meshes: for me in bpy.data.meshes:
me.tag = False me.tag = False
for ob in obList: for ob in obList:
me = ob.data me = ob.data
@@ -810,7 +816,7 @@ def main(context,
# Tag as used # Tag as used
me.tag = True me.tag = True
if not me.uv_layers: # Mesh has no UV Coords, don't bother. if not me.uv_layers: # Mesh has no UV Coords, don't bother.
me.uv_layers.new() me.uv_layers.new()
uv_layer = me.uv_layers.active.data uv_layer = me.uv_layers.active.data
@@ -821,7 +827,7 @@ def main(context,
else: else:
meshFaces = [thickface(f, uv_layer, me_verts) for i, f in enumerate(me.polygons)] meshFaces = [thickface(f, uv_layer, me_verts) for i, f in enumerate(me.polygons)]
#XXX Window.DrawProgressBar(0.1, 'SmartProj UV Unwrapper, mapping "%s", %i faces.' % (me.name, len(meshFaces))) # XXX Window.DrawProgressBar(0.1, 'SmartProj UV Unwrapper, mapping "%s", %i faces.' % (me.name, len(meshFaces)))
# ======= # =======
# Generate a projection list from face normals, this is meant to be smart :) # Generate a projection list from face normals, this is meant to be smart :)
@@ -849,17 +855,15 @@ def main(context,
# 0d is 1.0 # 0d is 1.0
# 180 IS -0.59846 # 180 IS -0.59846
# Initialize projectVecs # Initialize projectVecs
if USER_VIEW_INIT: if USER_VIEW_INIT:
# Generate Projection # Generate Projection
projectVecs = [Vector(Window.GetViewVector()) * ob.matrix_world.inverted().to_3x3()] # We add to this along the way projectVecs = [Vector(Window.GetViewVector()) * ob.matrix_world.inverted().to_3x3()] # We add to this along the way
else: else:
projectVecs = [] projectVecs = []
newProjectVec = meshFaces[0].no newProjectVec = meshFaces[0].no
newProjectMeshFaces = [] # Popping stuffs it up. newProjectMeshFaces = [] # Popping stuffs it up.
# Pretend that the most unique angle is ages away to start the loop off # Pretend that the most unique angle is ages away to start the loop off
mostUniqueAngle = -1.0 mostUniqueAngle = -1.0
@@ -867,14 +871,12 @@ def main(context,
# This is popped # This is popped
tempMeshFaces = meshFaces[:] tempMeshFaces = meshFaces[:]
# This while only gathers projection vecs, faces are assigned later on. # This while only gathers projection vecs, faces are assigned later on.
while 1: while 1:
# If theres none there then start with the largest face # If theres none there then start with the largest face
# add all the faces that are close. # add all the faces that are close.
for fIdx in range(len(tempMeshFaces)-1, -1, -1): for fIdx in range(len(tempMeshFaces) - 1, -1, -1):
# Use half the angle limit so we don't overweight faces towards this # Use half the angle limit so we don't overweight faces towards this
# normal and hog all the faces. # normal and hog all the faces.
if newProjectVec.dot(tempMeshFaces[fIdx].no) > USER_PROJECTION_LIMIT_HALF_CONVERTED: if newProjectVec.dot(tempMeshFaces[fIdx].no) > USER_PROJECTION_LIMIT_HALF_CONVERTED:
@@ -892,24 +894,23 @@ def main(context,
for fprop in newProjectMeshFaces: for fprop in newProjectMeshFaces:
averageVec += fprop.no * ((fprop.area * user_area_weight) + (1.0 - user_area_weight)) 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 if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN
projectVecs.append(averageVec.normalized()) projectVecs.append(averageVec.normalized())
# Get the next vec! # Get the next vec!
# Pick the face thats most different to all existing angles :) # Pick the face thats most different to all existing angles :)
mostUniqueAngle = 1.0 # 1.0 is 0d. no difference. mostUniqueAngle = 1.0 # 1.0 is 0d. no difference.
mostUniqueIndex = 0 # dummy mostUniqueIndex = 0 # dummy
for fIdx in range(len(tempMeshFaces)-1, -1, -1): for fIdx in range(len(tempMeshFaces) - 1, -1, -1):
angleDifference = -1.0 # 180d difference. angleDifference = -1.0 # 180d difference.
# Get the closest vec angle we are to. # Get the closest vec angle we are to.
for p in projectVecs: for p in projectVecs:
temp_angle_diff= p.dot(tempMeshFaces[fIdx].no) temp_angle_diff = p.dot(tempMeshFaces[fIdx].no)
if angleDifference < temp_angle_diff: if angleDifference < temp_angle_diff:
angleDifference= temp_angle_diff angleDifference = temp_angle_diff
if angleDifference < mostUniqueAngle: if angleDifference < mostUniqueAngle:
# We have a new most different angle # We have a new most different angle
@@ -917,30 +918,28 @@ def main(context,
mostUniqueAngle = angleDifference mostUniqueAngle = angleDifference
if mostUniqueAngle < USER_PROJECTION_LIMIT_CONVERTED: if mostUniqueAngle < USER_PROJECTION_LIMIT_CONVERTED:
#print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectMeshFaces) # print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectMeshFaces)
# Now weight the vector to all its faces, will give a more direct projection # Now weight the vector to all its faces, will give a more direct projection
# if the face its self was not representative of the normal from surrounding faces. # if the face its self was not representative of the normal from surrounding faces.
newProjectVec = tempMeshFaces[mostUniqueIndex].no newProjectVec = tempMeshFaces[mostUniqueIndex].no
newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)] newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)]
else: else:
if len(projectVecs) >= 1: # Must have at least 2 projections if len(projectVecs) >= 1: # Must have at least 2 projections
break break
# If there are only zero area faces then its possible # If there are only zero area faces then its possible
# there are no projectionVecs # there are no projectionVecs
if not len(projectVecs): if not len(projectVecs):
Draw.PupMenu('error, no projection vecs where generated, 0 area faces can cause this.') Draw.PupMenu('error, no projection vecs where generated, 0 area faces can cause this.')
return return
faceProjectionGroupList =[[] for i in range(len(projectVecs)) ] faceProjectionGroupList = [[] for i in range(len(projectVecs))]
# MAP and Arrange # We know there are 3 or 4 faces here # MAP and Arrange # We know there are 3 or 4 faces here
for fIdx in range(len(meshFaces)-1, -1, -1): for fIdx in range(len(meshFaces) - 1, -1, -1):
fvec = meshFaces[fIdx].no fvec = meshFaces[fIdx].no
i = len(projectVecs) i = len(projectVecs)
@@ -949,11 +948,11 @@ def main(context,
bestAngIdx = 0 bestAngIdx = 0
# Cycle through the remaining, first already done # Cycle through the remaining, first already done
while i-1: while i - 1:
i-=1 i -= 1
newAng = fvec.dot(projectVecs[i]) newAng = fvec.dot(projectVecs[i])
if newAng > bestAng: # Reverse logic for dotvecs if newAng > bestAng: # Reverse logic for dotvecs
bestAng = newAng bestAng = newAng
bestAngIdx = i bestAngIdx = i
@@ -962,7 +961,6 @@ def main(context,
# Cull faceProjectionGroupList, # Cull faceProjectionGroupList,
# Now faceProjectionGroupList is full of faces that face match the project Vecs list # Now faceProjectionGroupList is full of faces that face match the project Vecs list
for i in range(len(projectVecs)): for i in range(len(projectVecs)):
# Account for projectVecs having no faces. # Account for projectVecs having no faces.
@@ -979,7 +977,6 @@ def main(context,
# XXX - note, between mathutils in 2.4 and 2.5 the order changed. # XXX - note, between mathutils in 2.4 and 2.5 the order changed.
f_uv[j][:] = (MatQuat * v.co).xy f_uv[j][:] = (MatQuat * v.co).xy
if USER_SHARE_SPACE: if USER_SHARE_SPACE:
# Should we collect and pack later? # Should we collect and pack later?
islandList = getUvIslands(faceProjectionGroupList, me) islandList = getUvIslands(faceProjectionGroupList, me)
@@ -990,12 +987,11 @@ def main(context,
islandList = getUvIslands(faceProjectionGroupList, me) islandList = getUvIslands(faceProjectionGroupList, me)
packIslands(islandList) packIslands(islandList)
# update the mesh here if we need to. # update the mesh here if we need to.
# We want to pack all in 1 go, so pack now # We want to pack all in 1 go, so pack now
if USER_SHARE_SPACE: if USER_SHARE_SPACE:
#XXX Window.DrawProgressBar(0.9, "Box Packing for all objects...") # XXX Window.DrawProgressBar(0.9, "Box Packing for all objects...")
packIslands(collected_islandList) packIslands(collected_islandList)
print("Smart Projection time: %.2f" % (time.time() - time1)) print("Smart Projection time: %.2f" % (time.time() - time1))
@@ -1006,31 +1002,32 @@ def main(context,
bpy.ops.object.mode_set(mode='EDIT') bpy.ops.object.mode_set(mode='EDIT')
if use_aspect: if use_aspect:
import bmesh import bmesh
aspect = context.scene.uvedit_aspect(context.active_object) aspect = context.scene.uvedit_aspect(context.active_object)
if aspect[0] > aspect[1]: if aspect[0] > aspect[1]:
aspect[0] = aspect[1]/aspect[0]; aspect[0] = aspect[1] / aspect[0]
aspect[1] = 1.0 aspect[1] = 1.0
else: else:
aspect[1] = aspect[0]/aspect[1]; aspect[1] = aspect[0] / aspect[1]
aspect[0] = 1.0 aspect[0] = 1.0
bm = bmesh.from_edit_mesh(me) bm = bmesh.from_edit_mesh(me)
uv_act = bm.loops.layers.uv.active uv_act = bm.loops.layers.uv.active
faces = [f for f in bm.faces if f.select] faces = [f for f in bm.faces if f.select]
for f in faces: for f in faces:
for l in f.loops: for l in f.loops:
l[uv_act].uv[0] *= aspect[0] l[uv_act].uv[0] *= aspect[0]
l[uv_act].uv[1] *= aspect[1] l[uv_act].uv[1] *= aspect[1]
dict_matrix.clear() dict_matrix.clear()
#XXX Window.DrawProgressBar(1.0, "") # XXX Window.DrawProgressBar(1.0, "")
#XXX Window.WaitCursor(0) # XXX Window.WaitCursor(0)
#XXX Window.RedrawAll() # XXX Window.RedrawAll()
""" """
pup_block = [\ pup_block = [\
@@ -1052,41 +1049,41 @@ from bpy.props import FloatProperty, BoolProperty
class SmartProject(Operator): class SmartProject(Operator):
"""This script projection unwraps the selected faces of a mesh """ \ """This script projection unwraps the selected faces of a mesh """ \
"""(it operates on all selected mesh objects, and can be used """ \ """(it operates on all selected mesh objects, and can be used """ \
"""to unwrap selected faces, or all faces)""" """to unwrap selected faces, or all faces)"""
bl_idname = "uv.smart_project" bl_idname = "uv.smart_project"
bl_label = "Smart UV Project" bl_label = "Smart UV Project"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
angle_limit = FloatProperty( angle_limit = FloatProperty(
name="Angle Limit", name="Angle Limit",
description="Lower for more projection groups, higher for less distortion", description="Lower for more projection groups, higher for less distortion",
min=1.0, max=89.0, min=1.0, max=89.0,
default=66.0, default=66.0,
) )
island_margin = FloatProperty( island_margin = FloatProperty(
name="Island Margin", name="Island Margin",
description="Margin to reduce bleed from adjacent islands", description="Margin to reduce bleed from adjacent islands",
unit='LENGTH', subtype='DISTANCE', unit='LENGTH', subtype='DISTANCE',
min=0.0, max=1.0, min=0.0, max=1.0,
default=0.0, default=0.0,
) )
user_area_weight = FloatProperty( user_area_weight = FloatProperty(
name="Area Weight", name="Area Weight",
description="Weight projections vector by faces with larger areas", description="Weight projections vector by faces with larger areas",
min=0.0, max=1.0, min=0.0, max=1.0,
default=0.0, default=0.0,
) )
use_aspect = BoolProperty( use_aspect = BoolProperty(
name="Correct Aspect", name="Correct Aspect",
description="Map UVs taking image aspect ratio into account", description="Map UVs taking image aspect ratio into account",
default=True default=True
) )
stretch_to_bounds = BoolProperty( stretch_to_bounds = BoolProperty(
name="Stretch to UV Bounds", name="Stretch to UV Bounds",
description="Stretch the final output to texture bounds", description="Stretch the final output to texture bounds",
default=True, default=True,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -139,36 +139,36 @@ class VertexPaintDirt(Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
blur_strength = FloatProperty( blur_strength = FloatProperty(
name="Blur Strength", name="Blur Strength",
description="Blur strength per iteration", description="Blur strength per iteration",
min=0.01, max=1.0, min=0.01, max=1.0,
default=1.0, default=1.0,
) )
blur_iterations = IntProperty( blur_iterations = IntProperty(
name="Blur Iterations", name="Blur Iterations",
description="Number of times to blur the colors (higher blurs more)", description="Number of times to blur the colors (higher blurs more)",
min=0, max=40, min=0, max=40,
default=1, default=1,
) )
clean_angle = FloatProperty( clean_angle = FloatProperty(
name="Highlight Angle", name="Highlight Angle",
description="Less than 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=pi, min=0.0, max=pi,
default=pi, default=pi,
unit="ROTATION", unit="ROTATION",
) )
dirt_angle = FloatProperty( dirt_angle = FloatProperty(
name="Dirt Angle", name="Dirt Angle",
description="Less than 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=pi, min=0.0, max=pi,
default=0.0, default=0.0,
unit="ROTATION", unit="ROTATION",
) )
dirt_only = BoolProperty( dirt_only = BoolProperty(
name="Dirt Only", name="Dirt Only",
description="Don't calculate cleans for convex areas", description="Don't calculate cleans for convex areas",
default=False, default=False,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -39,13 +39,16 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
totface = mesh.total_face_sel totface = mesh.total_face_sel
totedge = mesh.total_edge_sel totedge = mesh.total_edge_sel
#~ totvert = mesh.total_vert_sel # totvert = mesh.total_vert_sel
if select_mode[2] and totface == 1: if select_mode[2] and totface == 1:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', bpy.ops.mesh.extrude_region_move(
TRANSFORM_OT_translate={ 'INVOKE_REGION_WIN',
"constraint_orientation": 'NORMAL', TRANSFORM_OT_translate={
"constraint_axis": (False, False, True)}) "constraint_orientation": 'NORMAL',
"constraint_axis": (False, False, True),
}
)
elif select_mode[2] and totface > 1: elif select_mode[2] and totface > 1:
bpy.ops.mesh.extrude_faces_move('INVOKE_REGION_WIN') bpy.ops.mesh.extrude_faces_move('INVOKE_REGION_WIN')
elif select_mode[1] and totedge >= 1: elif select_mode[1] and totedge >= 1:
@@ -77,25 +80,32 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
totface = mesh.total_face_sel totface = mesh.total_face_sel
totedge = mesh.total_edge_sel totedge = mesh.total_edge_sel
#~ totvert = mesh.total_vert_sel # totvert = mesh.total_vert_sel
if totface >= 1: if totface >= 1:
if use_vert_normals: if use_vert_normals:
bpy.ops.mesh.extrude_region_shrink_fatten('INVOKE_REGION_WIN', bpy.ops.mesh.extrude_region_shrink_fatten(
TRANSFORM_OT_shrink_fatten={}) 'INVOKE_REGION_WIN',
TRANSFORM_OT_shrink_fatten={},
)
else: else:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', bpy.ops.mesh.extrude_region_move(
TRANSFORM_OT_translate={ 'INVOKE_REGION_WIN',
"constraint_orientation": 'NORMAL',
"constraint_axis": (False, False, True)})
elif totedge == 1:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN',
TRANSFORM_OT_translate={ TRANSFORM_OT_translate={
"constraint_orientation": 'NORMAL', "constraint_orientation": 'NORMAL',
# not a popular choice, too restrictive for retopo. "constraint_axis": (False, False, True),
#~ "constraint_axis": (True, True, False)}) },
"constraint_axis": (False, False, False)}) )
elif totedge == 1:
bpy.ops.mesh.extrude_region_move(
'INVOKE_REGION_WIN',
TRANSFORM_OT_translate={
"constraint_orientation": 'NORMAL',
# not a popular choice, too restrictive for retopo.
# "constraint_axis": (True, True, False)})
"constraint_axis": (False, False, False),
})
else: else:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN') bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN')
@@ -134,40 +144,40 @@ class VIEW3D_OT_select_or_deselect_all(Operator):
bl_options = {'UNDO'} bl_options = {'UNDO'}
extend = BoolProperty( extend = BoolProperty(
name="Extend", name="Extend",
description="Extend selection instead of deselecting everything first", description="Extend selection instead of deselecting everything first",
default=False, default=False,
) )
toggle = BoolProperty( toggle = BoolProperty(
name="Toggle", name="Toggle",
description="Toggle the selection", description="Toggle the selection",
default=False, default=False,
) )
deselect = BoolProperty( deselect = BoolProperty(
name="Deselect", name="Deselect",
description="Remove from selection", description="Remove from selection",
default=False, default=False,
) )
center = BoolProperty( center = BoolProperty(
name="Center", name="Center",
description="Use the object center when selecting, in editmode used to extend object selection", description="Use the object center when selecting, in editmode used to extend object selection",
default=False, default=False,
) )
enumerate = BoolProperty( enumerate = BoolProperty(
name="Enumerate", name="Enumerate",
description="List objects under the mouse (object mode only)", description="List objects under the mouse (object mode only)",
default=False, default=False,
) )
object = BoolProperty( object = BoolProperty(
name="Object", name="Object",
description="Use object selection (editmode only)", description="Use object selection (editmode only)",
default=False, default=False,
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):

View File

@@ -36,37 +36,37 @@ from bpy.app.translations import pgettext_tip as tip_
rna_path_prop = StringProperty( rna_path_prop = StringProperty(
name="Context Attributes", name="Context Attributes",
description="RNA context string", description="RNA context string",
maxlen=1024, maxlen=1024,
) )
rna_reverse_prop = BoolProperty( rna_reverse_prop = BoolProperty(
name="Reverse", name="Reverse",
description="Cycle backwards", description="Cycle backwards",
default=False, default=False,
) )
rna_wrap_prop = BoolProperty( rna_wrap_prop = BoolProperty(
name="Wrap", name="Wrap",
description="Wrap back to the first/last values", description="Wrap back to the first/last values",
default=False, default=False,
) )
rna_relative_prop = BoolProperty( rna_relative_prop = BoolProperty(
name="Relative", name="Relative",
description="Apply relative to the current value (delta)", description="Apply relative to the current value (delta)",
default=False, default=False,
) )
rna_space_type_prop = EnumProperty( rna_space_type_prop = EnumProperty(
name="Type", name="Type",
items=tuple( items=tuple(
(e.identifier, e.name, "", e. value) (e.identifier, e.name, "", e. value)
for e in bpy.types.Space.bl_rna.properties["type"].enum_items for e in bpy.types.Space.bl_rna.properties["type"].enum_items
), ),
default='EMPTY', default='EMPTY',
) )
def context_path_validate(context, data_path): def context_path_validate(context, data_path):
@@ -163,14 +163,14 @@ class BRUSH_OT_active_index_set(Operator):
bl_label = "Set Brush Number" bl_label = "Set Brush Number"
mode = StringProperty( mode = StringProperty(
name="Mode", name="Mode",
description="Paint mode to set brush for", description="Paint mode to set brush for",
maxlen=1024, maxlen=1024,
) )
index = IntProperty( index = IntProperty(
name="Number", name="Number",
description="Brush number", description="Brush number",
) )
_attr_dict = { _attr_dict = {
"sculpt": "use_paint_sculpt", "sculpt": "use_paint_sculpt",
@@ -201,10 +201,10 @@ class WM_OT_context_set_boolean(Operator):
data_path = rna_path_prop data_path = rna_path_prop
value = BoolProperty( value = BoolProperty(
name="Value", name="Value",
description="Assignment value", description="Assignment value",
default=True, default=True,
) )
execute = execute_context_assign execute = execute_context_assign
@@ -217,10 +217,10 @@ class WM_OT_context_set_int(Operator): # same as enum
data_path = rna_path_prop data_path = rna_path_prop
value = IntProperty( value = IntProperty(
name="Value", name="Value",
description="Assign value", description="Assign value",
default=0, default=0,
) )
relative = rna_relative_prop relative = rna_relative_prop
execute = execute_context_assign execute = execute_context_assign
@@ -234,10 +234,10 @@ class WM_OT_context_scale_float(Operator):
data_path = rna_path_prop data_path = rna_path_prop
value = FloatProperty( value = FloatProperty(
name="Value", name="Value",
description="Assign value", description="Assign value",
default=1.0, default=1.0,
) )
def execute(self, context): def execute(self, context):
data_path = self.data_path data_path = self.data_path
@@ -262,15 +262,15 @@ class WM_OT_context_scale_int(Operator):
data_path = rna_path_prop data_path = rna_path_prop
value = FloatProperty( value = FloatProperty(
name="Value", name="Value",
description="Assign value", description="Assign value",
default=1.0, default=1.0,
) )
always_step = BoolProperty( always_step = BoolProperty(
name="Always Step", name="Always Step",
description="Always adjust the value by a minimum of 1 when 'value' is not 1.0", description="Always adjust the value by a minimum of 1 when 'value' is not 1.0",
default=True, default=True,
) )
def execute(self, context): def execute(self, context):
data_path = self.data_path data_path = self.data_path
@@ -305,10 +305,10 @@ class WM_OT_context_set_float(Operator): # same as enum
data_path = rna_path_prop data_path = rna_path_prop
value = FloatProperty( value = FloatProperty(
name="Value", name="Value",
description="Assignment value", description="Assignment value",
default=0.0, default=0.0,
) )
relative = rna_relative_prop relative = rna_relative_prop
execute = execute_context_assign execute = execute_context_assign
@@ -322,10 +322,10 @@ class WM_OT_context_set_string(Operator): # same as enum
data_path = rna_path_prop data_path = rna_path_prop
value = StringProperty( value = StringProperty(
name="Value", name="Value",
description="Assign value", description="Assign value",
maxlen=1024, maxlen=1024,
) )
execute = execute_context_assign execute = execute_context_assign
@@ -338,10 +338,10 @@ class WM_OT_context_set_enum(Operator):
data_path = rna_path_prop data_path = rna_path_prop
value = StringProperty( value = StringProperty(
name="Value", name="Value",
description="Assignment value (as a string)", description="Assignment value (as a string)",
maxlen=1024, maxlen=1024,
) )
execute = execute_context_assign execute = execute_context_assign
@@ -354,10 +354,10 @@ class WM_OT_context_set_value(Operator):
data_path = rna_path_prop data_path = rna_path_prop
value = StringProperty( value = StringProperty(
name="Value", name="Value",
description="Assignment value (as a string)", description="Assignment value (as a string)",
maxlen=1024, maxlen=1024,
) )
def execute(self, context): def execute(self, context):
data_path = self.data_path data_path = self.data_path
@@ -394,15 +394,15 @@ class WM_OT_context_toggle_enum(Operator):
data_path = rna_path_prop data_path = rna_path_prop
value_1 = StringProperty( value_1 = StringProperty(
name="Value", name="Value",
description="Toggle enum", description="Toggle enum",
maxlen=1024, maxlen=1024,
) )
value_2 = StringProperty( value_2 = StringProperty(
name="Value", name="Value",
description="Toggle enum", description="Toggle enum",
maxlen=1024, maxlen=1024,
) )
def execute(self, context): def execute(self, context):
data_path = self.data_path data_path = self.data_path
@@ -426,7 +426,7 @@ class WM_OT_context_toggle_enum(Operator):
class WM_OT_context_cycle_int(Operator): class WM_OT_context_cycle_int(Operator):
"""Set a context value (useful for cycling active material, """ \ """Set a context value (useful for cycling active material, """ \
"""vertex keys, groups, etc.)""" """vertex keys, groups, etc.)"""
bl_idname = "wm.context_cycle_int" bl_idname = "wm.context_cycle_int"
bl_label = "Context Int Cycle" bl_label = "Context Int Cycle"
bl_options = {'UNDO', 'INTERNAL'} bl_options = {'UNDO', 'INTERNAL'}
@@ -519,7 +519,7 @@ class WM_OT_context_cycle_enum(Operator):
class WM_OT_context_cycle_array(Operator): class WM_OT_context_cycle_array(Operator):
"""Set a context array value """ \ """Set a context array value """ \
"""(useful for cycling the active mesh edit mode)""" """(useful for cycling the active mesh edit mode)"""
bl_idname = "wm.context_cycle_array" bl_idname = "wm.context_cycle_array"
bl_label = "Context Array Cycle" bl_label = "Context Array Cycle"
bl_options = {'UNDO', 'INTERNAL'} bl_options = {'UNDO', 'INTERNAL'}
@@ -603,15 +603,15 @@ class WM_OT_operator_pie_enum(Operator):
bl_label = "Operator Enum Pie" bl_label = "Operator Enum Pie"
bl_options = {'UNDO', 'INTERNAL'} bl_options = {'UNDO', 'INTERNAL'}
data_path = StringProperty( data_path = StringProperty(
name="Operator", name="Operator",
description="Operator name (in python as string)", description="Operator name (in python as string)",
maxlen=1024, maxlen=1024,
) )
prop_string = StringProperty( prop_string = StringProperty(
name="Property", name="Property",
description="Property name (as a string)", description="Property name (as a string)",
maxlen=1024, maxlen=1024,
) )
def invoke(self, context, event): def invoke(self, context, event):
wm = context.window_manager wm = context.window_manager
@@ -648,10 +648,10 @@ class WM_OT_context_set_id(Operator):
data_path = rna_path_prop data_path = rna_path_prop
value = StringProperty( value = StringProperty(
name="Value", name="Value",
description="Assign value", description="Assign value",
maxlen=1024, maxlen=1024,
) )
def execute(self, context): def execute(self, context):
value = self.value value = self.value
@@ -679,16 +679,16 @@ class WM_OT_context_set_id(Operator):
doc_id = StringProperty( doc_id = StringProperty(
name="Doc ID", name="Doc ID",
maxlen=1024, maxlen=1024,
options={'HIDDEN'}, options={'HIDDEN'},
) )
data_path_iter = StringProperty( data_path_iter = StringProperty(
description="The data path relative to the context, must point to an iterable") description="The data path relative to the context, must point to an iterable")
data_path_item = StringProperty( data_path_item = StringProperty(
description="The data path from each iterable to the value (int or float)") description="The data path from each iterable to the value (int or float)")
class WM_OT_context_collection_boolean_set(Operator): class WM_OT_context_collection_boolean_set(Operator):
@@ -701,12 +701,12 @@ class WM_OT_context_collection_boolean_set(Operator):
data_path_item = data_path_item data_path_item = data_path_item
type = EnumProperty( type = EnumProperty(
name="Type", name="Type",
items=(('TOGGLE', "Toggle", ""), items=(('TOGGLE', "Toggle", ""),
('ENABLE', "Enable", ""), ('ENABLE', "Enable", ""),
('DISABLE', "Disable", ""), ('DISABLE', "Disable", ""),
), ),
) )
def execute(self, context): def execute(self, context):
data_path_iter = self.data_path_iter data_path_iter = self.data_path_iter
@@ -759,18 +759,18 @@ class WM_OT_context_modal_mouse(Operator):
data_path_iter = data_path_iter data_path_iter = data_path_iter
data_path_item = data_path_item data_path_item = data_path_item
header_text = StringProperty( header_text = StringProperty(
name="Header Text", name="Header Text",
description="Text to display in header during scale", description="Text to display in header during scale",
) )
input_scale = FloatProperty( input_scale = FloatProperty(
description="Scale the mouse movement by this value before applying the delta", description="Scale the mouse movement by this value before applying the delta",
default=0.01, default=0.01,
) )
invert = BoolProperty( invert = BoolProperty(
description="Invert the mouse input", description="Invert the mouse input",
default=False, default=False,
) )
initial_x = IntProperty(options={'HIDDEN'}) initial_x = IntProperty(options={'HIDDEN'})
def _values_store(self, context): def _values_store(self, context):
@@ -865,9 +865,9 @@ class WM_OT_url_open(Operator):
bl_options = {'INTERNAL'} bl_options = {'INTERNAL'}
url = StringProperty( url = StringProperty(
name="URL", name="URL",
description="URL to open", description="URL to open",
) )
def execute(self, context): def execute(self, context):
import webbrowser import webbrowser
@@ -882,9 +882,9 @@ class WM_OT_path_open(Operator):
bl_options = {'INTERNAL'} bl_options = {'INTERNAL'}
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
def execute(self, context): def execute(self, context):
import sys import sys
@@ -1068,44 +1068,44 @@ class WM_OT_doc_view(Operator):
rna_path = StringProperty( rna_path = StringProperty(
name="Property Edit", name="Property Edit",
description="Property data_path edit", description="Property data_path edit",
maxlen=1024, maxlen=1024,
options={'HIDDEN'}, options={'HIDDEN'},
) )
rna_value = StringProperty( rna_value = StringProperty(
name="Property Value", name="Property Value",
description="Property value edit", description="Property value edit",
maxlen=1024, maxlen=1024,
) )
rna_property = StringProperty( rna_property = StringProperty(
name="Property Name", name="Property Name",
description="Property name edit", description="Property name edit",
maxlen=1024, maxlen=1024,
) )
rna_min = FloatProperty( rna_min = FloatProperty(
name="Min", name="Min",
default=-10000.0, default=-10000.0,
precision=3, precision=3,
) )
rna_max = FloatProperty( rna_max = FloatProperty(
name="Max", name="Max",
default=10000.0, default=10000.0,
precision=3, precision=3,
) )
rna_use_soft_limits = BoolProperty( rna_use_soft_limits = BoolProperty(
name="Use Soft Limits", name="Use Soft Limits",
) )
rna_is_overridable_static = BoolProperty( rna_is_overridable_static = BoolProperty(
name="Is Statically Overridable", name="Is Statically Overridable",
default=False, default=False,
) )
class WM_OT_properties_edit(Operator): class WM_OT_properties_edit(Operator):
@@ -1124,8 +1124,8 @@ class WM_OT_properties_edit(Operator):
soft_min = rna_min soft_min = rna_min
soft_max = rna_max soft_max = rna_max
description = StringProperty( description = StringProperty(
name="Tooltip", name="Tooltip",
) )
def _cmp_props_get(self): def _cmp_props_get(self):
# Changing these properties will refresh the UI # Changing these properties will refresh the UI
@@ -1363,9 +1363,9 @@ class WM_OT_properties_context_change(Operator):
bl_options = {'INTERNAL'} bl_options = {'INTERNAL'}
context = StringProperty( context = StringProperty(
name="Context", name="Context",
maxlen=64, maxlen=64,
) )
def execute(self, context): def execute(self, context):
context.space_data.context = self.context context.space_data.context = self.context
@@ -1401,8 +1401,8 @@ class WM_OT_keyconfig_activate(Operator):
bl_label = "Activate Keyconfig" bl_label = "Activate Keyconfig"
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
) )
def execute(self, context): def execute(self, context):
if bpy.utils.keyconfig_set(self.filepath, report=self.report): if bpy.utils.keyconfig_set(self.filepath, report=self.report):
@@ -1436,8 +1436,8 @@ class WM_OT_appconfig_activate(Operator):
bl_label = "Activate Application Configuration" bl_label = "Activate Application Configuration"
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
) )
def execute(self, context): def execute(self, context):
import os import os
@@ -1461,9 +1461,9 @@ class WM_OT_sysinfo(Operator):
bl_label = "Save System Info" bl_label = "Save System Info"
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
def execute(self, context): def execute(self, context):
import sys_info import sys_info
@@ -1475,7 +1475,7 @@ class WM_OT_sysinfo(Operator):
if not self.filepath: if not self.filepath:
self.filepath = os.path.join( self.filepath = os.path.join(
os.path.expanduser("~"), "system-info.txt") os.path.expanduser("~"), "system-info.txt")
wm = context.window_manager wm = context.window_manager
wm.fileselect_add(self) wm.fileselect_add(self)
@@ -1539,29 +1539,29 @@ class WM_OT_keyconfig_import(Operator):
bl_label = "Import Key Configuration..." bl_label = "Import Key Configuration..."
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
default="keymap.py", default="keymap.py",
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
name="Filter folders", name="Filter folders",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_text = BoolProperty( filter_text = BoolProperty(
name="Filter text", name="Filter text",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_python = BoolProperty( filter_python = BoolProperty(
name="Filter python", name="Filter python",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
keep_original = BoolProperty( keep_original = BoolProperty(
name="Keep original", name="Keep original",
description="Keep original file after copying to configuration folder", description="Keep original file after copying to configuration folder",
default=True, default=True,
) )
def execute(self, context): def execute(self, context):
import os import os
@@ -1606,24 +1606,24 @@ class WM_OT_keyconfig_export(Operator):
bl_label = "Export Key Configuration..." bl_label = "Export Key Configuration..."
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
default="keymap.py", default="keymap.py",
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
name="Filter folders", name="Filter folders",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_text = BoolProperty( filter_text = BoolProperty(
name="Filter text", name="Filter text",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_python = BoolProperty( filter_python = BoolProperty(
name="Filter python", name="Filter python",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
def execute(self, context): def execute(self, context):
from bpy_extras import keyconfig_utils from bpy_extras import keyconfig_utils
@@ -1656,9 +1656,9 @@ class WM_OT_keymap_restore(Operator):
bl_label = "Restore Key Map(s)" bl_label = "Restore Key Map(s)"
all = BoolProperty( all = BoolProperty(
name="All Keymaps", name="All Keymaps",
description="Restore all keymaps to default", description="Restore all keymaps to default",
) )
def execute(self, context): def execute(self, context):
wm = context.window_manager wm = context.window_manager
@@ -1679,9 +1679,9 @@ class WM_OT_keyitem_restore(Operator):
bl_label = "Restore Key Map Item" bl_label = "Restore Key Map Item"
item_id = IntProperty( item_id = IntProperty(
name="Item Identifier", name="Item Identifier",
description="Identifier of the item to remove", description="Identifier of the item to remove",
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -1726,9 +1726,9 @@ class WM_OT_keyitem_remove(Operator):
bl_label = "Remove Key Map Item" bl_label = "Remove Key Map Item"
item_id = IntProperty( item_id = IntProperty(
name="Item Identifier", name="Item Identifier",
description="Identifier of the item to remove", description="Identifier of the item to remove",
) )
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -1794,9 +1794,9 @@ class WM_OT_addon_enable(Operator):
bl_label = "Enable Add-on" bl_label = "Enable Add-on"
module = StringProperty( module = StringProperty(
name="Module", name="Module",
description="Module name of the add-on to enable", description="Module name of the add-on to enable",
) )
def execute(self, context): def execute(self, context):
import addon_utils import addon_utils
@@ -1840,9 +1840,9 @@ class WM_OT_addon_disable(Operator):
bl_label = "Disable Add-on" bl_label = "Disable Add-on"
module = StringProperty( module = StringProperty(
name="Module", name="Module",
description="Module name of the add-on to disable", description="Module name of the add-on to disable",
) )
def execute(self, context): def execute(self, context):
import addon_utils import addon_utils
@@ -1869,8 +1869,8 @@ class WM_OT_owner_enable(Operator):
bl_label = "Enable Add-on" bl_label = "Enable Add-on"
owner_id = StringProperty( owner_id = StringProperty(
name="UI Tag", name="UI Tag",
) )
def execute(self, context): def execute(self, context):
workspace = context.workspace workspace = context.workspace
@@ -1884,8 +1884,8 @@ class WM_OT_owner_disable(Operator):
bl_label = "Disable UI Tag" bl_label = "Disable UI Tag"
owner_id = StringProperty( owner_id = StringProperty(
name="UI Tag", name="UI Tag",
) )
def execute(self, context): def execute(self, context):
workspace = context.workspace workspace = context.workspace
@@ -1900,22 +1900,22 @@ class WM_OT_theme_install(Operator):
bl_label = "Install Theme..." bl_label = "Install Theme..."
overwrite = BoolProperty( overwrite = BoolProperty(
name="Overwrite", name="Overwrite",
description="Remove existing theme file if exists", description="Remove existing theme file if exists",
default=True, default=True,
) )
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
name="Filter folders", name="Filter folders",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_glob = StringProperty( filter_glob = StringProperty(
default="*.xml", default="*.xml",
options={'HIDDEN'}, options={'HIDDEN'},
) )
def execute(self, context): def execute(self, context):
import os import os
@@ -1977,33 +1977,33 @@ class WM_OT_addon_install(Operator):
bl_label = "Install Add-on from File..." bl_label = "Install Add-on from File..."
overwrite = BoolProperty( overwrite = BoolProperty(
name="Overwrite", name="Overwrite",
description="Remove existing add-ons with the same ID", description="Remove existing add-ons with the same ID",
default=True, default=True,
) )
target = EnumProperty( target = EnumProperty(
name="Target Path", name="Target Path",
items=(('DEFAULT', "Default", ""), items=(('DEFAULT', "Default", ""),
('PREFS', "User Prefs", "")), ('PREFS', "User Prefs", "")),
) )
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
name="Filter folders", name="Filter folders",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_python = BoolProperty( filter_python = BoolProperty(
name="Filter python", name="Filter python",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_glob = StringProperty( filter_glob = StringProperty(
default="*.py;*.zip", default="*.py;*.zip",
options={'HIDDEN'}, options={'HIDDEN'},
) )
def execute(self, context): def execute(self, context):
import addon_utils import addon_utils
@@ -2131,9 +2131,9 @@ class WM_OT_addon_remove(Operator):
bl_label = "Remove Add-on" bl_label = "Remove Add-on"
module = StringProperty( module = StringProperty(
name="Module", name="Module",
description="Module name of the add-on to remove", description="Module name of the add-on to remove",
) )
@staticmethod @staticmethod
def path_from_addon(module): def path_from_addon(module):
@@ -2191,9 +2191,9 @@ class WM_OT_addon_expand(Operator):
bl_options = {'INTERNAL'} bl_options = {'INTERNAL'}
module = StringProperty( module = StringProperty(
name="Module", name="Module",
description="Module name of the add-on to expand", description="Module name of the add-on to expand",
) )
def execute(self, context): def execute(self, context):
import addon_utils import addon_utils
@@ -2215,9 +2215,9 @@ class WM_OT_addon_userpref_show(Operator):
bl_options = {'INTERNAL'} bl_options = {'INTERNAL'}
module = StringProperty( module = StringProperty(
name="Module", name="Module",
description="Module name of the add-on to expand", description="Module name of the add-on to expand",
) )
def execute(self, context): def execute(self, context):
import addon_utils import addon_utils
@@ -2246,23 +2246,23 @@ class WM_OT_app_template_install(Operator):
bl_label = "Install Template from File..." bl_label = "Install Template from File..."
overwrite = BoolProperty( overwrite = BoolProperty(
name="Overwrite", name="Overwrite",
description="Remove existing template with the same ID", description="Remove existing template with the same ID",
default=True, default=True,
) )
filepath = StringProperty( filepath = StringProperty(
subtype='FILE_PATH', subtype='FILE_PATH',
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
name="Filter folders", name="Filter folders",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_glob = StringProperty( filter_glob = StringProperty(
default="*.zip", default="*.zip",
options={'HIDDEN'}, options={'HIDDEN'},
) )
def execute(self, context): def execute(self, context):
import traceback import traceback
@@ -2345,16 +2345,16 @@ class WM_OT_tool_set_by_name(Operator):
bl_label = "Set Tool By Name" bl_label = "Set Tool By Name"
name = StringProperty( name = StringProperty(
name="Text", name="Text",
description="Display name of the tool", description="Display name of the tool",
) )
cycle = BoolProperty( cycle = BoolProperty(
name="Cycle", name="Cycle",
description="Cycle through tools in this group", description="Cycle through tools in this group",
default=False, default=False,
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
) )
space_type = rna_space_type_prop space_type = rna_space_type_prop
@@ -2411,21 +2411,21 @@ class WM_OT_studiolight_install(Operator):
bl_label = "Install Custom Studio Light" bl_label = "Install Custom Studio Light"
files = CollectionProperty( files = CollectionProperty(
name="File Path", name="File Path",
type=OperatorFileListElement, type=OperatorFileListElement,
) )
directory = StringProperty( directory = StringProperty(
subtype='DIR_PATH', subtype='DIR_PATH',
) )
filter_folder = BoolProperty( filter_folder = BoolProperty(
name="Filter folders", name="Filter folders",
default=True, default=True,
options={'HIDDEN'}, options={'HIDDEN'},
) )
filter_glob = StringProperty( filter_glob = StringProperty(
default="*.png;*.jpg;*.hdr;*.exr", default="*.png;*.jpg;*.hdr;*.exr",
options={'HIDDEN'}, options={'HIDDEN'},
) )
orientation = EnumProperty( orientation = EnumProperty(
items=( items=(
("MATCAP", "MatCap", ""), ("MATCAP", "MatCap", ""),

View File

@@ -59,6 +59,8 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
# Generic Layout - Used as base for filtering popovers used in all animation editors # Generic Layout - Used as base for filtering popovers used in all animation editors
# Used for DopeSheet, NLA, and Graph Editors # Used for DopeSheet, NLA, and Graph Editors
class DopesheetFilterPopoverBase: class DopesheetFilterPopoverBase:
bl_region_type = 'HEADER' bl_region_type = 'HEADER'
bl_label = "Filters" bl_label = "Filters"
@@ -211,11 +213,13 @@ class DOPESHEET_HT_header(Header):
TIME_HT_editor_buttons.draw_header(context, layout) TIME_HT_editor_buttons.draw_header(context, layout)
else: else:
layout.prop(st, "ui_mode", text="") layout.prop(st, "ui_mode", text="")
layout.popover(space_type='DOPESHEET_EDITOR', layout.popover(
region_type='HEADER', space_type='DOPESHEET_EDITOR',
panel_type="DOPESHEET_PT_filters", region_type='HEADER',
text="", panel_type="DOPESHEET_PT_filters",
icon='FILTER') text="",
icon='FILTER',
)
DOPESHEET_MT_editor_menus.draw_collapsible(context, layout) DOPESHEET_MT_editor_menus.draw_collapsible(context, layout)
DOPESHEET_HT_editor_buttons.draw_header(context, layout) DOPESHEET_HT_editor_buttons.draw_header(context, layout)

View File

@@ -23,7 +23,7 @@ from bpy.types import Header, Menu, Panel
from .space_dopesheet import ( from .space_dopesheet import (
DopesheetFilterPopoverBase, DopesheetFilterPopoverBase,
dopesheet_filter, dopesheet_filter,
) )
class GRAPH_HT_header(Header): class GRAPH_HT_header(Header):
@@ -41,11 +41,13 @@ class GRAPH_HT_header(Header):
# Now a exposed as a sub-space type # Now a exposed as a sub-space type
# layout.prop(st, "mode", text="") # layout.prop(st, "mode", text="")
layout.popover(space_type='GRAPH_EDITOR', layout.popover(
region_type='HEADER', space_type='GRAPH_EDITOR',
panel_type="GRAPH_PT_filters", region_type='HEADER',
text="", panel_type="GRAPH_PT_filters",
icon='FILTER') text="",
icon='FILTER',
)
GRAPH_MT_editor_menus.draw_collapsible(context, layout) GRAPH_MT_editor_menus.draw_collapsible(context, layout)

View File

@@ -23,7 +23,7 @@ from bpy.types import Header, Menu, Panel
from .space_dopesheet import ( from .space_dopesheet import (
DopesheetFilterPopoverBase, DopesheetFilterPopoverBase,
dopesheet_filter, dopesheet_filter,
) )
class NLA_HT_header(Header): class NLA_HT_header(Header):
@@ -37,11 +37,13 @@ class NLA_HT_header(Header):
row = layout.row(align=True) row = layout.row(align=True)
row.template_header() row.template_header()
layout.popover(space_type='NLA_EDITOR', layout.popover(
region_type='HEADER', space_type='NLA_EDITOR',
panel_type="NLA_PT_filters", region_type='HEADER',
text="", panel_type="NLA_PT_filters",
icon='FILTER') text="",
icon='FILTER',
)
NLA_MT_editor_menus.draw_collapsible(context, layout) NLA_MT_editor_menus.draw_collapsible(context, layout)

View File

@@ -91,14 +91,18 @@ class TIME_MT_editor_menus(Menu):
@staticmethod @staticmethod
def draw_menus(layout, context): def draw_menus(layout, context):
layout.popover(space_type='DOPESHEET_EDITOR', layout.popover(
region_type='HEADER', space_type='DOPESHEET_EDITOR',
panel_type="TIME_PT_playback", region_type='HEADER',
text="Playback") panel_type="TIME_PT_playback",
layout.popover(space_type='DOPESHEET_EDITOR', text="Playback",
region_type='HEADER', )
panel_type="TIME_PT_keyframing_settings", layout.popover(
text="Keying") space_type='DOPESHEET_EDITOR',
region_type='HEADER',
panel_type="TIME_PT_keyframing_settings",
text="Keying",
)
layout.menu("TIME_MT_view") layout.menu("TIME_MT_view")
layout.menu("TIME_MT_marker") layout.menu("TIME_MT_marker")

View File

@@ -8,7 +8,7 @@ bl_info = {
"warning": "", "warning": "",
"wiki_url": "", "wiki_url": "",
"category": "Add Mesh", "category": "Add Mesh",
} }
import bpy import bpy
@@ -22,11 +22,12 @@ def add_object(self, context):
scale_x = self.scale.x scale_x = self.scale.x
scale_y = self.scale.y scale_y = self.scale.y
verts = [Vector((-1 * scale_x, 1 * scale_y, 0)), verts = [
Vector((1 * scale_x, 1 * scale_y, 0)), Vector((-1 * scale_x, 1 * scale_y, 0)),
Vector((1 * scale_x, -1 * scale_y, 0)), Vector((1 * scale_x, 1 * scale_y, 0)),
Vector((-1 * scale_x, -1 * scale_y, 0)), Vector((1 * scale_x, -1 * scale_y, 0)),
] Vector((-1 * scale_x, -1 * scale_y, 0)),
]
edges = [] edges = []
faces = [[0, 1, 2, 3]] faces = [[0, 1, 2, 3]]
@@ -45,11 +46,11 @@ class OBJECT_OT_add_object(Operator, AddObjectHelper):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
scale = FloatVectorProperty( scale = FloatVectorProperty(
name="scale", name="scale",
default=(1.0, 1.0, 1.0), default=(1.0, 1.0, 1.0),
subtype='TRANSLATION', subtype='TRANSLATION',
description="scaling", description="scaling",
) )
def execute(self, context): def execute(self, context):
@@ -72,7 +73,7 @@ def add_object_manual_map():
url_manual_prefix = "https://docs.blender.org/manual/en/dev/" url_manual_prefix = "https://docs.blender.org/manual/en/dev/"
url_manual_mapping = ( url_manual_mapping = (
("bpy.ops.mesh.add_object", "editors/3dview/object"), ("bpy.ops.mesh.add_object", "editors/3dview/object"),
) )
return url_manual_prefix, url_manual_mapping return url_manual_prefix, url_manual_mapping

View File

@@ -73,21 +73,27 @@ def main():
# When --help or no args are given, print this help # When --help or no args are given, print this help
usage_text = ( usage_text = (
"Run blender in background mode with this script:" "Run blender in background mode with this script:"
" blender --background --python " + __file__ + " -- [options]" " blender --background --python " + __file__ + " -- [options]"
) )
parser = argparse.ArgumentParser(description=usage_text) parser = argparse.ArgumentParser(description=usage_text)
# Example utility, add some text and renders or saves it (with options) # Example utility, add some text and renders or saves it (with options)
# Possible types are: string, int, long, choice, float and complex. # Possible types are: string, int, long, choice, float and complex.
parser.add_argument("-t", "--text", dest="text", type=str, required=True, parser.add_argument(
help="This text will be used to render an image") "-t", "--text", dest="text", type=str, required=True,
help="This text will be used to render an image",
)
parser.add_argument("-s", "--save", dest="save_path", metavar='FILE', parser.add_argument(
help="Save the generated file to the specified path") "-s", "--save", dest="save_path", metavar='FILE',
parser.add_argument("-r", "--render", dest="render_path", metavar='FILE', help="Save the generated file to the specified path",
help="Render an image to the specified path") )
parser.add_argument(
"-r", "--render", dest="render_path", metavar='FILE',
help="Render an image to the specified path",
)
args = parser.parse_args(argv) # In this example we wont use the args args = parser.parse_args(argv) # In this example we wont use the args

View File

@@ -28,7 +28,7 @@ for obj in selection:
bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True) bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True)
## Can be used for multiple formats # Can be used for multiple formats
# bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True) # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
obj.select_set(action='DESELECT') obj.select_set(action='DESELECT')

View File

@@ -124,6 +124,8 @@ from nodeitems_utils import NodeCategory, NodeItem
# our own base class with an appropriate poll function, # our own base class with an appropriate poll function,
# so the categories only show up in our own tree type # so the categories only show up in our own tree type
class MyNodeCategory(NodeCategory): class MyNodeCategory(NodeCategory):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@@ -159,6 +161,7 @@ classes = (
MyCustomNode, MyCustomNode,
) )
def register(): def register():
from bpy.utils import register_class from bpy.utils import register_class
for cls in classes: for cls in classes:

View File

@@ -16,6 +16,7 @@ from bpy.props import (
FloatVectorProperty, FloatVectorProperty,
) )
def main(context, plane_co, plane_no): def main(context, plane_co, plane_no):
obj = context.active_object obj = context.active_object
matrix = obj.matrix_world.copy() matrix = obj.matrix_world.copy()
@@ -218,6 +219,7 @@ classes = (
SelectSideOfPlaneManipulatorGroup, SelectSideOfPlaneManipulatorGroup,
) )
def register(): def register():
for cls in classes: for cls in classes:
bpy.utils.register_class(cls) bpy.utils.register_class(cls)
@@ -227,5 +229,6 @@ def unregister():
for cls in reversed(classes): for cls in reversed(classes):
bpy.utils.unregister_class(cls) bpy.utils.unregister_class(cls)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -8,6 +8,7 @@ from bpy.types import (
ManipulatorGroup, ManipulatorGroup,
) )
class MyCameraWidgetGroup(ManipulatorGroup): class MyCameraWidgetGroup(ManipulatorGroup):
bl_idname = "OBJECT_WGT_test_camera" bl_idname = "OBJECT_WGT_test_camera"
bl_label = "Object Camera Test Widget" bl_label = "Object Camera Test Widget"
@@ -45,4 +46,5 @@ class MyCameraWidgetGroup(ManipulatorGroup):
mpr = self.roll_widget mpr = self.roll_widget
mpr.matrix_basis = ob.matrix_world.normalized() mpr.matrix_basis = ob.matrix_world.normalized()
bpy.utils.register_class(MyCameraWidgetGroup) bpy.utils.register_class(MyCameraWidgetGroup)

View File

@@ -9,6 +9,7 @@ from bpy.types import (
ManipulatorGroup, ManipulatorGroup,
) )
class MyLampWidgetGroup(ManipulatorGroup): class MyLampWidgetGroup(ManipulatorGroup):
bl_idname = "OBJECT_WGT_lamp_test" bl_idname = "OBJECT_WGT_lamp_test"
bl_label = "Test Lamp Widget" bl_label = "Test Lamp Widget"
@@ -42,4 +43,5 @@ class MyLampWidgetGroup(ManipulatorGroup):
mpr = self.energy_widget mpr = self.energy_widget
mpr.matrix_basis = ob.matrix_world.normalized() mpr.matrix_basis = ob.matrix_world.normalized()
bpy.utils.register_class(MyLampWidgetGroup) bpy.utils.register_class(MyLampWidgetGroup)

View File

@@ -26,26 +26,28 @@ class ExportSomeData(Operator, ExportHelper):
filename_ext = ".txt" filename_ext = ".txt"
filter_glob = StringProperty( filter_glob = StringProperty(
default="*.txt", default="*.txt",
options={'HIDDEN'}, options={'HIDDEN'},
maxlen=255, # Max internal buffer length, longer would be clamped. maxlen=255, # Max internal buffer length, longer would be clamped.
) )
# List of operator properties, the attributes will be assigned # List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling. # to the class instance from the operator settings before calling.
use_setting = BoolProperty( use_setting = BoolProperty(
name="Example Boolean", name="Example Boolean",
description="Example Tooltip", description="Example Tooltip",
default=True, default=True,
) )
type = EnumProperty( type = EnumProperty(
name="Example Enum", name="Example Enum",
description="Choose between two items", description="Choose between two items",
items=(('OPT_A', "First Option", "Description one"), items=(
('OPT_B', "Second Option", "Description two")), ('OPT_A', "First Option", "Description one"),
default='OPT_A', ('OPT_B', "Second Option", "Description two"),
) ),
default='OPT_A',
)
def execute(self, context): def execute(self, context):
return write_some_data(context, self.filepath, self.use_setting) return write_some_data(context, self.filepath, self.use_setting)

View File

@@ -29,26 +29,28 @@ class ImportSomeData(Operator, ImportHelper):
filename_ext = ".txt" filename_ext = ".txt"
filter_glob = StringProperty( filter_glob = StringProperty(
default="*.txt", default="*.txt",
options={'HIDDEN'}, options={'HIDDEN'},
maxlen=255, # Max internal buffer length, longer would be clamped. maxlen=255, # Max internal buffer length, longer would be clamped.
) )
# List of operator properties, the attributes will be assigned # List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling. # to the class instance from the operator settings before calling.
use_setting = BoolProperty( use_setting = BoolProperty(
name="Example Boolean", name="Example Boolean",
description="Example Tooltip", description="Example Tooltip",
default=True, default=True,
) )
type = EnumProperty( type = EnumProperty(
name="Example Enum", name="Example Enum",
description="Choose between two items", description="Choose between two items",
items=(('OPT_A', "First Option", "Description one"), items=(
('OPT_B', "Second Option", "Description two")), ('OPT_A', "First Option", "Description one"),
default='OPT_A', ('OPT_B', "Second Option", "Description two"),
) ),
default='OPT_A',
)
def execute(self, context): def execute(self, context):
return read_some_data(context, self.filepath, self.use_setting) return read_some_data(context, self.filepath, self.use_setting)

View File

@@ -8,23 +8,25 @@ def add_box(width, height, depth):
no actual mesh data creation is done here. no actual mesh data creation is done here.
""" """
verts = [(+1.0, +1.0, -1.0), verts = [
(+1.0, -1.0, -1.0), (+1.0, +1.0, -1.0),
(-1.0, -1.0, -1.0), (+1.0, -1.0, -1.0),
(-1.0, +1.0, -1.0), (-1.0, -1.0, -1.0),
(+1.0, +1.0, +1.0), (-1.0, +1.0, -1.0),
(+1.0, -1.0, +1.0), (+1.0, +1.0, +1.0),
(-1.0, -1.0, +1.0), (+1.0, -1.0, +1.0),
(-1.0, +1.0, +1.0), (-1.0, -1.0, +1.0),
] (-1.0, +1.0, +1.0),
]
faces = [(0, 1, 2, 3), faces = [
(4, 7, 6, 5), (0, 1, 2, 3),
(0, 4, 5, 1), (4, 7, 6, 5),
(1, 5, 6, 2), (0, 4, 5, 1),
(2, 6, 7, 3), (1, 5, 6, 2),
(4, 0, 3, 7), (2, 6, 7, 3),
] (4, 0, 3, 7),
]
# apply size # apply size
for i, v in enumerate(verts): for i, v in enumerate(verts):
@@ -48,50 +50,51 @@ class AddBox(bpy.types.Operator):
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
width = FloatProperty( width = FloatProperty(
name="Width", name="Width",
description="Box Width", description="Box Width",
min=0.01, max=100.0, min=0.01, max=100.0,
default=1.0, default=1.0,
) )
height = FloatProperty( height = FloatProperty(
name="Height", name="Height",
description="Box Height", description="Box Height",
min=0.01, max=100.0, min=0.01, max=100.0,
default=1.0, default=1.0,
) )
depth = FloatProperty( depth = FloatProperty(
name="Depth", name="Depth",
description="Box Depth", description="Box Depth",
min=0.01, max=100.0, min=0.01, max=100.0,
default=1.0, default=1.0,
) )
layers = BoolVectorProperty( layers = BoolVectorProperty(
name="Layers", name="Layers",
description="Object Layers", description="Object Layers",
size=20, size=20,
options={'HIDDEN', 'SKIP_SAVE'}, options={'HIDDEN', 'SKIP_SAVE'},
) )
# generic transform props # generic transform props
view_align = BoolProperty( view_align = BoolProperty(
name="Align to View", name="Align to View",
default=False, default=False,
) )
location = FloatVectorProperty( location = FloatVectorProperty(
name="Location", name="Location",
subtype='TRANSLATION', subtype='TRANSLATION',
) )
rotation = FloatVectorProperty( rotation = FloatVectorProperty(
name="Rotation", name="Rotation",
subtype='EULER', subtype='EULER',
) )
def execute(self, context): def execute(self, context):
verts_loc, faces = add_box(self.width, verts_loc, faces = add_box(
self.height, self.width,
self.depth, self.height,
) self.depth,
)
mesh = bpy.data.meshes.new("Box") mesh = bpy.data.meshes.new("Box")
@@ -127,6 +130,7 @@ def unregister():
bpy.utils.unregister_class(AddBox) bpy.utils.unregister_class(AddBox)
bpy.types.INFO_MT_mesh_add.remove(menu_func) bpy.types.INFO_MT_mesh_add.remove(menu_func)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -75,5 +75,6 @@ def register():
def unregister(): def unregister():
bpy.utils.unregister_class(ModalDrawOperator) bpy.utils.unregister_class(ModalDrawOperator)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -9,9 +9,9 @@ class ViewOperator(bpy.types.Operator):
bl_label = "Simple View Operator" bl_label = "Simple View Operator"
offset = FloatVectorProperty( offset = FloatVectorProperty(
name="Offset", name="Offset",
size=3, size=3,
) )
def execute(self, context): def execute(self, context):
v3d = context.space_data v3d = context.space_data

View File

@@ -42,6 +42,7 @@ def unregister():
bpy.types.INFO_HT_header.remove(draw_item) bpy.types.INFO_HT_header.remove(draw_item)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -19,6 +19,7 @@ def register():
def unregister(): def unregister():
bpy.utils.unregister_class(SimpleCustomMenu) bpy.utils.unregister_class(SimpleCustomMenu)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

View File

@@ -89,19 +89,19 @@ preview_collections = {}
def register(): def register():
from bpy.types import WindowManager from bpy.types import WindowManager
from bpy.props import ( from bpy.props import (
StringProperty, StringProperty,
EnumProperty, EnumProperty,
) )
WindowManager.my_previews_dir = StringProperty( WindowManager.my_previews_dir = StringProperty(
name="Folder Path", name="Folder Path",
subtype='DIR_PATH', subtype='DIR_PATH',
default="" default=""
) )
WindowManager.my_previews = EnumProperty( WindowManager.my_previews = EnumProperty(
items=enum_previews_from_directory_items, items=enum_previews_from_directory_items,
) )
# Note that preview collections returned by bpy.utils.previews # Note that preview collections returned by bpy.utils.previews
# are regular Python objects - you can use them to store custom data. # are regular Python objects - you can use them to store custom data.

View File

@@ -368,7 +368,8 @@ void MESH_OT_bisect(struct wmOperatorType *ot)
RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane"); RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry in front of the plane"); RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry in front of the plane");
RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1); RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold",
"Preserves the existing geometry along the cut plane", 0.00001, 0.1);
WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT); WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);

View File

@@ -4354,11 +4354,13 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */ /* properties */
prop = RNA_def_int(ot->srna, "span", 1, 1, 1000, "Span", "Number of sides (zero disables)", 1, 100); prop = RNA_def_int(ot->srna, "span", 1, 1, 1000, "Span", "Number of grid columns", 1, 100);
RNA_def_property_flag(prop, PROP_SKIP_SAVE); RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna, "offset", 0, -1000, 1000, "Offset", "Number of sides (zero disables)", -100, 100); prop = RNA_def_int(ot->srna, "offset", 0, -1000, 1000, "Offset",
"Vertex that is the corner of the grid", -100, 100);
RNA_def_property_flag(prop, PROP_SKIP_SAVE); RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_boolean(ot->srna, "use_interp_simple", false, "Simple Blending", ""); RNA_def_boolean(ot->srna, "use_interp_simple", false, "Simple Blending",
"Use simple interpolation of grid vertices");
} }
/** \} */ /** \} */
@@ -6610,7 +6612,8 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
ot->srna, "direction", rna_enum_symmetrize_direction_items, ot->srna, "direction", rna_enum_symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X, BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to"); "Direction", "Which sides to copy from and to");
RNA_def_float(ot->srna, "threshold", 1e-4f, 0.0f, 10.0f, "Threshold", "", 1e-5f, 0.1f); RNA_def_float(ot->srna, "threshold", 1e-4f, 0.0f, 10.0f, "Threshold",
"Limit for snap middle vertices to the axis center", 1e-5f, 0.1f);
} }
/** \} */ /** \} */
@@ -6741,9 +6744,11 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
ot->srna, "direction", rna_enum_symmetrize_direction_items, ot->srna, "direction", rna_enum_symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X, BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to"); "Direction", "Which sides to copy from and to");
RNA_def_float_distance(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold", "", 1e-4f, 1.0f); RNA_def_float_distance(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold",
RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f); "Distance within which matching vertices are searched", 1e-4f, 1.0f);
RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap mid verts to the axis center"); RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor",
"Mix factor of the locations of the vertices", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap middle vertices to the axis center");
} }
/** \} */ /** \} */

View File

@@ -358,9 +358,9 @@ void WM_operator_properties_checker_interval(wmOperatorType *ot, bool nth_can_di
{ {
const int nth_default = nth_can_disable ? 1 : 2; const int nth_default = nth_can_disable ? 1 : 2;
const int nth_min = min_ii(nth_default, 2); const int nth_min = min_ii(nth_default, 2);
RNA_def_int(ot->srna, "nth", nth_default, nth_min, INT_MAX, "Nth Selection", "", nth_min, 100); RNA_def_int(ot->srna, "nth", nth_default, nth_min, INT_MAX, "Nth Element", "Skip every Nth element", nth_min, 100);
RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100); RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "Number of elements to skip at once", 1, 100);
RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100); RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "Offset from the starting point", -100, 100);
} }
void WM_operator_properties_checker_interval_from_op( void WM_operator_properties_checker_interval_from_op(