forked from bartvdbraak/blender
removing this script because editmode select group replaces it.
This commit is contained in:
parent
cbf7e5cd0f
commit
cd87c75a2f
@ -1,398 +0,0 @@
|
|||||||
#!BPY
|
|
||||||
|
|
||||||
"""
|
|
||||||
Name: 'Similar to Active'
|
|
||||||
Blender: 234
|
|
||||||
Group: 'FaceSelect'
|
|
||||||
Tooltip: 'Select faces that match a given attribute of the active face'
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = "Campbell Barton"
|
|
||||||
__url__ = ["blender", "elysiun"]
|
|
||||||
__version__ = "1.0"
|
|
||||||
|
|
||||||
__bpydoc__ = """\
|
|
||||||
This script selects faces matching a given attribute of the currently
|
|
||||||
active face.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
Enter "UV Face Select" mode and make the desired face active. Then run this
|
|
||||||
script and choose the selection rule: by same (or similar for some itens):
|
|
||||||
|
|
||||||
- material;<br>
|
|
||||||
- texture image;<br>
|
|
||||||
- mode;<br>
|
|
||||||
- vertex colors;<br>
|
|
||||||
- uv coordinates;<br>
|
|
||||||
- area;<br>
|
|
||||||
- proportions;<br>
|
|
||||||
- normal vector;<br>
|
|
||||||
- coplanar.
|
|
||||||
|
|
||||||
Another menu will ask if the script should add, subtract, overwrite or
|
|
||||||
overwrite inverse of current current selection. For some choices like vcolors,
|
|
||||||
area, etc., a pop-up will ask for a maximum threshold value.
|
|
||||||
|
|
||||||
Notes:<br>
|
|
||||||
Again, to select / deselect faces, enter "UV Face Select" mode. This is not
|
|
||||||
the same as selecting faces in edit mode (new feature in Blender 2.35).
|
|
||||||
"""
|
|
||||||
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
#===============================================#
|
|
||||||
# Sel Same script 1.0 by Campbell Barton #
|
|
||||||
# email me ideasman@linuxmail.org #
|
|
||||||
#===============================================#
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
# Sel Same Face 1.0 By Campbell Barton (AKA Ideasman)
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
# ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
#
|
|
||||||
# ***** END GPL LICENCE BLOCK *****
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
from Blender import *
|
|
||||||
from Blender.Mathutils import DotVecs, Vector
|
|
||||||
from math import sqrt
|
|
||||||
|
|
||||||
|
|
||||||
#====================================#
|
|
||||||
# Sanity checks #
|
|
||||||
#====================================#
|
|
||||||
def error(str):
|
|
||||||
Draw.PupMenu('ERROR: '+str)
|
|
||||||
af = None
|
|
||||||
selection = Object.GetSelected()
|
|
||||||
if len(selection) == 0:
|
|
||||||
error('No object selected')
|
|
||||||
else:
|
|
||||||
object = Object.GetSelected()[0]
|
|
||||||
if object.getType() != 'Mesh':
|
|
||||||
error('Active object must be a mesh')
|
|
||||||
else:
|
|
||||||
mesh = object.getData()
|
|
||||||
|
|
||||||
# We have a mesh so find AF.
|
|
||||||
af = mesh.getActiveFace()
|
|
||||||
if af: af = mesh.faces[af]
|
|
||||||
|
|
||||||
if af == None:
|
|
||||||
error('No active face')
|
|
||||||
|
|
||||||
else: # Okay everything seems sane
|
|
||||||
|
|
||||||
#=====================================
|
|
||||||
# Popup menu to select the functions #
|
|
||||||
#====================================#
|
|
||||||
method = Draw.PupMenu(\
|
|
||||||
'Selection Attribute%t|\
|
|
||||||
Material|\
|
|
||||||
UV Image|\
|
|
||||||
Face Mode|\
|
|
||||||
Vertex Colours|\
|
|
||||||
UV Coordinates|\
|
|
||||||
Area|\
|
|
||||||
Edge Proportions|\
|
|
||||||
Normal Vector|\
|
|
||||||
Coplanar|')
|
|
||||||
|
|
||||||
if method != -1:
|
|
||||||
#================================================#
|
|
||||||
# Do we add, seb or set to the existing face sel #
|
|
||||||
#================================================#
|
|
||||||
faceOp = Draw.PupMenu(\
|
|
||||||
'Active Face Match%t|\
|
|
||||||
Add to Selection|\
|
|
||||||
Subtract From Selection |\
|
|
||||||
Overwrite Selection|\
|
|
||||||
Overwrite Selection Inverse|')
|
|
||||||
|
|
||||||
if faceOp != -1:
|
|
||||||
|
|
||||||
def setFSel(f):
|
|
||||||
if faceOp == 1 or faceOp == 3:
|
|
||||||
f.flag |= NMesh.FaceFlags['SELECT'] # will set selection
|
|
||||||
elif faceOp == 2 or faceOp ==4:
|
|
||||||
f.flag &=~NMesh.FaceFlags['SELECT'] # will unselect, note the '~' to invert bitflags
|
|
||||||
|
|
||||||
def setFUnSel(f):
|
|
||||||
if faceOp == 3:
|
|
||||||
f.flag &=~NMesh.FaceFlags['SELECT'] # will unselect, note the '~' to invert bitflags
|
|
||||||
elif faceOp == 4:
|
|
||||||
f.flag |= NMesh.FaceFlags['SELECT'] # will set selection
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#================#
|
|
||||||
# Math functions #
|
|
||||||
#================#
|
|
||||||
def compare(f1, f2, limit):
|
|
||||||
if f1 + limit > f2 and f1 - limit < f2:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def compare2(v1, v2, limit):
|
|
||||||
if v1[0] + limit > v2[0] and v1[0] - limit < v2[0]:
|
|
||||||
if v1[1] + limit > v2[1] and v1[1] - limit < v2[1]:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def compare3(v1, v2, limit):
|
|
||||||
if v1[0] + limit > v2[0] and v1[0] - limit < v2[0]:
|
|
||||||
if v1[1] + limit > v2[1] and v1[1] - limit < v2[1]:
|
|
||||||
if v1[2] + limit > v2[2] and v1[2] - limit < v2[2]:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def colCompare(v1, v2, limit):
|
|
||||||
# Simple test first
|
|
||||||
if v1.r == v2.r:
|
|
||||||
if v1.g == v2.g:
|
|
||||||
if v1.b == v2.b:
|
|
||||||
return 1
|
|
||||||
# Now a test that uses the limit.
|
|
||||||
limit = int(limit * 255)
|
|
||||||
if v1.r + limit >= v2.r and v1.r - limit <= v2.r:
|
|
||||||
if v1.g + limit >= v2.g and v1.g - limit <= v2.g:
|
|
||||||
if v1.b + limit >= v2.b and v1.b - limit <= v2.b:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# Makes sure face 2 has all the colours of face 1
|
|
||||||
def faceColCompare(f1, f2, limit):
|
|
||||||
avcolIdx = 0
|
|
||||||
while avcolIdx < len(f1.col):
|
|
||||||
match = 0
|
|
||||||
|
|
||||||
vcolIdx = 0
|
|
||||||
while vcolIdx < len(f2.col):
|
|
||||||
if colCompare(f1.col[avcolIdx], f2.col[vcolIdx], limit):
|
|
||||||
match = 1
|
|
||||||
break
|
|
||||||
vcolIdx += 1
|
|
||||||
if match == 0: # premature exit if a motch not found
|
|
||||||
return 0
|
|
||||||
avcolIdx += 1
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Makes sure face 2 has matching UVs within the limit.
|
|
||||||
def faceUvCompare(f1, f2, limit):
|
|
||||||
for auv in f1.uv:
|
|
||||||
match = 0
|
|
||||||
for uv in f2.uv:
|
|
||||||
if compare2(auv, uv, limit):
|
|
||||||
match = 1
|
|
||||||
break
|
|
||||||
if match == 0: # premature exit if a motch not found
|
|
||||||
return 0
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
def measure(v1, v2):
|
|
||||||
return Mathutils.Vector([v1[0]-v2[0], v1[1] - v2[1], v1[2] - v2[2]]).length
|
|
||||||
|
|
||||||
def triArea2D(v1, v2, v3):
|
|
||||||
e1 = measure(v1, v2)
|
|
||||||
e2 = measure(v2, v3)
|
|
||||||
e3 = measure(v3, v1)
|
|
||||||
p = e1+e2+e3
|
|
||||||
return 0.25 * sqrt(p*(p-2*e1)*(p-2*e2)*(p-2*e3))
|
|
||||||
#====================#
|
|
||||||
# End Math Functions #
|
|
||||||
#====================#
|
|
||||||
|
|
||||||
|
|
||||||
#=============================#
|
|
||||||
# Blender functions/shortcuts #
|
|
||||||
#=============================#
|
|
||||||
def getLimit(text):
|
|
||||||
return Draw.PupFloatInput(text, 0.1, 0.0, 1.0, 0.1, 3)
|
|
||||||
|
|
||||||
def faceArea(f):
|
|
||||||
if len(f.v) == 4:
|
|
||||||
return triArea2D(f.v[0].co, f.v[1].co, f.v[2].co) + triArea2D(f.v[0].co, f.v[2].co, f.v[3].co)
|
|
||||||
elif len(f.v) == 3:
|
|
||||||
return triArea2D(f.v[0].co, f.v[1].co, f.v[2].co)
|
|
||||||
|
|
||||||
def getEdgeLengths(f):
|
|
||||||
if len(f.v) == 4:
|
|
||||||
return (measure(f.v[0].co, f.v[1].co), measure(f.v[1].co, f.v[2].co), measure(f.v[2].co, f.v[3].co) , measure(f.v[3].co, f.v[0].co) )
|
|
||||||
elif len(f.v) == 3:
|
|
||||||
return (measure(f.v[0].co, f.v[1].co), measure(f.v[1].co, f.v[2].co), measure(f.v[2].co, f.v[0].co) )
|
|
||||||
|
|
||||||
def faceCent(f):
|
|
||||||
x = y = z = 0
|
|
||||||
for v in f.v:
|
|
||||||
x += v.co[0]
|
|
||||||
y += v.co[1]
|
|
||||||
z += v.co[2]
|
|
||||||
x = x/len(f.v)
|
|
||||||
y = y/len(f.v)
|
|
||||||
z = z/len(f.v)
|
|
||||||
return Vector([x, y, z])
|
|
||||||
|
|
||||||
#========================================#
|
|
||||||
# Should we bother computing this faces #
|
|
||||||
#========================================#
|
|
||||||
def fShouldCompare(f):
|
|
||||||
# Only calculate for faces that will be affected.
|
|
||||||
if len(f.v) < 3: # cant be an edge
|
|
||||||
return 0
|
|
||||||
elif faceOp == 1 and f.flag == 1:
|
|
||||||
return 0
|
|
||||||
elif faceOp == 0 and f.flag == 0:
|
|
||||||
return 0
|
|
||||||
elif f.flag == 64: # Ignore hidden
|
|
||||||
return 0
|
|
||||||
return 1
|
|
||||||
|
|
||||||
#=======================================#
|
|
||||||
# Sel same funcs as called by the menus #
|
|
||||||
#=======================================#
|
|
||||||
def get_same_mat():
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
if af.mat == f.mat: setFSel(f)
|
|
||||||
else: setFUnSel(f)
|
|
||||||
|
|
||||||
def get_same_image():
|
|
||||||
if mesh.hasFaceUV() == 0:
|
|
||||||
error('mesh has no uv image')
|
|
||||||
else:
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
if af.image == f.image: setFSel(f)
|
|
||||||
else: setFUnSel(f)
|
|
||||||
|
|
||||||
def get_same_mode():
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
if af.mode == f.mode: setFSel(f)
|
|
||||||
else: setFUnSel(f)
|
|
||||||
|
|
||||||
def get_same_vcol(limit):
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
if faceColCompare(f, af, limit) and faceColCompare(af, f, limit) :
|
|
||||||
setFSel(f)
|
|
||||||
else:
|
|
||||||
setFUnSel(f)
|
|
||||||
|
|
||||||
def get_same_uvco(limit):
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
if faceUvCompare(af, f, limit): setFSel(f)
|
|
||||||
else: setFUnSel(f)
|
|
||||||
|
|
||||||
def get_same_area(limit):
|
|
||||||
afArea = faceArea(af)
|
|
||||||
limit = limit * afArea # Make the lomot proportinal to the
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
if compare(afArea, faceArea(f), limit): setFSel(f)
|
|
||||||
else: setFUnSel(f)
|
|
||||||
|
|
||||||
def get_same_prop(limit):
|
|
||||||
# Here we get the perimeter and use it for a proportional limit modifier.
|
|
||||||
afEdgeLens = getEdgeLengths(af)
|
|
||||||
perim = 0
|
|
||||||
for e in afEdgeLens:
|
|
||||||
perim += e
|
|
||||||
|
|
||||||
limit = limit * perim
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
for ae in afEdgeLens:
|
|
||||||
match = 0
|
|
||||||
for e in getEdgeLengths(f):
|
|
||||||
if compare(ae, e, limit):
|
|
||||||
match = 1
|
|
||||||
break
|
|
||||||
if not match:
|
|
||||||
break
|
|
||||||
|
|
||||||
if match: setFSel(f)
|
|
||||||
else: setFUnSel(f)
|
|
||||||
|
|
||||||
def get_same_normal(limit):
|
|
||||||
limit = limit * 2
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
if compare3(af.no, f.no, limit): setFSel(f)
|
|
||||||
else: setFUnSel(f)
|
|
||||||
|
|
||||||
def get_same_coplaner(limit):
|
|
||||||
nlimit = limit * 2 # * 1 # limit for normal test
|
|
||||||
climit = limit * 3 # limit for coplaner test.
|
|
||||||
afCent = faceCent(af)
|
|
||||||
for f in mesh.faces:
|
|
||||||
if fShouldCompare(f):
|
|
||||||
match = 0
|
|
||||||
if compare3(af.no, f.no, nlimit):
|
|
||||||
fCent = faceCent(f)
|
|
||||||
if abs(DotVecs(Vector([af.no[0], af.no[1], af.no[2]]), afCent ) - DotVecs(Vector([af.no[0], af.no[1], af.no[2]]), fCent )) <= climit:
|
|
||||||
match = 1
|
|
||||||
if match:
|
|
||||||
setFSel(f)
|
|
||||||
else:
|
|
||||||
setFUnSel(f)
|
|
||||||
|
|
||||||
#=====================#
|
|
||||||
# End Sel same funcs #
|
|
||||||
#=====================#
|
|
||||||
limit = 1 # some of these dont use the limit so it needs to be set, to somthing.
|
|
||||||
# act on the menu item selected
|
|
||||||
if method == 1: # Material
|
|
||||||
get_same_mat()
|
|
||||||
elif method == 2: # UV Image
|
|
||||||
get_same_image()
|
|
||||||
elif method == 3: # mode
|
|
||||||
get_same_mode()
|
|
||||||
elif method == 4: # vertex colours
|
|
||||||
limit = getLimit('vert col limit: ')
|
|
||||||
if limit != None:
|
|
||||||
get_same_vcol(limit)
|
|
||||||
elif method == 5: # UV-coords
|
|
||||||
limit = getLimit('uv-coord limit: ')
|
|
||||||
if limit != None:
|
|
||||||
get_same_uvco(limit)
|
|
||||||
elif method == 6: # area
|
|
||||||
limit = getLimit('area limit: ')
|
|
||||||
if limit != None:
|
|
||||||
get_same_area(limit)
|
|
||||||
elif method == 7: # proportions
|
|
||||||
limit = getLimit('proportion limit: ')
|
|
||||||
if limit != None:
|
|
||||||
get_same_prop(limit)
|
|
||||||
elif method == 8: # normal
|
|
||||||
limit = getLimit('normal limit: ')
|
|
||||||
if limit != None:
|
|
||||||
get_same_normal(limit)
|
|
||||||
elif method == 9: # coplaner
|
|
||||||
limit = getLimit('coplanar limit: ')
|
|
||||||
if limit != None:
|
|
||||||
get_same_coplaner(limit)
|
|
||||||
|
|
||||||
# If limit is not set then dont bother
|
|
||||||
if limit != None:
|
|
||||||
mesh.update(0)
|
|
Loading…
Reference in New Issue
Block a user