Hi, awesome addon, definitely worth paying for!
I saw that you can rename “Orientation&Pivot” bookmarks but is there no way to rename snapping combos? I’d love to be able to rename them to something more memorable than “Snap combo 1” etc.
Keep up the great work, I used your addon for Modo before switching.
Great add-on!
Is it possible to add functionality to the Direct Loop Cut similar to modo? Specifically, is it possible to run Loop Slice presets in one click?
Earlier post with more details:
Referencing scripts by Cristobal Vila, ETEREA Slices Presets 1.4
https://community.foundry.com/discuss/topic/26386
Hey! Yes, I’ll add that to the list.
Hey! Yes, I am familiar with the idea. I still have that pie menu in my modo install. (But I never really used them). Personal side note: Currently I experiment with “korean” bevels (aka just flat or square bevels for subd workflows) using the bevel modifier and/or edge-bevel. (2 segments, profile 1), and weighting and/or creasing.
I could make a similar pie with presets with a custom defined cut operation or two. maybe all. fairly easily (you set prefs for the end-offset %) (it would just be a macro of loop cut and offset edge slide pretty much) I’ll add it, as that is simple enough ;>
(note: it wont actually use direct loop cut at all. When I was planning on making DLC modal I actually wanted to include hotkeys for such multislices, but that got cut. pun intended.)
Well, why not give it a try - quite handy feature (besides “korean” bevel)
Personally, I like it better because it’s faster and more flexible in lot of cases.
I’ve made similar functionality in Blender for myself some time ago. It isn’t an external addon, so it’s useless for people atm without some tricky manipulations.
Awesome! Thank you!
Hi.
I have the same with a little exception, I use EVEN values on sides, in cases when mesh is not perfectly square.
Example 1:
It built from other scripts, so it also can’t be possible exported…but we all know how @Kiellog is good!
Updated:
Also it’s possible to do like this, with choosing parameters
Code:
class EDGE_OT_5_90_5 (Operator):
bl_idname = "edge.5_90_5"
bl_label = "Slide Offset X - XX - X"
bl_description = "Slide Offset Even or Not"
bl_options = {'REGISTER', 'UNDO'}
even: bpy.props.EnumProperty(
items=[("ON", "ON", "ON", 1),
("OFF", "OFF", "OFF", 2)
],
name="Even",
default="ON")
values: bpy.props.EnumProperty(
items=[("5-90-5", "5-90-5", "5-90-5", 1),
("10-80-10", "10-80-10", "10-80-10", 2),
("15-70-15", "15-70-15", "15-70-15", 3),
("20-60-20", "20-60-20", "20-60-20", 4),
("25-50-25", "25-50-25", "25-50-25", 5)
],
name="Values",
default="5-90-5")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
column = layout.column()
row = column.row()
row.prop(self, "even", expand=True)
# row = column.row()
# row.prop(self, "values", expand=True)
col = layout.column()
col.prop(self, "values", expand=True)
def main(self, context):
if self.even == 'ON':
if self.values == '5-90-5':
return 0.9
elif self.values == '10-80-10':
return 0.8
elif self.values == '15-70-15':
return 0.7
elif self.values == '20-60-20':
return 0.6
elif self.values == '25-50-25':
return 0.5
if self.even == 'OFF':
if self.values == '5-90-5':
return 0.9
elif self.values == '10-80-10':
return 0.8
elif self.values == '15-70-15':
return 0.7
elif self.values == '20-60-20':
return 0.6
elif self.values == '25-50-25':
return 0.5
def execute(self, context):
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)
bpy.ops.armored.connect()
selEdges = [e for e in bm.edges if e.select]
if self.even =='ON':
bpy.ops.mesh.offset_edge_loops_slide(TRANSFORM_OT_edge_slide={
"value":self.main(context),
"single_side":True,
"use_even":True,
"flipped":True,
"use_clamp":True,
"mirror":True,
"snap":False,
"snap_target":'CLOSEST',
"snap_point":(0, 0, 0),
"snap_align":False,
"snap_normal":(0, 0, 0),
"correct_uv":True,
"release_confirm":False,
"use_accurate":False
})
if self.even =='OFF':
bpy.ops.mesh.offset_edge_loops_slide(TRANSFORM_OT_edge_slide={
"value":self.main(context),
"single_side":True,
"use_even":False,
"flipped":False,
"use_clamp":True,
"mirror":True,
"snap":False,
"snap_target":'CLOSEST',
"snap_point":(0, 0, 0),
"snap_align":False,
"snap_normal":(0, 0, 0),
"correct_uv":True,
"release_confirm":False,
"use_accurate":False
})
selEdges2 = [e for e in bm.edges if e.select]
bpy.ops.mesh.select_all(action='DESELECT')
for e in selEdges:
e.select = True
bpy.ops.mesh.dissolve_mode(use_verts=True)
for e in selEdges2:
e.select = True
return {'FINISHED'}
I used other script from ARMORED COLONY (bpy.ops.armored.connect()
) which basically slice selected edge without selecting whole loop. Then I just used default blender “Edge Offset” with some tweaks and remembering selection for dissolving unneeded loop after…
So, if @Kiellog not mind
here is complete code for loop tool in my previous post.
Works only with edges. Need exceptions for verts/faces selection (it recognize them as edges too).
modify whatever you need
code
class EDGE_OT_5_90_5 (Operator):
bl_idname = "edge.5_90_5"
bl_label = "Slide Offset X - XX - X"
bl_description = "Slide Offset Even or Not"
bl_options = {'REGISTER', 'UNDO'}
even: bpy.props.EnumProperty(
items=[("ON", "ON", "ON", 1),
("OFF", "OFF", "OFF", 2)
],
name="Even",
default="ON")
values: bpy.props.EnumProperty(
items=[("5-90-5", "5-90-5", "5-90-5", 1),
("10-80-10", "10-80-10", "10-80-10", 2),
("15-70-15", "15-70-15", "15-70-15", 3),
("20-60-20", "20-60-20", "20-60-20", 4),
("25-50-25", "25-50-25", "25-50-25", 5)
],
name="Values",
default="5-90-5")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
column = layout.column()
row = column.row()
row.prop(self, "even", expand=True)
# row = column.row()
# row.prop(self, "values", expand=True)
col = layout.column()
col.prop(self, "values", expand=True)
def main(self, context):
if self.even == 'ON':
if self.values == '5-90-5':
return 0.9
elif self.values == '10-80-10':
return 0.8
elif self.values == '15-70-15':
return 0.7
elif self.values == '20-60-20':
return 0.6
elif self.values == '25-50-25':
return 0.5
if self.even == 'OFF':
if self.values == '5-90-5':
return 0.9
elif self.values == '10-80-10':
return 0.8
elif self.values == '15-70-15':
return 0.7
elif self.values == '20-60-20':
return 0.6
elif self.values == '25-50-25':
return 0.5
def execute(self, context):
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)
bpy.ops.mesh.loop_multi_select(ring=True)
#remembering ring of cuting edges
cut_edges = [e for e in bm.edges if e.select]
bpy.ops.mesh.select_all(action='DESELECT')
#remembering new edges after subdivide_edges for dissolving them later
middle_edges = bmesh.ops.subdivide_edges(bm, edges=list(cut_edges), cuts=1, use_grid_fill=False)
#selecting inner edges with 'geom_inner' after subdivide_edges operation
for e in middle_edges['geom_inner']: e.select = True
bmesh.update_edit_mesh(me)
#Offset Edge Slide with Even:ON
if self.even =='ON':
bpy.ops.mesh.offset_edge_loops_slide(TRANSFORM_OT_edge_slide={
"value":self.main(context),
"single_side":True,
"use_even":True,
"flipped":True,
"use_clamp":True,
"mirror":True,
"snap":False,
"snap_target":'CLOSEST',
"snap_point":(0, 0, 0),
"snap_align":False,
"snap_normal":(0, 0, 0),
"correct_uv":True,
"release_confirm":False,
"use_accurate":False
})
#Offset Edge Slide with Even:OFF
if self.even =='OFF':
bpy.ops.mesh.offset_edge_loops_slide(TRANSFORM_OT_edge_slide={
"value":self.main(context),
"single_side":True,
"use_even":False,
"flipped":False,
"use_clamp":True,
"mirror":True,
"snap":False,
"snap_target":'CLOSEST',
"snap_point":(0, 0, 0),
"snap_align":False,
"snap_normal":(0, 0, 0),
"correct_uv":True,
"release_confirm":False,
"use_accurate":False
})
#remembering edges after Offset Edge Slide operation
sel_edges = [e for e in bm.edges if e.select]
bpy.ops.mesh.select_all(action='DESELECT')
#selecting inner middle edge loop for dissolving
for e in middle_edges['geom_inner']: e.select = True
bpy.ops.mesh.dissolve_mode(use_verts=True)
#selecting earlier remembering edges after Offset Edge Slide operation
for e in sel_edges:
e.select = True
return {'FINISHED'}
col.operator("edge.5_90_5", icon="PAUSE")
for UI pannel
cheers,
I do have a test version up & running already, it will get the offsets correct automatically, like so;
Redo panel comes later, I’ll add as much customization as I can ;>
(I got stuck trying to add more cuts though, very strange issues using ops. So I either have to code it or just stick to 3 cuts max (center cut optional)…which I’m leaning towards. )
IMO you don’t need more then 3 cuts, in most cases it even no need middle cut. So you just cut at the sides and then do other operation with created selected loops.
My best wish if this tool be interactive. Not just select presets 5-90-5, and how in modo with interactive sliding…but it’s not possible with simple macros.
Updated:
Lol, just forgot about FloatProperty
possibility
Updated Code
class EDGE_OT_5_90_5 (Operator):
bl_idname = "edge.5_90_5"
bl_label = "Slide Offset X - XX - X"
bl_description = "Slide Offset Even or Not"
bl_options = {'REGISTER', 'UNDO'}
even: bpy.props.EnumProperty(
items=[("ON", "ON", "ON", 1),
("OFF", "OFF", "OFF", 2)
],
name="Even",
default="ON")
factor: FloatProperty(
name="Factor",
min=0.1,
max=1.0,
step=0.1,
default=0.9
)
def draw(self, context):
layout = self.layout
layout.use_property_split = True
column = layout.column()
row = column.row()
row.prop(self, "even", expand=True)
# row = column.row()
# row.prop(self, "values", expand=True)
col = layout.column()
col.prop(self, "factor")
def main(self, context):
if self.even == 'ON':
if self.factor:
return self.factor
if self.even == 'OFF':
if self.factor:
return self.factor
def execute(self, context):
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)
bpy.ops.mesh.loop_multi_select(ring=True)
#remembering ring of cuting edges
cut_edges = [e for e in bm.edges if e.select]
bpy.ops.mesh.select_all(action='DESELECT')
#remembering new edges after subdivide_edges for dissolving them later
middle_edges = bmesh.ops.subdivide_edges(bm, edges=list(cut_edges), cuts=1, use_grid_fill=False)
#selecting inner edges with 'geom_inner' after subdivide_edges operation
for e in middle_edges['geom_inner']: e.select = True
bmesh.update_edit_mesh(me)
#Offset Edge Slide with Even:ON
if self.even =='ON':
bpy.ops.mesh.offset_edge_loops_slide(TRANSFORM_OT_edge_slide={
"value":self.main(context),
"single_side":True,
"use_even":True,
"flipped":True,
"use_clamp":True,
"mirror":True,
"snap":False,
"snap_target":'CLOSEST',
"snap_point":(0, 0, 0),
"snap_align":False,
"snap_normal":(0, 0, 0),
"correct_uv":True,
"release_confirm":False,
"use_accurate":False
})
#Offset Edge Slide with Even:OFF
if self.even =='OFF':
bpy.ops.mesh.offset_edge_loops_slide(TRANSFORM_OT_edge_slide={
"value":self.main(context),
"single_side":True,
"use_even":False,
"flipped":False,
"use_clamp":True,
"mirror":True,
"snap":False,
"snap_target":'CLOSEST',
"snap_point":(0, 0, 0),
"snap_align":False,
"snap_normal":(0, 0, 0),
"correct_uv":True,
"release_confirm":False,
"use_accurate":False
})
#remembering edges after Offset Edge Slide operation
sel_edges = [e for e in bm.edges if e.select]
bpy.ops.mesh.select_all(action='DESELECT')
#selecting inner middle edge loop for dissolving
for e in middle_edges['geom_inner']: e.select = True
bpy.ops.mesh.dissolve_mode(use_verts=True)
#selecting earlier remembering edges after Offset Edge Slide operation
for e in sel_edges:
e.select = True
return {'FINISHED'}
in UI panel you can create presets like this
op = col.operator("edge.5_90_5", text="Slide Offset | OFF | 0.5 ", icon="PAUSE")
op.even = 'OFF'
op.factor = 0.5
Heh ;>
Well, not being a huge fan of the redo panel (I like things immediate) one could do a little hack where you just use offset loop slide in modal, and dissolve the center when LMB (if one does not want it)
Why it’s very convenient to have loops selected after running tool, you can do like this
Oh nice! As someone coming from Modo having to use the redo panel feels slow, I’d much rather have the tool do what I need in one action.
Would it be possible to add an option to use absolute distance instead of percentages? If I have two differently sized props Id still want the bevels to be the same size to ground the assets.
It is possible, sure. Hmm, there are some complex issues trying to combine everything in the same behaviour - I think the modal variant will be a bit different, and maybe a little more dynamic (not as big of a need for presets, as it just a starting point anyways in modal) Probably will use the same operator, just different modes. Or i separate them to keep it simple. we´ll see
I cant replicate. Works afaict. Could you be more specific? (extruding verts? using split edges with “auto merge”, value not at 0.001?)
Thank you for letting know, so, knowing its bug on my side, i found a solution.
Installed on vanilla one - everything works as expected, so made some tests in my 2.9 and found that it needs:
- to hold standard extrude operator in mesh section (was deleted by myself)
- and place “context extrude” below it (adding operator back didnt get result at first so i reapplied “context delete”)
Maybe i missed or misunderstand something but for me everything works now (•¯ ∀ ¯•)
Ok! Good that you found a solution.
I could not understand your explanation/process though
Are you talking about shortcut mappings or modifying python code, or something else?
I see! Tip: If you get conflicts with multple assignments to the same hotkey,it does look a bit dubious, just disabling the unwanted hotkeys is an option. (then you can easily re-assign as well) Example: