Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
blender-addons
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
blender
blender-addons
Commits
62c114e2
Commit
62c114e2
authored
12 years ago
by
Bart Crouch
Browse files
Options
Downloads
Patches
Plain Diff
Moving F2 from contrib to trunk. Add-on has been approved by a code review.
[[Split portion of a mixed commit.]]
parent
d2c18e87
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
mesh_f2.py
+298
-0
298 additions, 0 deletions
mesh_f2.py
with
298 additions
and
0 deletions
mesh_f2.py
0 → 100644
+
298
−
0
View file @
62c114e2
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
bl_info
=
{
'
name
'
:
"
F2
"
,
'
author
'
:
"
Bart Crouch
"
,
'
version
'
:
(
1
,
4
,
0
),
'
blender
'
:
(
2
,
65
,
9
),
'
location
'
:
"
Editmode > F
"
,
'
warning
'
:
""
,
'
description
'
:
"
Extends the
'
Make Edge/Face
'
functionality
"
,
'
wiki_url
'
:
"
http://wiki.blender.org/index.php/Extensions:2.6/Py/
"
\
"
Scripts/Modeling/F2
"
,
'
tracker_url
'
:
"
http://projects.blender.org/tracker/index.php?
"
\
"
func=detail&aid=33979
"
,
'
category
'
:
'
Mesh
'
}
import
bmesh
import
bpy
import
itertools
import
mathutils
from
bpy_extras
import
view3d_utils
# create a face from a single selected edge
def
quad_from_edge
(
bm
,
edge_sel
,
context
,
event
):
ob
=
context
.
active_object
region
=
context
.
region
region_3d
=
context
.
space_data
.
region_3d
# find linked edges that are open (<2 faces connected) and not part of
# the face the selected edge belongs to
all_edges
=
[[
edge
for
edge
in
edge_sel
.
verts
[
i
].
link_edges
if
\
len
(
edge
.
link_faces
)
<
2
and
edge
!=
edge_sel
and
\
sum
([
face
in
edge_sel
.
link_faces
for
face
in
edge
.
link_faces
])
==
0
]
\
for
i
in
range
(
2
)]
if
not
all_edges
[
0
]
or
not
all_edges
[
1
]:
return
# determine which edges to use, based on mouse cursor position
mouse_pos
=
mathutils
.
Vector
([
event
.
mouse_region_x
,
event
.
mouse_region_y
])
optimal_edges
=
[]
for
edges
in
all_edges
:
min_dist
=
False
for
edge
in
edges
:
vert
=
[
vert
for
vert
in
edge
.
verts
if
not
vert
.
select
][
0
]
world_pos
=
ob
.
matrix_world
*
vert
.
co
.
copy
()
screen_pos
=
view3d_utils
.
location_3d_to_region_2d
(
region
,
region_3d
,
world_pos
)
dist
=
(
mouse_pos
-
screen_pos
).
length
if
not
min_dist
or
dist
<
min_dist
[
0
]:
min_dist
=
(
dist
,
edge
,
vert
)
optimal_edges
.
append
(
min_dist
)
# determine the vertices, which make up the quad
v1
=
edge_sel
.
verts
[
0
]
v2
=
edge_sel
.
verts
[
1
]
edge_1
=
optimal_edges
[
0
][
1
]
edge_2
=
optimal_edges
[
1
][
1
]
v3
=
optimal_edges
[
0
][
2
]
v4
=
optimal_edges
[
1
][
2
]
# normal detection
flip_align
=
True
normal_edge
=
edge_1
if
not
normal_edge
.
link_faces
:
normal_edge
=
edge_2
if
not
normal_edge
.
link_faces
:
normal_edge
=
edge_sel
if
not
normal_edge
.
link_faces
:
# no connected faces, so no need to flip the face normal
flip_align
=
False
if
flip_align
:
# there is a face to which the normal can be aligned
ref_verts
=
[
v
for
v
in
normal_edge
.
link_faces
[
0
].
verts
]
if
v3
in
ref_verts
:
va_1
=
v3
va_2
=
v1
elif
normal_edge
==
edge_sel
:
va_1
=
v1
va_2
=
v2
else
:
va_1
=
v2
va_2
=
v4
if
(
va_1
==
ref_verts
[
0
]
and
va_2
==
ref_verts
[
-
1
])
or
\
(
va_2
==
ref_verts
[
0
]
and
va_1
==
ref_verts
[
-
1
]):
# reference verts are at start and end of the list -> shift list
ref_verts
=
ref_verts
[
1
:]
+
[
ref_verts
[
0
]]
if
ref_verts
.
index
(
va_1
)
>
ref_verts
.
index
(
va_2
):
# connected face has same normal direction, so don't flip
flip_align
=
False
# material index detection
ref_faces
=
edge_sel
.
link_faces
if
not
ref_faces
:
ref_faces
=
edge_sel
.
verts
[
0
].
link_faces
if
not
ref_faces
:
ref_faces
=
edge_sel
.
verts
[
1
].
link_faces
if
not
ref_faces
:
mat_index
=
False
smooth
=
False
else
:
mat_index
=
ref_faces
[
0
].
material_index
smooth
=
ref_faces
[
0
].
smooth
# create quad
try
:
verts
=
[
v3
,
v1
,
v2
,
v4
]
if
flip_align
:
verts
.
reverse
()
face
=
bm
.
faces
.
new
(
verts
)
if
mat_index
:
face
.
material_index
=
mat_index
face
.
smooth
=
smooth
except
:
# face already exists
return
# change selection
edge_sel
.
select
=
False
for
vert
in
edge_sel
.
verts
:
vert
.
select
=
False
for
edge
in
face
.
edges
:
if
edge
.
index
<
0
:
edge
.
select
=
True
v3
.
select
=
True
v4
.
select
=
True
# toggle mode, to force correct drawing
bpy
.
ops
.
object
.
mode_set
(
mode
=
'
OBJECT
'
)
bpy
.
ops
.
object
.
mode_set
(
mode
=
'
EDIT
'
)
# create a face from a single selected vertex, if it is an open vertex
def
quad_from_vertex
(
bm
,
vert_sel
,
context
,
event
):
ob
=
context
.
active_object
region
=
context
.
region
region_3d
=
context
.
space_data
.
region_3d
# find linked edges that are open (<2 faces connected)
edges
=
[
edge
for
edge
in
vert_sel
.
link_edges
if
len
(
edge
.
link_faces
)
<
2
]
if
len
(
edges
)
<
2
:
return
# determine which edges to use, based on mouse cursor position
min_dist
=
False
mouse_pos
=
mathutils
.
Vector
([
event
.
mouse_region_x
,
event
.
mouse_region_y
])
for
a
,
b
in
itertools
.
combinations
(
edges
,
2
):
other_verts
=
[
vert
for
edge
in
[
a
,
b
]
for
vert
in
edge
.
verts
\
if
not
vert
.
select
]
mid_other
=
(
other_verts
[
0
].
co
.
copy
()
+
other_verts
[
1
].
co
.
copy
())
\
/
2
new_pos
=
2
*
(
mid_other
-
vert_sel
.
co
.
copy
())
+
vert_sel
.
co
.
copy
()
world_pos
=
ob
.
matrix_world
*
new_pos
screen_pos
=
view3d_utils
.
location_3d_to_region_2d
(
region
,
region_3d
,
world_pos
)
dist
=
(
mouse_pos
-
screen_pos
).
length
if
not
min_dist
or
dist
<
min_dist
[
0
]:
min_dist
=
(
dist
,
(
a
,
b
),
other_verts
,
new_pos
)
# create vertex at location mirrored in the line, connecting the open edges
edges
=
min_dist
[
1
]
other_verts
=
min_dist
[
2
]
new_pos
=
min_dist
[
3
]
vert_new
=
bm
.
verts
.
new
(
new_pos
)
# normal detection
flip_align
=
True
normal_edge
=
edges
[
0
]
if
not
normal_edge
.
link_faces
:
normal_edge
=
edges
[
1
]
if
not
normal_edge
.
link_faces
:
# no connected faces, so no need to flip the face normal
flip_align
=
False
if
flip_align
:
# there is a face to which the normal can be aligned
ref_verts
=
[
v
for
v
in
normal_edge
.
link_faces
[
0
].
verts
]
if
other_verts
[
0
]
in
ref_verts
:
va_1
=
other_verts
[
0
]
va_2
=
vert_sel
else
:
va_1
=
vert_sel
va_2
=
other_verts
[
1
]
if
(
va_1
==
ref_verts
[
0
]
and
va_2
==
ref_verts
[
-
1
])
or
\
(
va_2
==
ref_verts
[
0
]
and
va_1
==
ref_verts
[
-
1
]):
# reference verts are at start and end of the list -> shift list
ref_verts
=
ref_verts
[
1
:]
+
[
ref_verts
[
0
]]
if
ref_verts
.
index
(
va_1
)
>
ref_verts
.
index
(
va_2
):
# connected face has same normal direction, so don't flip
flip_align
=
False
# material index detection
ref_faces
=
vert_sel
.
link_faces
if
not
ref_faces
:
mat_index
=
False
smooth
=
False
else
:
mat_index
=
ref_faces
[
0
].
material_index
smooth
=
ref_faces
[
0
].
smooth
# create face between all 4 vertices involved
verts
=
[
other_verts
[
0
],
vert_sel
,
other_verts
[
1
],
vert_new
]
if
flip_align
:
verts
.
reverse
()
face
=
bm
.
faces
.
new
(
verts
)
if
mat_index
:
face
.
material_index
=
mat_index
face
.
smooth
=
smooth
# change selection
vert_new
.
select
=
True
vert_sel
.
select
=
False
# toggle mode, to force correct drawing
bpy
.
ops
.
object
.
mode_set
(
mode
=
'
OBJECT
'
)
bpy
.
ops
.
object
.
mode_set
(
mode
=
'
EDIT
'
)
class
MeshF2
(
bpy
.
types
.
Operator
):
"""
Tooltip
"""
bl_idname
=
"
mesh.f2
"
bl_label
=
"
Make Edge/Face
"
bl_description
=
"
Extends the
'
Make Edge/Face
'
functionality
"
bl_options
=
{
'
REGISTER
'
,
'
UNDO
'
}
@classmethod
def
poll
(
cls
,
context
):
# check we are in mesh editmode
ob
=
context
.
active_object
return
(
ob
and
ob
.
type
==
'
MESH
'
and
context
.
mode
==
'
EDIT_MESH
'
)
def
invoke
(
self
,
context
,
event
):
bm
=
bmesh
.
from_edit_mesh
(
context
.
active_object
.
data
)
sel
=
[
v
for
v
in
bm
.
verts
if
v
.
select
]
if
len
(
sel
)
>
2
:
# original 'Make Edge/Face' behaviour
bpy
.
ops
.
mesh
.
edge_face_add
()
elif
len
(
sel
)
==
1
:
# single vertex selected -> mirror vertex and create new face
quad_from_vertex
(
bm
,
sel
[
0
],
context
,
event
)
elif
len
(
sel
)
==
2
:
edges_sel
=
[
ed
for
ed
in
bm
.
edges
if
ed
.
select
]
if
len
(
edges_sel
)
!=
1
:
# 2 vertices selected, but not on the same edge
bpy
.
ops
.
mesh
.
edge_face_add
()
else
:
# single edge selected -> new face from linked open edges
quad_from_edge
(
bm
,
edges_sel
[
0
],
context
,
event
)
return
{
'
FINISHED
'
}
# registration
classes
=
[
MeshF2
]
addon_keymaps
=
[]
def
register
():
# add operator
for
c
in
classes
:
bpy
.
utils
.
register_class
(
c
)
# add keymap entry
km
=
bpy
.
context
.
window_manager
.
keyconfigs
.
addon
.
keymaps
.
new
(
\
name
=
'
Mesh
'
,
space_type
=
'
EMPTY
'
)
kmi
=
km
.
keymap_items
.
new
(
"
mesh.f2
"
,
'
F
'
,
'
PRESS
'
)
addon_keymaps
.
append
(
km
)
def
unregister
():
# remove operator
for
c
in
classes
:
bpy
.
utils
.
unregister_class
(
c
)
# remove keymap entry
for
km
in
addon_keymaps
:
bpy
.
context
.
window_manager
.
keyconfigs
.
addon
.
keymaps
.
remove
(
km
)
addon_keymaps
.
clear
()
if
__name__
==
"
__main__
"
:
register
()
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment