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,
}
def init():
"""init function - runs once"""
import os

View File

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

View File

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

View File

@@ -81,6 +81,7 @@ for msg in translations_tuple:
# Define remaining addon (operators, UI...) here.
def register():
# Usual operator/UI/etc. registration...

View File

@@ -14,6 +14,7 @@ class MaterialSettings(bpy.types.PropertyGroup):
my_float = bpy.props.FloatProperty()
my_string = bpy.props.StringProperty()
bpy.utils.register_class(MaterialSettings)
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")
value = bpy.props.IntProperty(name="Test Prop", default=22)
bpy.utils.register_class(SceneSettingItem)
bpy.types.Scene.my_settings = \

View File

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

View File

@@ -19,6 +19,7 @@ def get_float(self):
def set_float(self, value):
self["testprop"] = value
bpy.types.Scene.test_float = bpy.props.FloatProperty(get=get_float, set=set_float)
@@ -27,6 +28,7 @@ def get_date(self):
import datetime
return str(datetime.datetime.now())
bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date)
@@ -40,6 +42,7 @@ def get_array(self):
def set_array(self, values):
self["somebool"] = values[0] and values[1]
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),
("BLUE", "Blue", "", 3),
("YELLOW", "Yellow", "", 4),
]
]
def get_enum(self):
@@ -61,6 +64,7 @@ def get_enum(self):
def set_enum(self, value):
print("setting value", value)
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": "",
"tracker_url": "",
"category": "Object",
}
}
import bpy

View File

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

View File

@@ -61,7 +61,7 @@ def panel_func(self, context):
classes = (
OBJECT_MT_draw_presets,
AddPresetObjectDraw,
)
)
def register():

View File

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

View File

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

View File

@@ -42,6 +42,7 @@ class SimpleMouseOperator(bpy.types.Operator):
self.y = event.mouse_y
return self.execute(context)
bpy.utils.register_class(SimpleMouseOperator)
# 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(ExportSomeData.bl_idname, text="Text Export Operator")
# Register and add to the file selector
bpy.utils.register_class(ExportSomeData)
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")
bpy.utils.register_class(CustomDrawOperator)
# test call

View File

@@ -22,6 +22,7 @@ class HelloWorldOperator(bpy.types.Operator):
print("Hello World")
return {'FINISHED'}
bpy.utils.register_class(HelloWorldOperator)
# 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_2 = bpy.props.IntProperty(name="My Int")
bpy.utils.register_class(MyPropertyGroup)
bpy.types.Object.my_prop_grp = bpy.props.PointerProperty(type=MyPropertyGroup)

View File

@@ -10,4 +10,5 @@ import bpy
def draw(self, context):
self.layout.label("Hello World")
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):
nested = bpy.props.FloatProperty(name="Nested", default=0.0)
# register it so its available for all bones
bpy.utils.register_class(MyPropGroup)
bpy.types.Bone.my_prop = PointerProperty(type=MyPropGroup,

View File

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

View File

@@ -251,7 +251,8 @@ class BakeAction(Operator):
name="Bake Data",
description="Which data's transformations to bake",
options={'ENUM_FLAG'},
items=(('POSE', "Pose", "Bake bones transformations"),
items=(
('POSE', "Pose", "Bake bones transformations"),
('OBJECT', "Object", "Bake object transformations"),
),
default={'POSE'},
@@ -316,8 +317,10 @@ class ClearUselessActions(Operator):
for action in bpy.data.actions:
# if only user is "fake" user...
if ((self.only_unused is False) or
(action.use_fake_user and action.users == 1)):
if (
(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"
# (i.e. walk, wave, jump, etc.)

View File

@@ -167,7 +167,8 @@ class CLIP_OT_filter_tracks(bpy.types.Operator):
relevant_tracks = [
track for track in clip.tracking.tracks
if (track.markers.find_frame(frame) and
track.markers.find_frame(frame - 1))]
track.markers.find_frame(frame - 1))
]
if not relevant_tracks:
continue

View File

@@ -175,7 +175,8 @@ class WM_OT_previews_batch_clear(Operator):
name="Scenes",
description="Clear scenes' previews",
)
use_collections = BoolProperty(default=True,
use_collections = BoolProperty(
default=True,
name="Collections",
description="Clear collections' previews",
)

View File

@@ -35,8 +35,10 @@ class MeshMirrorUV(Operator):
direction = EnumProperty(
name="Axis Direction",
items=(('POSITIVE', "Positive", ""),
('NEGATIVE', "Negative", "")),
items=(
('POSITIVE', "Positive", ""),
('NEGATIVE', "Negative", ""),
),
)
precision = IntProperty(

View File

@@ -368,7 +368,7 @@ class ShapeTransfer(Operator):
orig_normals = me_nos(me.vertices)
# 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)
for ob_other in objects:
@@ -697,22 +697,11 @@ class TransformsToDeltas(Operator):
bl_options = {'REGISTER', 'UNDO'}
mode = EnumProperty(
items=(('ALL',
"All Transforms",
"Transfer location, rotation, and scale transforms",
),
('LOC',
"Location",
"Transfer location transforms only",
),
('ROT',
"Rotation",
"Transfer rotation transforms only",
),
('SCALE',
"Scale",
"Transfer scale transforms only",
),
items=(
('ALL', "All Transforms", "Transfer location, rotation, and scale transforms"),
('LOC', "Location", "Transfer location transforms only"),
('ROT', "Rotation", "Transfer rotation transforms only"),
('SCALE', "Scale", "Transfer scale transforms only"),
),
name="Mode",
description="Which transforms to transfer",
@@ -788,11 +777,11 @@ class TransformsToDeltasAnim(Operator):
def execute(self, context):
# map from standard transform paths to "new" transform paths
STANDARD_TO_DELTA_PATHS = {
"location" : "delta_location",
"rotation_euler" : "delta_rotation_euler",
"rotation_quaternion" : "delta_rotation_quaternion",
#"rotation_axis_angle" : "delta_rotation_axis_angle",
"scale" : "delta_scale"
"location": "delta_location",
"rotation_euler": "delta_rotation_euler",
"rotation_quaternion": "delta_rotation_quaternion",
# "rotation_axis_angle" : "delta_rotation_axis_angle",
"scale": "delta_scale"
}
DELTA_PATHS = STANDARD_TO_DELTA_PATHS.values()
@@ -852,8 +841,8 @@ class TransformsToDeltasAnim(Operator):
fcu.data_path = "delta_rotation_quaternion"
obj.rotation_quaternion.identity()
# XXX: currently not implemented
#~ elif fcu.data_path == "rotation_axis_angle":
#~ fcu.data_path = "delta_rotation_axis_angle"
# ~ elif fcu.data_path == "rotation_axis_angle":
# ~ fcu.data_path = "delta_rotation_axis_angle"
elif fcu.data_path == "scale":
fcu.data_path = "delta_scale"
obj.scale = 1.0, 1.0, 1.0

View File

@@ -365,15 +365,18 @@ class AlignObjects(Operator):
bb_quality = BoolProperty(
name="High Quality",
description=("Enables high quality calculation of the "
description=(
"Enables high quality calculation of the "
"bounding box for perfect results on complex "
"shape meshes with rotation/scale (Slow)"),
"shape meshes with rotation/scale (Slow)"
),
default=True,
)
align_mode = EnumProperty(
name="Align Mode:",
description="Side of object to use for alignment",
items=(('OPT_1', "Negative Sides", ""),
items=(
('OPT_1', "Negative Sides", ""),
('OPT_2', "Centers", ""),
('OPT_3', "Positive Sides", ""),
),
@@ -382,7 +385,8 @@ class AlignObjects(Operator):
relative_to = EnumProperty(
name="Relative 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_1', "Scene Origin", "Use the Scene Origin 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_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"),
@@ -392,7 +396,8 @@ class AlignObjects(Operator):
align_axis = EnumProperty(
name="Align",
description="Align to axis",
items=(('X', "X", ""),
items=(
('X', "X", ""),
('Y', "Y", ""),
('Z', "Z", ""),
),

View File

@@ -54,9 +54,11 @@ class QuickFur(Operator):
density = EnumProperty(
name="Fur Density",
items=(('LIGHT', "Light", ""),
items=(
('LIGHT', "Light", ""),
('MEDIUM', "Medium", ""),
('HEAVY', "Heavy", "")),
('HEAVY', "Heavy", "")
),
default='MEDIUM',
)
view_percentage = IntProperty(
@@ -118,8 +120,10 @@ class QuickExplode(Operator):
style = EnumProperty(
name="Explode Style",
items=(('EXPLODE', "Explode", ""),
('BLEND', "Blend", "")),
items=(
('EXPLODE', "Explode", ""),
('BLEND', "Blend", ""),
),
default='EXPLODE',
)
amount = IntProperty(
@@ -304,7 +308,8 @@ class QuickSmoke(Operator):
style = EnumProperty(
name="Smoke Style",
items=(('SMOKE', "Smoke", ""),
items=(
('SMOKE', "Smoke", ""),
('FIRE', "Fire", ""),
('BOTH', "Smoke + Fire", ""),
),
@@ -407,8 +412,10 @@ class QuickFluid(Operator):
style = EnumProperty(
name="Fluid Style",
items=(('INFLOW', "Inflow", ""),
('BASIC', "Basic", "")),
items=(
('INFLOW', "Inflow", ""),
('BASIC', "Basic", ""),
),
default='BASIC',
)
initial_velocity = FloatVectorProperty(

View File

@@ -29,6 +29,7 @@ WindowManager.preset_name = StringProperty(
default="New Preset"
)
class AddPresetBase:
"""Base preset class, only for subclassing
subclasses must define
@@ -268,22 +269,26 @@ class PresetMenu(Panel):
@classmethod
def draw_panel_header(cls, layout):
layout.emboss = 'NONE'
layout.popover(cls.bl_space_type,
layout.popover(
cls.bl_space_type,
cls.bl_region_type,
cls.__name__,
icon='PRESET',
text='')
text="",
)
@classmethod
def draw_menu(cls, layout, text=None):
if text == None:
if text is None:
text = cls.bl_label
layout.popover(cls.bl_space_type,
layout.popover(
cls.bl_space_type,
cls.bl_region_type,
cls.__name__,
icon='PRESET',
text=text)
text=text,
)
def draw(self, context):
layout = self.layout

View File

@@ -220,23 +220,29 @@ class ConnectRigidBodies(Operator):
name="Type",
description="Type of generated constraint",
# XXX Would be nice to get icons too, but currently not possible ;)
items=tuple((e.identifier, e.name, e.description, e. value)
for e in bpy.types.RigidBodyConstraint.bl_rna.properties["type"].enum_items),
items=tuple(
(e.identifier, e.name, e.description, e. value)
for e in bpy.types.RigidBodyConstraint.bl_rna.properties["type"].enum_items
),
default='FIXED',
)
pivot_type = EnumProperty(
name="Location",
description="Constraint pivot location",
items=(('CENTER', "Center", "Pivot location is between the constrained rigid bodies"),
items=(
('CENTER', "Center", "Pivot location is between the constrained rigid bodies"),
('ACTIVE', "Active", "Pivot location is at the active object position"),
('SELECTED', "Selected", "Pivot location is at the selected object position")),
('SELECTED', "Selected", "Pivot location is at the selected object position"),
),
default='CENTER',
)
connection_pattern = EnumProperty(
name="Connection Pattern",
description="Pattern used to connect objects",
items=(('SELECTED_TO_ACTIVE', "Selected to Active", "Connect selected objects to the active object"),
('CHAIN_DISTANCE', "Chain by Distance", "Connect objects as a chain based on distance, starting at the active object")),
items=(
('SELECTED_TO_ACTIVE', "Selected to Active", "Connect selected objects to the active object"),
('CHAIN_DISTANCE', "Chain by Distance", "Connect objects as a chain based on distance, starting at the active object"),
),
default='SELECTED_TO_ACTIVE',
)

View File

@@ -115,7 +115,7 @@ class PlayRenderedAnim(Operator):
self.report({'WARNING'}, "File %r not found" % file)
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:
file = rd.frame_path(frame=scene.frame_start, preview=False)
file = bpy.path.abspath(file) # expand '//'

View File

@@ -18,7 +18,7 @@
# <pep8 compliant>
#for full docs see...
# for full docs see...
# http://mediawiki.blender.org/index.php/Scripts/Manual/UV_Calculate/Follow_active_quads
import bpy

View File

@@ -63,7 +63,7 @@ class prettyface:
self.width = self.height = d * 2
#else:
# else:
# print(len(data), data)
# raise "Error"
@@ -460,7 +460,7 @@ def lightmap_uvpack(meshes,
# Tall boxes in groups of 2
for d, boxes in list(odd_dict.items()):
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:
# print("foo", len(boxes))
ok = True
@@ -597,6 +597,7 @@ def unwrap(operator, context, **kwargs):
return {'FINISHED'}
from bpy.props import BoolProperty, FloatProperty, IntProperty
@@ -617,7 +618,8 @@ class LightMapPack(Operator):
PREF_CONTEXT = bpy.props.EnumProperty(
name="Selection",
items=(('SEL_FACES', "Selected Faces", "Space all UVs evenly"),
items=(
('SEL_FACES', "Selected Faces", "Space all UVs evenly"),
('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")
),
@@ -626,8 +628,10 @@ class LightMapPack(Operator):
# Image & UVs...
PREF_PACK_IN_ONE = BoolProperty(
name="Share Tex Space",
description=("Objects Share texture space, map all objects "
"into 1 uvmap"),
description=(
"Objects Share texture space, map all objects "
"into 1 uvmap"
),
default=True,
)
PREF_NEW_UVLAYER = BoolProperty(
@@ -637,8 +641,10 @@ class LightMapPack(Operator):
)
PREF_APPLY_IMAGE = BoolProperty(
name="New Image",
description=("Assign new images for every mesh (only one if "
"shared tex space enabled)"),
description=(
"Assign new images for every mesh (only one if "
"shared tex space enabled)"
),
default=False,
)
PREF_IMG_PX_SIZE = IntProperty(

View File

@@ -38,6 +38,7 @@ global USER_FILL_HOLES_QUALITY
USER_FILL_HOLES = None
USER_FILL_HOLES_QUALITY = None
def pointInTri2D(v, v1, v2, v3):
key = v1.x, v1.y, v2.x, v2.y, v3.x, v3.y
@@ -98,15 +99,20 @@ def boundsIsland(faces):
# print len(faces), minx, maxx, miny , maxy
for f in faces:
for uv in f.uv:
x= uv.x
y= uv.y
if x<minx: minx= x
if y<miny: miny= y
if x>maxx: maxx= x
if y>maxy: maxy= y
x = uv.x
y = uv.y
if x < minx:
minx = x
if y < miny:
miny = y
if x > maxx:
maxx = x
if y > maxy:
maxy = y
return minx, miny, maxx, maxy
"""
def boundsEdgeLoop(edges):
minx = maxx = edges[0][0] # Set initial bounds.
@@ -128,45 +134,51 @@ def boundsEdgeLoop(edges):
# Only for UV's
# only returns outline edges for intersection tests. and unique points.
def island2Edge(island):
# Vert index edges
edges = {}
unique_points= {}
unique_points = {}
for f in island:
f_uvkey= map(tuple, f.uv)
f_uvkey = map(tuple, f.uv)
for vIdx, edkey in enumerate(f.edge_keys):
unique_points[f_uvkey[vIdx]] = f.uv[vIdx]
if f.v[vIdx].index > f.v[vIdx-1].index:
i1= vIdx-1; i2= vIdx
if f.v[vIdx].index > f.v[vIdx - 1].index:
i1 = vIdx - 1
i2 = vIdx
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.
except: edges[ f_uvkey[i1], f_uvkey[i2] ] = (f.uv[i1] - f.uv[i2]).length,
try:
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.
# Sort by length
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
except: length_sorted_edges.sort(lambda A, B: cmp(B[2], A[2]))
try:
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.
#for e in length_sorted_edges:
# for e in length_sorted_edges:
# e.pop(2)
# return edges and unique points
return length_sorted_edges, [v.to_3d() for v in unique_points.values()]
# ========================= NOT WORKING????
# Find if a points inside an edge loop, unordered.
# pt is and x/y
@@ -190,6 +202,7 @@ def pointInEdges(pt, edges):
return intersectCount % 2
"""
def pointInIsland(pt, island):
vec1, vec2, vec3 = Vector(), Vector(), Vector()
for f in island:
@@ -220,8 +233,8 @@ def islandIntersectUvIsland(source, target, SourceOffset):
for seg in edgeLoopsTarget:
i = geometry.intersect_line_line_2d(seg[0],
seg[1],
SourceOffset+ed[0],
SourceOffset+ed[1],
SourceOffset + ed[0],
SourceOffset + ed[1],
)
if i:
return 1 # LINE INTERSECTION
@@ -229,12 +242,12 @@ def islandIntersectUvIsland(source, target, SourceOffset):
# 1 test for source being totally inside target
SourceOffset.resize_3d()
for pv in source[7]:
if pointInIsland(pv+SourceOffset, target[0]):
if pointInIsland(pv + SourceOffset, target[0]):
return 2 # SOURCE INSIDE TARGET
# 2 test for a part of the target being totally inside the source.
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 0 # NO INTERSECTION
@@ -270,50 +283,47 @@ def mergeUvIslands(islandList):
global USER_FILL_HOLES
global USER_FILL_HOLES_QUALITY
# Pack islands to bottom LHS
# Sync with island
#islandTotFaceArea = [] # A list of floats, each island area
#islandArea = [] # a list of tuples ( area, w,h)
# islandTotFaceArea = [] # A list of floats, each island area
# islandArea = [] # a list of tuples ( area, w,h)
decoratedIslandList = []
islandIdx = len(islandList)
while islandIdx:
islandIdx-=1
islandIdx -= 1
minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx])
w, h = maxx-minx, maxy-miny
w, h = maxx - minx, maxy - miny
totFaceArea = 0
offset= Vector((minx, miny))
offset = Vector((minx, miny))
for f in islandList[islandIdx]:
for uv in f.uv:
uv -= offset
totFaceArea += f.area
islandBoundsArea = w*h
islandBoundsArea = w * h
efficiency = abs(islandBoundsArea - totFaceArea)
# UV Edge list used for intersections as well as unique points.
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.
# 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.
decoratedIslandListEfficSort = decoratedIslandList[:]
# 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.
# This is a quality value for the number of tests.
@@ -324,27 +334,27 @@ def mergeUvIslands(islandList):
# this is rarely enough, and testing takes a while, so lower quality speeds this up.
# 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_FREE_SPACE_TO_TEST_QUALITY', USER_FREE_SPACE_TO_TEST_QUALITY
# print 'USER_STEP_QUALITY', USER_STEP_QUALITY
# print 'USER_FREE_SPACE_TO_TEST_QUALITY', USER_FREE_SPACE_TO_TEST_QUALITY
removedCount = 0
areaIslandIdx = 0
ctrl = Window.Qual.CTRL
BREAK= False
BREAK = False
while areaIslandIdx < len(decoratedIslandListAreaSort) and not BREAK:
sourceIsland = decoratedIslandListAreaSort[areaIslandIdx]
# Already packed?
if not sourceIsland[0]:
areaIslandIdx+=1
areaIslandIdx += 1
else:
efficIslandIdx = 0
while efficIslandIdx < len(decoratedIslandListEfficSort) and not BREAK:
if Window.GetKeyQualifiers() & ctrl:
BREAK= True
BREAK = True
break
# Now we have 2 islands, if the efficiency of the islands lowers theres an
@@ -355,7 +365,6 @@ def mergeUvIslands(islandList):
targetIsland = decoratedIslandListEfficSort[efficIslandIdx]
if sourceIsland[0] == targetIsland[0] or\
not targetIsland[0] or\
not sourceIsland[0]:
@@ -365,9 +374,8 @@ def mergeUvIslands(islandList):
#~ ([island, totFaceArea, efficiency, islandArea, w,h])
# Wasted space on target is greater then UV bounding island area.
#~ 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\
targetIsland[4] > sourceIsland[4] and\
targetIsland[5] > sourceIsland[5]:
@@ -377,42 +385,40 @@ def mergeUvIslands(islandList):
# These enough spare space lets move the box until it fits
# How many times does the source fit into the target x/y
blockTestXUnit = targetIsland[4]/sourceIsland[4]
blockTestYUnit = targetIsland[5]/sourceIsland[5]
blockTestXUnit = targetIsland[4] / sourceIsland[4]
blockTestYUnit = targetIsland[5] / sourceIsland[5]
boxLeft = 0
# Distance we can move between whilst staying inside the targets bounds.
testWidth = targetIsland[4] - sourceIsland[4]
testHeight = targetIsland[5] - sourceIsland[5]
# Increment we move each test. x/y
xIncrement = (testWidth / (blockTestXUnit * ((USER_STEP_QUALITY/50)+0.1)))
yIncrement = (testHeight / (blockTestYUnit * ((USER_STEP_QUALITY/50)+0.1)))
xIncrement = (testWidth / (blockTestXUnit * ((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
if xIncrement<sourceIsland[4]/3:
xIncrement= sourceIsland[4]
if yIncrement<sourceIsland[5]/3:
yIncrement= sourceIsland[5]
if xIncrement < sourceIsland[4] / 3:
xIncrement = sourceIsland[4]
if yIncrement < sourceIsland[5] / 3:
yIncrement = sourceIsland[5]
boxLeft = 0 # Start 1 back so we can jump into the loop.
boxBottom= 0 #-yIncrement
boxBottom = 0 # -yIncrement
#~ testcount= 0
# ~ testcount= 0
while boxBottom <= testHeight:
# Should we use this? - not needed for now.
#~ if Window.GetKeyQualifiers() & ctrl:
#~ BREAK= True
#~ break
# ~ if Window.GetKeyQualifiers() & ctrl:
# ~ BREAK= True
# ~ break
##testcount+=1
#print 'Testing intersect'
# testcount+=1
# print 'Testing intersect'
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
pass
@@ -431,71 +437,71 @@ def mergeUvIslands(islandList):
boxLeft += sourceIsland[4]
elif Intersect == 0: # No intersection?? Place it.
# Progress
removedCount +=1
#XXX Window.DrawProgressBar(0.0, 'Merged: %i islands, Ctrl to finish early.' % removedCount)
removedCount += 1
# XXX Window.DrawProgressBar(0.0, 'Merged: %i islands, Ctrl to finish early.' % removedCount)
# Move faces into new island and offset
targetIsland[0].extend(sourceIsland[0])
offset= Vector((boxLeft, boxBottom))
offset = Vector((boxLeft, boxBottom))
for f in sourceIsland[0]:
for uv in f.uv:
uv+= offset
uv += offset
del sourceIsland[0][:] # Empty
# Move edge loop into new and offset.
# targetIsland[6].extend(sourceIsland[6])
#while sourceIsland[6]:
targetIsland[6].extend( [ (\
(e[0]+offset, e[1]+offset, e[2])\
) for e in sourceIsland[6] ] )
# while sourceIsland[6]:
targetIsland[6].extend([(
(e[0] + offset, e[1] + offset, e[2])
) for e in sourceIsland[6]])
del sourceIsland[6][:] # Empty
# Sort by edge length, reverse so biggest are first.
try: targetIsland[6].sort(key = lambda A: A[2])
except: targetIsland[6].sort(lambda B,A: cmp(A[2], B[2] ))
try:
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])
offset= Vector((boxLeft, boxBottom, 0.0))
offset = Vector((boxLeft, boxBottom, 0.0))
for p in sourceIsland[7]:
p+= offset
p += offset
del sourceIsland[7][:]
# Decrement the efficiency
targetIsland[1]+=sourceIsland[1] # Increment totFaceArea
targetIsland[2]-=sourceIsland[1] # Decrement efficiency
targetIsland[1] += sourceIsland[1] # Increment totFaceArea
targetIsland[2] -= sourceIsland[1] # Decrement efficiency
# IF we ever used these again, should set to 0, eg
sourceIsland[2] = 0 # No area if anyone wants to know
break
# INCREMENT NEXT LOCATION
if boxLeft > testWidth:
boxBottom += yIncrement
boxLeft = 0.0
else:
boxLeft += xIncrement
##print testcount
# print testcount
efficIslandIdx+=1
areaIslandIdx+=1
efficIslandIdx += 1
areaIslandIdx += 1
# Remove empty islands
i = len(islandList)
while i:
i-=1
i -= 1
if not islandList[i]:
del islandList[i] # Can increment islands removed here.
# Takes groups of faces. assumes face groups are UV groups.
def getUvIslands(faceGroups, me):
# Get seams so we don't cross over seams
@@ -505,17 +511,16 @@ def getUvIslands(faceGroups, me):
edge_seams[ed.key] = None # dummy var- use sets!
# Done finding seams
islandList = []
#XXX Window.DrawProgressBar(0.0, 'Splitting %d projection groups into UV islands:' % len(faceGroups))
#print '\tSplitting %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),
# Find grouped faces
faceGroupIdx = len(faceGroups)
while faceGroupIdx:
faceGroupIdx-=1
faceGroupIdx -= 1
faces = faceGroups[faceGroupIdx]
if not faces:
@@ -529,8 +534,10 @@ def getUvIslands(faceGroups, me):
if ed_key in edge_seams: # DELIMIT SEAMS! ;)
edge_users[ed_key] = [] # so as not to raise an error
else:
try: edge_users[ed_key].append(i)
except: edge_users[ed_key] = [i]
try:
edge_users[ed_key].append(i)
except:
edge_users[ed_key] = [i]
# Modes
# 0 - face not yet touched.
@@ -544,13 +551,12 @@ def getUvIslands(faceGroups, me):
newIsland.append(faces[0])
ok = True
while ok:
ok = True
while ok:
ok= False
ok = False
for i in range(len(faces)):
if face_modes[i] == 1: # search
for ed_key in faces[i].edge_keys:
@@ -574,7 +580,7 @@ def getUvIslands(faceGroups, me):
break
# 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:
optiRotateUvIsland(island)
@@ -584,10 +590,9 @@ def getUvIslands(faceGroups, me):
def packIslands(islandList):
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
# Now we have UV islands, we need to pack them.
# Make a synchronized list with the islands
@@ -603,16 +608,16 @@ def packIslands(islandList):
while islandIdx < len(islandList):
minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx])
w, h = maxx-minx, maxy-miny
w, h = maxx - minx, maxy - miny
if USER_ISLAND_MARGIN:
minx -= USER_ISLAND_MARGIN# *w
miny -= USER_ISLAND_MARGIN# *h
maxx += USER_ISLAND_MARGIN# *w
maxy += USER_ISLAND_MARGIN# *h
minx -= USER_ISLAND_MARGIN # *w
miny -= USER_ISLAND_MARGIN # *h
maxx += USER_ISLAND_MARGIN # *w
maxy += USER_ISLAND_MARGIN # *h
# recalc width and height
w, h = maxx-minx, maxy-miny
w, h = maxx - minx, maxy - miny
if w < SMALL_NUM:
w = SMALL_NUM
@@ -628,24 +633,24 @@ def packIslands(islandList):
# Add to boxList. use the island idx for the BOX id.
packBoxes.append([0, 0, w, h])
islandIdx+=1
islandIdx += 1
# Now we have a list of boxes to pack that syncs
# with the islands.
#print '\tPacking UV Islands...'
#XXX Window.DrawProgressBar(0.7, "Packing %i UV Islands..." % len(packBoxes) )
# print '\tPacking UV Islands...'
# XXX Window.DrawProgressBar(0.7, "Packing %i UV Islands..." % len(packBoxes) )
# time1 = time.time()
packWidth, packHeight = geometry.box_pack_2d(packBoxes)
# 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")
#print '\tWriting Packed Data to faces'
#XXX Window.DrawProgressBar(0.8, "Writing Packed Data to faces")
# print '\tWriting Packed Data to faces'
# XXX Window.DrawProgressBar(0.8, "Writing Packed Data to faces")
# Sort by ID, so there in sync again
islandIdx = len(islandList)
@@ -661,7 +666,7 @@ def packIslands(islandList):
xfactor = yfactor = 1.0 / max(packWidth, packHeight)
while islandIdx:
islandIdx -=1
islandIdx -= 1
# Write the packed values to the UV's
xoffset = packBoxes[islandIdx][0] - islandOffsetList[islandIdx][0]
@@ -669,8 +674,8 @@ def packIslands(islandList):
for f in islandList[islandIdx]: # Offsetting the UV's so they fit in there packed box
for uv in f.uv:
uv.x= (uv.x+xoffset) * xfactor
uv.y= (uv.y+yoffset) * yfactor
uv.x = (uv.x + xoffset) * xfactor
uv.y = (uv.y + yoffset) * yfactor
def VectoQuat(vec):
@@ -679,7 +684,8 @@ def VectoQuat(vec):
class thickface:
__slost__= "v", "uv", "no", "area", "edge_keys"
__slost__ = "v", "uv", "no", "area", "edge_keys"
def __init__(self, face, uv_layer, mesh_verts):
self.v = [mesh_verts[i] for i in face.vertices]
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)
RotMatStepRotation = []
rot_angle = 22.5 #45.0/2
rot_angle = 22.5 # 45.0/2
while rot_angle > 0.1:
RotMatStepRotation.append([
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
ob = None
def main(context,
island_margin,
projection_limit,
@@ -770,15 +778,14 @@ def main(context,
time.sleep(10)
'''
#~ XXX if not Draw.PupBlock(ob % len(obList), pup_block):
#~ XXX return
#~ XXX del ob
# ~ XXX if not Draw.PupBlock(ob % len(obList), pup_block):
# ~ XXX return
# ~ XXX del ob
# Convert from being button types
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
is_editmode = (context.active_object.mode == 'EDIT')
@@ -788,19 +795,18 @@ def main(context,
if USER_SHARE_SPACE:
# Sort by data name so we get consistent results
obList.sort(key = lambda ob: ob.data.name)
collected_islandList= []
obList.sort(key=lambda ob: ob.data.name)
collected_islandList = []
#XXX Window.WaitCursor(1)
# XXX Window.WaitCursor(1)
time1 = time.time()
# 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:
me.tag = False
for ob in obList:
me = ob.data
@@ -821,7 +827,7 @@ def main(context,
else:
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 :)
@@ -849,7 +855,6 @@ def main(context,
# 0d is 1.0
# 180 IS -0.59846
# Initialize projectVecs
if USER_VIEW_INIT:
# Generate Projection
@@ -860,21 +865,18 @@ def main(context,
newProjectVec = meshFaces[0].no
newProjectMeshFaces = [] # Popping stuffs it up.
# Pretend that the most unique angle is ages away to start the loop off
mostUniqueAngle = -1.0
# This is popped
tempMeshFaces = meshFaces[:]
# This while only gathers projection vecs, faces are assigned later on.
while 1:
# If theres none there then start with the largest face
# 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
# normal and hog all the faces.
if newProjectVec.dot(tempMeshFaces[fIdx].no) > USER_PROJECTION_LIMIT_HALF_CONVERTED:
@@ -895,21 +897,20 @@ def main(context,
if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN
projectVecs.append(averageVec.normalized())
# Get the next vec!
# Pick the face thats most different to all existing angles :)
mostUniqueAngle = 1.0 # 1.0 is 0d. no difference.
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.
# Get the closest vec angle we are to.
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:
angleDifference= temp_angle_diff
angleDifference = temp_angle_diff
if angleDifference < mostUniqueAngle:
# We have a new most different angle
@@ -917,30 +918,28 @@ def main(context,
mostUniqueAngle = angleDifference
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
# if the face its self was not representative of the normal from surrounding faces.
newProjectVec = tempMeshFaces[mostUniqueIndex].no
newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)]
else:
if len(projectVecs) >= 1: # Must have at least 2 projections
break
# If there are only zero area faces then its possible
# there are no projectionVecs
if not len(projectVecs):
Draw.PupMenu('error, no projection vecs where generated, 0 area faces can cause this.')
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
for fIdx in range(len(meshFaces)-1, -1, -1):
for fIdx in range(len(meshFaces) - 1, -1, -1):
fvec = meshFaces[fIdx].no
i = len(projectVecs)
@@ -949,8 +948,8 @@ def main(context,
bestAngIdx = 0
# Cycle through the remaining, first already done
while i-1:
i-=1
while i - 1:
i -= 1
newAng = fvec.dot(projectVecs[i])
if newAng > bestAng: # Reverse logic for dotvecs
@@ -962,7 +961,6 @@ def main(context,
# Cull faceProjectionGroupList,
# Now faceProjectionGroupList is full of faces that face match the project Vecs list
for i in range(len(projectVecs)):
# 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.
f_uv[j][:] = (MatQuat * v.co).xy
if USER_SHARE_SPACE:
# Should we collect and pack later?
islandList = getUvIslands(faceProjectionGroupList, me)
@@ -990,12 +987,11 @@ def main(context,
islandList = getUvIslands(faceProjectionGroupList, me)
packIslands(islandList)
# update the mesh here if we need to.
# We want to pack all in 1 go, so pack now
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)
print("Smart Projection time: %.2f" % (time.time() - time1))
@@ -1009,10 +1005,10 @@ def main(context,
import bmesh
aspect = context.scene.uvedit_aspect(context.active_object)
if aspect[0] > aspect[1]:
aspect[0] = aspect[1]/aspect[0];
aspect[0] = aspect[1] / aspect[0]
aspect[1] = 1.0
else:
aspect[1] = aspect[0]/aspect[1];
aspect[1] = aspect[0] / aspect[1]
aspect[0] = 1.0
bm = bmesh.from_edit_mesh(me)
@@ -1028,9 +1024,10 @@ def main(context,
dict_matrix.clear()
#XXX Window.DrawProgressBar(1.0, "")
#XXX Window.WaitCursor(0)
#XXX Window.RedrawAll()
# XXX Window.DrawProgressBar(1.0, "")
# XXX Window.WaitCursor(0)
# XXX Window.RedrawAll()
"""
pup_block = [\

View File

@@ -39,13 +39,16 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
totface = mesh.total_face_sel
totedge = mesh.total_edge_sel
#~ totvert = mesh.total_vert_sel
# totvert = mesh.total_vert_sel
if select_mode[2] and totface == 1:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN',
bpy.ops.mesh.extrude_region_move(
'INVOKE_REGION_WIN',
TRANSFORM_OT_translate={
"constraint_orientation": 'NORMAL',
"constraint_axis": (False, False, True)})
"constraint_axis": (False, False, True),
}
)
elif select_mode[2] and totface > 1:
bpy.ops.mesh.extrude_faces_move('INVOKE_REGION_WIN')
elif select_mode[1] and totedge >= 1:
@@ -77,25 +80,32 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
totface = mesh.total_face_sel
totedge = mesh.total_edge_sel
#~ totvert = mesh.total_vert_sel
# totvert = mesh.total_vert_sel
if totface >= 1:
if use_vert_normals:
bpy.ops.mesh.extrude_region_shrink_fatten('INVOKE_REGION_WIN',
TRANSFORM_OT_shrink_fatten={})
bpy.ops.mesh.extrude_region_shrink_fatten(
'INVOKE_REGION_WIN',
TRANSFORM_OT_shrink_fatten={},
)
else:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN',
bpy.ops.mesh.extrude_region_move(
'INVOKE_REGION_WIN',
TRANSFORM_OT_translate={
"constraint_orientation": 'NORMAL',
"constraint_axis": (False, False, True)})
"constraint_axis": (False, False, True),
},
)
elif totedge == 1:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN',
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)})
# "constraint_axis": (True, True, False)})
"constraint_axis": (False, False, False),
})
else:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN')

View File

@@ -39,25 +39,25 @@ rna_path_prop = StringProperty(
name="Context Attributes",
description="RNA context string",
maxlen=1024,
)
)
rna_reverse_prop = BoolProperty(
name="Reverse",
description="Cycle backwards",
default=False,
)
)
rna_wrap_prop = BoolProperty(
name="Wrap",
description="Wrap back to the first/last values",
default=False,
)
)
rna_relative_prop = BoolProperty(
name="Relative",
description="Apply relative to the current value (delta)",
default=False,
)
)
rna_space_type_prop = EnumProperty(
name="Type",
@@ -66,7 +66,7 @@ rna_space_type_prop = EnumProperty(
for e in bpy.types.Space.bl_rna.properties["type"].enum_items
),
default='EMPTY',
)
)
def context_path_validate(context, data_path):
@@ -682,7 +682,7 @@ doc_id = StringProperty(
name="Doc ID",
maxlen=1024,
options={'HIDDEN'},
)
)
data_path_iter = StringProperty(
description="The data path relative to the context, must point to an iterable")
@@ -1072,40 +1072,40 @@ rna_path = StringProperty(
description="Property data_path edit",
maxlen=1024,
options={'HIDDEN'},
)
)
rna_value = StringProperty(
name="Property Value",
description="Property value edit",
maxlen=1024,
)
)
rna_property = StringProperty(
name="Property Name",
description="Property name edit",
maxlen=1024,
)
)
rna_min = FloatProperty(
name="Min",
default=-10000.0,
precision=3,
)
)
rna_max = FloatProperty(
name="Max",
default=10000.0,
precision=3,
)
)
rna_use_soft_limits = BoolProperty(
name="Use Soft Limits",
)
)
rna_is_overridable_static = BoolProperty(
name="Is Statically Overridable",
default=False,
)
)
class WM_OT_properties_edit(Operator):

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
# Used for DopeSheet, NLA, and Graph Editors
class DopesheetFilterPopoverBase:
bl_region_type = 'HEADER'
bl_label = "Filters"
@@ -211,11 +213,13 @@ class DOPESHEET_HT_header(Header):
TIME_HT_editor_buttons.draw_header(context, layout)
else:
layout.prop(st, "ui_mode", text="")
layout.popover(space_type='DOPESHEET_EDITOR',
layout.popover(
space_type='DOPESHEET_EDITOR',
region_type='HEADER',
panel_type="DOPESHEET_PT_filters",
text="",
icon='FILTER')
icon='FILTER',
)
DOPESHEET_MT_editor_menus.draw_collapsible(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 (
DopesheetFilterPopoverBase,
dopesheet_filter,
)
)
class GRAPH_HT_header(Header):
@@ -41,11 +41,13 @@ class GRAPH_HT_header(Header):
# Now a exposed as a sub-space type
# layout.prop(st, "mode", text="")
layout.popover(space_type='GRAPH_EDITOR',
layout.popover(
space_type='GRAPH_EDITOR',
region_type='HEADER',
panel_type="GRAPH_PT_filters",
text="",
icon='FILTER')
icon='FILTER',
)
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 (
DopesheetFilterPopoverBase,
dopesheet_filter,
)
)
class NLA_HT_header(Header):
@@ -37,11 +37,13 @@ class NLA_HT_header(Header):
row = layout.row(align=True)
row.template_header()
layout.popover(space_type='NLA_EDITOR',
layout.popover(
space_type='NLA_EDITOR',
region_type='HEADER',
panel_type="NLA_PT_filters",
text="",
icon='FILTER')
icon='FILTER',
)
NLA_MT_editor_menus.draw_collapsible(context, layout)

View File

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

View File

@@ -8,7 +8,7 @@ bl_info = {
"warning": "",
"wiki_url": "",
"category": "Add Mesh",
}
}
import bpy
@@ -22,7 +22,8 @@ def add_object(self, context):
scale_x = self.scale.x
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)),

View File

@@ -81,13 +81,19 @@ def main():
# Example utility, add some text and renders or saves it (with options)
# Possible types are: string, int, long, choice, float and complex.
parser.add_argument("-t", "--text", dest="text", type=str, required=True,
help="This text will be used to render an image")
parser.add_argument(
"-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',
help="Save the generated file to the specified path")
parser.add_argument("-r", "--render", dest="render_path", metavar='FILE',
help="Render an image to the specified path")
parser.add_argument(
"-s", "--save", dest="save_path", metavar='FILE',
help="Save the generated file 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

View File

@@ -28,7 +28,7 @@ for obj in selection:
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)
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,
# so the categories only show up in our own tree type
class MyNodeCategory(NodeCategory):
@classmethod
def poll(cls, context):
@@ -159,6 +161,7 @@ classes = (
MyCustomNode,
)
def register():
from bpy.utils import register_class
for cls in classes:

View File

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

View File

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

View File

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

View File

@@ -42,8 +42,10 @@ class ExportSomeData(Operator, ExportHelper):
type = EnumProperty(
name="Example Enum",
description="Choose between two items",
items=(('OPT_A', "First Option", "Description one"),
('OPT_B', "Second Option", "Description two")),
items=(
('OPT_A', "First Option", "Description one"),
('OPT_B', "Second Option", "Description two"),
),
default='OPT_A',
)

View File

@@ -45,8 +45,10 @@ class ImportSomeData(Operator, ImportHelper):
type = EnumProperty(
name="Example Enum",
description="Choose between two items",
items=(('OPT_A', "First Option", "Description one"),
('OPT_B', "Second Option", "Description two")),
items=(
('OPT_A', "First Option", "Description one"),
('OPT_B', "Second Option", "Description two"),
),
default='OPT_A',
)

View File

@@ -8,7 +8,8 @@ def add_box(width, height, depth):
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),
@@ -18,7 +19,8 @@ def add_box(width, height, depth):
(-1.0, +1.0, +1.0),
]
faces = [(0, 1, 2, 3),
faces = [
(0, 1, 2, 3),
(4, 7, 6, 5),
(0, 4, 5, 1),
(1, 5, 6, 2),
@@ -88,7 +90,8 @@ class AddBox(bpy.types.Operator):
def execute(self, context):
verts_loc, faces = add_box(self.width,
verts_loc, faces = add_box(
self.width,
self.height,
self.depth,
)
@@ -127,6 +130,7 @@ def unregister():
bpy.utils.unregister_class(AddBox)
bpy.types.INFO_MT_mesh_add.remove(menu_func)
if __name__ == "__main__":
register()

View File

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

View File

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

View File

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

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_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);

View File

@@ -4354,11 +4354,13 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* 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);
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_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,
BMO_SYMMETRIZE_NEGATIVE_X,
"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,
BMO_SYMMETRIZE_NEGATIVE_X,
"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(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap mid verts to the axis center");
RNA_def_float_distance(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold",
"Distance within which matching vertices are searched", 1e-4f, 1.0f);
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_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, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100);
RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 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", "Number of elements to skip at once", 1, 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(