Merge branch 'master' into blender2.8
This commit is contained in:
@@ -15,6 +15,7 @@ font_info = {
|
||||
"handler": None,
|
||||
}
|
||||
|
||||
|
||||
def init():
|
||||
"""init function - runs once"""
|
||||
import os
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -81,6 +81,7 @@ for msg in translations_tuple:
|
||||
|
||||
# Define remaining addon (operators, UI...) here.
|
||||
|
||||
|
||||
def register():
|
||||
# Usual operator/UI/etc. registration...
|
||||
|
||||
|
||||
@@ -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 = \
|
||||
|
||||
@@ -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 = \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ bl_info = {
|
||||
"wiki_url": "",
|
||||
"tracker_url": "",
|
||||
"category": "Object",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import bpy
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -61,7 +61,7 @@ def panel_func(self, context):
|
||||
classes = (
|
||||
OBJECT_MT_draw_presets,
|
||||
AddPresetObjectDraw,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -21,4 +21,5 @@ class CyclesNodeTree(bpy.types.NodeTree):
|
||||
def poll(cls, context):
|
||||
return context.scene.render.engine == 'CYCLES'
|
||||
|
||||
|
||||
bpy.utils.register_class(CyclesNodeTree)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -41,6 +41,7 @@ class CustomDrawOperator(bpy.types.Operator):
|
||||
|
||||
col.prop(self, "my_string")
|
||||
|
||||
|
||||
bpy.utils.register_class(CustomDrawOperator)
|
||||
|
||||
# test call
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -48,7 +48,7 @@ _modules = [
|
||||
"vertexpaint_dirt",
|
||||
"view3d",
|
||||
"wm",
|
||||
]
|
||||
]
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
@@ -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.)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
@@ -35,8 +35,10 @@ class MeshMirrorUV(Operator):
|
||||
|
||||
direction = EnumProperty(
|
||||
name="Axis Direction",
|
||||
items=(('POSITIVE', "Positive", ""),
|
||||
('NEGATIVE', "Negative", "")),
|
||||
items=(
|
||||
('POSITIVE', "Positive", ""),
|
||||
('NEGATIVE', "Negative", ""),
|
||||
),
|
||||
)
|
||||
|
||||
precision = IntProperty(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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", ""),
|
||||
),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
)
|
||||
|
||||
|
||||
@@ -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 '//'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 = [\
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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',
|
||||
)
|
||||
|
||||
|
||||
@@ -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',
|
||||
)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -75,5 +75,6 @@ def register():
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(ModalDrawOperator)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
@@ -42,6 +42,7 @@ def unregister():
|
||||
|
||||
bpy.types.INFO_HT_header.remove(draw_item)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ def register():
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(SimpleCustomMenu)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user