Newer
Older
# bottom row
bottom_left = col_left.row()
bottom_left.active = lt.bridge_segments != 1
bottom_left.prop(lt, "bridge_interpolation", text="")
bottom_right = col_right.row()
bottom_right.active = lt.bridge_interpolation == 'cubic'
bottom_right.prop(lt, "bridge_cubic_strength")
# boolean properties
col_top.prop(lt, "bridge_remove_faces")
# override properties
col_top.separator()
row = box.row(align = True)
row.prop(lt, "bridge_twist")
row.prop(lt, "bridge_reverse")
# circle - first line
split = col.split(percentage=0.15, align=True)
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
if lt.display_circle:
split.prop(lt, "display_circle", text="", icon='DOWNARROW_HLT')
else:
split.prop(lt, "display_circle", text="", icon='RIGHTARROW')
split.operator("mesh.looptools_circle")
# circle - settings
if lt.display_circle:
box = col.column(align=True).box().column()
box.prop(lt, "circle_fit")
box.separator()
box.prop(lt, "circle_flatten")
row = box.row(align=True)
row.prop(lt, "circle_custom_radius")
row_right = row.row(align=True)
row_right.active = lt.circle_custom_radius
row_right.prop(lt, "circle_radius", text="")
box.prop(lt, "circle_regular")
box.separator()
box.prop(lt, "circle_influence")
# curve - first line
split = col.split(percentage=0.15, align=True)
if lt.display_curve:
split.prop(lt, "display_curve", text="", icon='DOWNARROW_HLT')
else:
split.prop(lt, "display_curve", text="", icon='RIGHTARROW')
split.operator("mesh.looptools_curve")
# curve - settings
if lt.display_curve:
box = col.column(align=True).box().column()
box.prop(lt, "curve_interpolation")
box.prop(lt, "curve_restriction")
box.prop(lt, "curve_boundaries")
box.prop(lt, "curve_regular")
box.separator()
box.prop(lt, "curve_influence")
# flatten - first line
split = col.split(percentage=0.15, align=True)
if lt.display_flatten:
split.prop(lt, "display_flatten", text="", icon='DOWNARROW_HLT')
else:
split.prop(lt, "display_flatten", text="", icon='RIGHTARROW')
split.operator("mesh.looptools_flatten")
# flatten - settings
if lt.display_flatten:
box = col.column(align=True).box().column()
box.prop(lt, "flatten_plane")
#box.prop(lt, "flatten_restriction")
box.separator()
box.prop(lt, "flatten_influence")
split = col.split(percentage=0.15, align=True)
if lt.display_gstretch:
split.prop(lt, "display_gstretch", text="", icon='DOWNARROW_HLT')
else:
split.prop(lt, "display_gstretch", text="", icon='RIGHTARROW')
split.operator("mesh.looptools_gstretch")
# gstretch settings
if lt.display_gstretch:
box = col.column(align=True).box().column()
box.prop(lt, "gstretch_method")
box.prop(lt, "gstretch_delete_strokes")
col_conv = box.column(align=True)
col_conv.prop(lt, "gstretch_conversion", text="")
if lt.gstretch_conversion == 'distance':
col_conv.prop(lt, "gstretch_conversion_distance")
elif lt.gstretch_conversion == 'limit_vertices':
row = col_conv.row(align=True)
row.prop(lt, "gstretch_conversion_min", text="Min")
row.prop(lt, "gstretch_conversion_max", text="Max")
elif lt.gstretch_conversion == 'vertices':
col_conv.prop(lt, "gstretch_conversion_vertices")
box.separator()
# loft - first line
split = col.split(percentage=0.15, align=True)
if lt.display_loft:
split.prop(lt, "display_loft", text="", icon='DOWNARROW_HLT')
else:
split.prop(lt, "display_loft", text="", icon='RIGHTARROW')
split.operator("mesh.looptools_bridge", text="Loft").loft = True
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
# loft - settings
if lt.display_loft:
box = col.column(align=True).box().column()
#box.prop(self, "mode")
# top row
col_top = box.column(align=True)
row = col_top.row(align=True)
col_left = row.column(align=True)
col_right = row.column(align=True)
col_right.active = lt.bridge_segments != 1
col_left.prop(lt, "bridge_segments")
col_right.prop(lt, "bridge_min_width", text="")
# bottom row
bottom_left = col_left.row()
bottom_left.active = lt.bridge_segments != 1
bottom_left.prop(lt, "bridge_interpolation", text="")
bottom_right = col_right.row()
bottom_right.active = lt.bridge_interpolation == 'cubic'
bottom_right.prop(lt, "bridge_cubic_strength")
# boolean properties
col_top.prop(lt, "bridge_remove_faces")
col_top.prop(lt, "bridge_loft_loop")
# override properties
col_top.separator()
row = box.row(align = True)
row.prop(lt, "bridge_twist")
row.prop(lt, "bridge_reverse")
# relax - first line
split = col.split(percentage=0.15, align=True)
if lt.display_relax:
split.prop(lt, "display_relax", text="", icon='DOWNARROW_HLT')
else:
split.prop(lt, "display_relax", text="", icon='RIGHTARROW')
split.operator("mesh.looptools_relax")
# relax - settings
if lt.display_relax:
box = col.column(align=True).box().column()
box.prop(lt, "relax_interpolation")
box.prop(lt, "relax_input")
box.prop(lt, "relax_iterations")
box.prop(lt, "relax_regular")
# space - first line
split = col.split(percentage=0.15, align=True)
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
if lt.display_space:
split.prop(lt, "display_space", text="", icon='DOWNARROW_HLT')
else:
split.prop(lt, "display_space", text="", icon='RIGHTARROW')
split.operator("mesh.looptools_space")
# space - settings
if lt.display_space:
box = col.column(align=True).box().column()
box.prop(lt, "space_interpolation")
box.prop(lt, "space_input")
box.separator()
box.prop(lt, "space_influence")
# property group containing all properties for the gui in the panel
class LoopToolsProps(bpy.types.PropertyGroup):
"""
Fake module like class
bpy.context.window_manager.looptools
"""
# general display properties
display_bridge = bpy.props.BoolProperty(name = "Bridge settings",
description = "Display settings of the Bridge tool",
default = False)
display_circle = bpy.props.BoolProperty(name = "Circle settings",
description = "Display settings of the Circle tool",
default = False)
display_curve = bpy.props.BoolProperty(name = "Curve settings",
description = "Display settings of the Curve tool",
default = False)
display_flatten = bpy.props.BoolProperty(name = "Flatten settings",
description = "Display settings of the Flatten tool",
default = False)
display_gstretch = bpy.props.BoolProperty(name = "Gstretch settings",
description = "Display settings of the Gstretch tool",
default = False)
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
display_loft = bpy.props.BoolProperty(name = "Loft settings",
description = "Display settings of the Loft tool",
default = False)
display_relax = bpy.props.BoolProperty(name = "Relax settings",
description = "Display settings of the Relax tool",
default = False)
display_space = bpy.props.BoolProperty(name = "Space settings",
description = "Display settings of the Space tool",
default = False)
# bridge properties
bridge_cubic_strength = bpy.props.FloatProperty(name = "Strength",
description = "Higher strength results in more fluid curves",
default = 1.0,
soft_min = -3.0,
soft_max = 3.0)
bridge_interpolation = bpy.props.EnumProperty(name = "Interpolation mode",
items = (('cubic', "Cubic", "Gives curved results"),
('linear', "Linear", "Basic, fast, straight interpolation")),
description = "Interpolation mode: algorithm used when creating "\
"segments",
default = 'cubic')
bridge_loft = bpy.props.BoolProperty(name = "Loft",
description = "Loft multiple loops, instead of considering them as "\
"a multi-input for bridging",
default = False)
bridge_loft_loop = bpy.props.BoolProperty(name = "Loop",
description = "Connect the first and the last loop with each other",
default = False)
bridge_min_width = bpy.props.IntProperty(name = "Minimum width",
description = "Segments with an edge smaller than this are merged "\
"(compared to base edge)",
default = 0,
min = 0,
max = 100,
subtype = 'PERCENTAGE')
bridge_mode = bpy.props.EnumProperty(name = "Mode",
items = (('basic', "Basic", "Fast algorithm"),
('shortest', "Shortest edge", "Slower algorithm with " \
"better vertex matching")),
description = "Algorithm used for bridging",
default = 'shortest')
bridge_remove_faces = bpy.props.BoolProperty(name = "Remove faces",
description = "Remove faces that are internal after bridging",
default = True)
bridge_reverse = bpy.props.BoolProperty(name = "Reverse",
description = "Manually override the direction in which the loops "\
"are bridged. Only use if the tool gives the wrong " \
"result",
default = False)
bridge_segments = bpy.props.IntProperty(name = "Segments",
description = "Number of segments used to bridge the gap "\
"(0 = automatic)",
default = 1,
min = 0,
soft_max = 20)
bridge_twist = bpy.props.IntProperty(name = "Twist",
description = "Twist what vertices are connected to each other",
default = 0)
# circle properties
circle_custom_radius = bpy.props.BoolProperty(name = "Radius",
description = "Force a custom radius",
default = False)
circle_fit = bpy.props.EnumProperty(name = "Method",
items = (("best", "Best fit", "Non-linear least squares"),
("inside", "Fit inside","Only move vertices towards the center")),
description = "Method used for fitting a circle to the vertices",
default = 'best')
circle_flatten = bpy.props.BoolProperty(name = "Flatten",
description = "Flatten the circle, instead of projecting it on the " \
"mesh",
default = True)
circle_influence = bpy.props.FloatProperty(name = "Influence",
description = "Force of the tool",
default = 100.0,
min = 0.0,
max = 100.0,
precision = 1,
subtype = 'PERCENTAGE')
circle_radius = bpy.props.FloatProperty(name = "Radius",
description = "Custom radius for circle",
default = 1.0,
min = 0.0,
soft_max = 1000.0)
circle_regular = bpy.props.BoolProperty(name = "Regular",
description = "Distribute vertices at constant distances along the " \
"circle",
default = True)
# curve properties
curve_boundaries = bpy.props.BoolProperty(name = "Boundaries",
description = "Limit the tool to work within the boundaries of the "\
"selected vertices",
default = False)
curve_influence = bpy.props.FloatProperty(name = "Influence",
description = "Force of the tool",
default = 100.0,
min = 0.0,
max = 100.0,
precision = 1,
subtype = 'PERCENTAGE')
curve_interpolation = bpy.props.EnumProperty(name = "Interpolation",
items = (("cubic", "Cubic", "Natural cubic spline, smooth results"),
("linear", "Linear", "Simple and fast linear algorithm")),
description = "Algorithm used for interpolation",
default = 'cubic')
curve_regular = bpy.props.BoolProperty(name = "Regular",
description = "Distribute vertices at constant distances along the " \
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
"curve",
default = True)
curve_restriction = bpy.props.EnumProperty(name = "Restriction",
items = (("none", "None", "No restrictions on vertex movement"),
("extrude", "Extrude only","Only allow extrusions (no "\
"indentations)"),
("indent", "Indent only", "Only allow indentation (no "\
"extrusions)")),
description = "Restrictions on how the vertices can be moved",
default = 'none')
# flatten properties
flatten_influence = bpy.props.FloatProperty(name = "Influence",
description = "Force of the tool",
default = 100.0,
min = 0.0,
max = 100.0,
precision = 1,
subtype = 'PERCENTAGE')
flatten_plane = bpy.props.EnumProperty(name = "Plane",
items = (("best_fit", "Best fit", "Calculate a best fitting plane"),
("normal", "Normal", "Derive plane from averaging vertex "\
"normals"),
("view", "View", "Flatten on a plane perpendicular to the "\
"viewing angle")),
description = "Plane on which vertices are flattened",
default = 'best_fit')
flatten_restriction = bpy.props.EnumProperty(name = "Restriction",
items = (("none", "None", "No restrictions on vertex movement"),
("bounding_box", "Bounding box", "Vertices are restricted to "\
"movement inside the bounding box of the selection")),
description = "Restrictions on how the vertices can be moved",
default = 'none')
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
gstretch_conversion = bpy.props.EnumProperty(name = "Conversion",
items = (("distance", "Distance", "Set the distance between vertices "\
"of the converted grease pencil stroke"),
("limit_vertices", "Limit vertices", "Set the minimum and maximum "\
"number of vertices that converted GP strokes will have"),
("vertices", "Exact vertices", "Set the exact number of vertices "\
"that converted grease pencil strokes will have. Short strokes "\
"with few points may contain less vertices than this number."),
("none", "No simplification", "Convert each grease pencil point "\
"to a vertex")),
description = "If grease pencil strokes are converted to geometry, "\
"use this simplification method",
default = 'limit_vertices')
gstretch_conversion_distance = bpy.props.FloatProperty(name = "Distance",
description = "Absolute distance between vertices along the converted "\
"grease pencil stroke",
default = 0.1,
min = 0.000001,
soft_min = 0.01,
soft_max = 100)
gstretch_conversion_max = bpy.props.IntProperty(name = "Max Vertices",
description = "Maximum number of vertices grease pencil strokes will "\
"have, when they are converted to geomtery",
default = 32,
min = 3,
soft_max = 500,
update = gstretch_update_min)
gstretch_conversion_min = bpy.props.IntProperty(name = "Min Vertices",
description = "Minimum number of vertices grease pencil strokes will "\
"have, when they are converted to geomtery",
default = 8,
min = 3,
soft_max = 500,
update = gstretch_update_max)
gstretch_conversion_vertices = bpy.props.IntProperty(name = "Vertices",
description = "Number of vertices grease pencil strokes will "\
"have, when they are converted to geometry. If strokes have less "\
"points than required, the 'Spread evenly' method is used.",
default = 32,
min = 3,
soft_max = 500)
gstretch_delete_strokes = bpy.props.BoolProperty(name="Delete strokes",
description = "Remove Grease Pencil strokes if they have been used "\
"for Gstretch. WARNING: DOES NOT SUPPORT UNDO",
default = False)
gstretch_influence = bpy.props.FloatProperty(name = "Influence",
description = "Force of the tool",
default = 100.0,
min = 0.0,
max = 100.0,
precision = 1,
subtype = 'PERCENTAGE')
gstretch_method = bpy.props.EnumProperty(name = "Method",
items = (("project", "Project", "Project vertices onto the stroke, "\
"using vertex normals and connected edges"),
("irregular", "Spread", "Distribute vertices along the full "\
"stroke, retaining relative distances between the vertices"),
("regular", "Spread evenly", "Distribute vertices at regular "\
"distances along the full stroke")),
description = "Method of distributing the vertices over the Grease "\
"Pencil stroke",
default = 'regular')
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
# relax properties
relax_input = bpy.props.EnumProperty(name = "Input",
items = (("all", "Parallel (all)", "Also use non-selected "\
"parallel loops as input"),
("selected", "Selection","Only use selected vertices as input")),
description = "Loops that are relaxed",
default = 'selected')
relax_interpolation = bpy.props.EnumProperty(name = "Interpolation",
items = (("cubic", "Cubic", "Natural cubic spline, smooth results"),
("linear", "Linear", "Simple and fast linear algorithm")),
description = "Algorithm used for interpolation",
default = 'cubic')
relax_iterations = bpy.props.EnumProperty(name = "Iterations",
items = (("1", "1", "One"),
("3", "3", "Three"),
("5", "5", "Five"),
("10", "10", "Ten"),
("25", "25", "Twenty-five")),
description = "Number of times the loop is relaxed",
default = "1")
relax_regular = bpy.props.BoolProperty(name = "Regular",
description = "Distribute vertices at constant distances along the" \
"loop",
default = True)
# space properties
space_influence = bpy.props.FloatProperty(name = "Influence",
description = "Force of the tool",
default = 100.0,
min = 0.0,
max = 100.0,
precision = 1,
subtype = 'PERCENTAGE')
space_input = bpy.props.EnumProperty(name = "Input",
items = (("all", "Parallel (all)", "Also use non-selected "\
"parallel loops as input"),
("selected", "Selection","Only use selected vertices as input")),
description = "Loops that are spaced",
default = 'selected')
space_interpolation = bpy.props.EnumProperty(name = "Interpolation",
items = (("cubic", "Cubic", "Natural cubic spline, smooth results"),
("linear", "Linear", "Vertices are projected on existing edges")),
description = "Algorithm used for interpolation",
default = 'cubic')
# draw function for integration in menus
def menu_func(self, context):
self.layout.menu("VIEW3D_MT_edit_mesh_looptools")
self.layout.separator()
# define classes for registration
classes = [VIEW3D_MT_edit_mesh_looptools,
VIEW3D_PT_tools_looptools,
LoopToolsProps,
Bridge,
Circle,
Curve,
Flatten,
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
Relax,
Space]
# registering and menu integration
def register():
for c in classes:
bpy.utils.register_class(c)
bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_func)
bpy.types.WindowManager.looptools = bpy.props.PointerProperty(\
type = LoopToolsProps)
# unregistering and removing menus
def unregister():
for c in classes:
bpy.utils.unregister_class(c)
bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func)
try:
del bpy.types.WindowManager.looptools
except:
pass
if __name__ == "__main__":
register()