Newer
Older
# ##### 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 #####
# Contributed to Germano Cavalcante (mano-wii), Florian Meyer (testscreenings),
# Brendon Murphy (meta-androcto),
# Maintainer: Vladimir Spivak (cwolf3d)
# Originally an addon by Bart Crouch
"author": "Bart Crouch, Vladimir Spivak (cwolf3d)",
Vladimir Spivak(cwolf3d)
committed
"version": (4, 7, 3),
"location": "View3D > Sidebar > Edit Tab / Edit Mode Context Menu",
"warning": "",
"description": "Mesh modelling toolkit. Several tools to aid modelling",
"doc_url": "{BLENDER_MANUAL_URL}/addons/mesh/looptools.html",
"category": "Mesh",
}
import bmesh
import bpy
import collections
import mathutils
import math
from bpy.types import (
Operator,
Menu,
Panel,
PropertyGroup,
AddonPreferences,
)
from bpy.props import (
BoolProperty,
EnumProperty,
FloatProperty,
IntProperty,
PointerProperty,
StringProperty,
)
# ########################################
# ##### General functions ################
# ########################################
# used by all tools to improve speed on reruns Unlink
looptools_cache = {}
def get_strokes(self, context):
looptools = context.window_manager.looptools
if looptools.gstretch_use_guide == "Annotation":
try:
strokes = bpy.data.grease_pencils[0].layers.active.active_frame.strokes
return True
except:
self.report({'WARNING'}, "active Annotation strokes not found")
return False
if looptools.gstretch_use_guide == "GPencil" and not looptools.gstretch_guide == None:
try:
strokes = looptools.gstretch_guide.data.layers.active.active_frame.strokes
return True
except:
self.report({'WARNING'}, "active GPencil strokes not found")
return False
else:
return False
beta-tester
committed
# force a full recalculation next time
def cache_delete(tool):
if tool in looptools_cache:
del looptools_cache[tool]
# check cache for stored information
def cache_read(tool, object, bm, input_method, boundaries):
# current tool not cached yet
if tool not in looptools_cache:
return(False, False, False, False, False)
# check if selected object didn't change
if object.name != looptools_cache[tool]["object"]:
return(False, False, False, False, False)
# check if input didn't change
if input_method != looptools_cache[tool]["input_method"]:
return(False, False, False, False, False)
if boundaries != looptools_cache[tool]["boundaries"]:
return(False, False, False, False, False)
modifiers = [mod.name for mod in object.modifiers if mod.show_viewport and
mod.type == 'MIRROR']
if modifiers != looptools_cache[tool]["modifiers"]:
return(False, False, False, False, False)
input = [v.index for v in bm.verts if v.select and not v.hide]
if input != looptools_cache[tool]["input"]:
return(False, False, False, False, False)
# reading values
single_loops = looptools_cache[tool]["single_loops"]
loops = looptools_cache[tool]["loops"]
derived = looptools_cache[tool]["derived"]
mapping = looptools_cache[tool]["mapping"]
CoDEmanX
committed
return(True, single_loops, loops, derived, mapping)
# store information in the cache
def cache_write(tool, object, bm, input_method, boundaries, single_loops,
loops, derived, mapping):
# clear cache of current tool
if tool in looptools_cache:
del looptools_cache[tool]
# prepare values to be saved to cache
input = [v.index for v in bm.verts if v.select and not v.hide]
modifiers = [mod.name for mod in object.modifiers if mod.show_viewport
and mod.type == 'MIRROR']
looptools_cache[tool] = {
"input": input, "object": object.name,
"input_method": input_method, "boundaries": boundaries,
"single_loops": single_loops, "loops": loops,
"derived": derived, "mapping": mapping, "modifiers": modifiers}
# calculates natural cubic splines through all given knots
def calculate_cubic_splines(bm_mod, tknots, knots):
# hack for circular loops
if knots[0] == knots[-1] and len(knots) > 1:
circular = True
k_new1 = []
for k in range(-1, -5, -1):
if k - 1 < -len(knots):
k += len(knots)
k_new2 = []
for k in range(4):
if k + 1 > len(knots) - 1:
k -= len(knots)
for k in k_new1:
knots.insert(0, k)
for k in k_new2:
knots.append(k)
t_new1 = []
total1 = 0
for t in range(-1, -5, -1):
if t - 1 < -len(tknots):
t += len(tknots)
total1 += tknots[t] - tknots[t - 1]
t_new1.append(tknots[0] - total1)
t_new2 = []
total2 = 0
for t in range(4):
if t + 1 > len(tknots) - 1:
t -= len(tknots)
total2 += tknots[t + 1] - tknots[t]
t_new2.append(tknots[-1] + total2)
for t in t_new1:
tknots.insert(0, t)
for t in t_new2:
tknots.append(t)
else:
circular = False
# end of hack
CoDEmanX
committed
n = len(knots)
if n < 2:
return False
x = tknots[:]
locs = [bm_mod.verts[k].co[:] for k in knots]
result = []
for j in range(3):
a = []
for i in locs:
a.append(i[j])
h = []
for i in range(n - 1):
if x[i + 1] - x[i] == 0:
h.append(1e-8)
else:
for i in range(1, n - 1):
q.append(3 / h[i] * (a[i + 1] - a[i]) - 3 / h[i - 1] * (a[i] - a[i - 1]))
l = [1.0]
u = [0.0]
z = [0.0]
Loading
Loading full blame...