Newer
Older
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)
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
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
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
# 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)
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
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)
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
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
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 " \
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
"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')
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
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
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)
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
gstretch_delete_strokes = bpy.props.BoolProperty(name="Delete strokes",
description = "Remove Grease Pencil strokes if they have been used "\
"for Gstretch",
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')
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
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
# 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,
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
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()