Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <germano.costa@ig.com.br>2017-04-10 02:59:44 +0300
committerGermano Cavalcante <germano.costa@ig.com.br>2017-04-10 02:59:44 +0300
commitccfde7b1b8462f7e8a82f89b6dd075d0d4c6f2bd (patch)
tree4b049e3fdc2f8b2cef3d8f121ce270bf76905b66
parent08de0de45e902114a085a47e03fdfed95e24d994 (diff)
Snap Utilities Line: Calculate the nearest edges in a loop (instead of using the selection operator)
In addition to indentation and rearrangement of some functions
-rw-r--r--mesh_snap_utilities_line.py387
1 files changed, 215 insertions, 172 deletions
diff --git a/mesh_snap_utilities_line.py b/mesh_snap_utilities_line.py
index 749c5e1b..0079b8bc 100644
--- a/mesh_snap_utilities_line.py
+++ b/mesh_snap_utilities_line.py
@@ -55,15 +55,15 @@ from bpy.props import (
def get_units_info(scale, unit_system, separate_units):
if unit_system == 'METRIC':
- scale_steps = ((1000, 'km'), (1, 'm'), (1 / 100, 'cm'),
- (1 / 1000, 'mm'), (1 / 1000000, '\u00b5m'))
+ scale_steps = ((1000, 'km'), (1, 'm'), (1 / 100, 'cm'),
+ (1 / 1000, 'mm'), (1 / 1000000, '\u00b5m'))
elif unit_system == 'IMPERIAL':
- scale_steps = ((5280, 'mi'), (1, '\''),
- (1 / 12, '"'), (1 / 12000, 'thou'))
- scale /= 0.3048 # BU to feet
+ scale_steps = ((5280, 'mi'), (1, '\''),
+ (1 / 12, '"'), (1 / 12000, 'thou'))
+ scale /= 0.3048 # BU to feet
else:
- scale_steps = ((1, ' BU'),)
- separate_units = False
+ scale_steps = ((1, ' BU'),)
+ separate_units = False
return (scale, scale_steps, separate_units)
@@ -73,26 +73,27 @@ def convert_distance(val, units_info, precision=5):
sval = val * scale
idx = 0
while idx < len(scale_steps) - 1:
- if sval >= scale_steps[idx][0]:
- break
- idx += 1
+ if sval >= scale_steps[idx][0]:
+ break
+ idx += 1
factor, suffix = scale_steps[idx]
sval /= factor
if not separate_units or idx == len(scale_steps) - 1:
- dval = str(round(sval, precision)) + suffix
+ dval = str(round(sval, precision)) + suffix
else:
- ival = int(sval)
- dval = str(round(ival, precision)) + suffix
- fval = sval - ival
+ ival = int(sval)
+ dval = str(round(ival, precision)) + suffix
+ fval = sval - ival
+ idx += 1
+ while idx < len(scale_steps):
+ fval *= scale_steps[idx - 1][0] / scale_steps[idx][0]
+ if fval >= 1:
+ dval += ' ' \
+ + ("%.1f" % fval) \
+ + scale_steps[idx][1]
+ break
idx += 1
- while idx < len(scale_steps):
- fval *= scale_steps[idx - 1][0] / scale_steps[idx][0]
- if fval >= 1:
- dval += ' ' \
- + ("%.1f" % fval) \
- + scale_steps[idx][1]
- break
- idx += 1
+
return dval
@@ -166,6 +167,38 @@ def out_Location(rv3d, region, orig, vector):
return hit
+def get_closest_edge(bm, point, dist):
+ r_edge = None
+ for edge in bm.edges:
+ v1 = edge.verts[0].co
+ v2 = edge.verts[1].co
+ # Test the BVH (AABB) first
+ for i in range(3):
+ if v1[i] <= v2[i]:
+ isect = v1[i] - dist <= point[i] <= v2[i] + dist
+ else:
+ isect = v2[i] - dist <= point[i] <= v1[i] + dist
+
+ if not isect:
+ break
+ else:
+ ret = intersect_point_line(point, v1, v2)
+
+ if ret[1] < 0.0:
+ tmp = v1
+ elif ret[1] > 1.0:
+ tmp = v2
+ else:
+ tmp = ret[0]
+
+ new_dist = (point - tmp).length
+ if new_dist <= dist:
+ dist = new_dist
+ r_edge = edge
+
+ return r_edge
+
+
class SnapCache():
bvert = None
vco = None
@@ -242,11 +275,11 @@ def snap_utilities(
cache.v2dmid = location_3d_to_region_2d(region, rv3d, cache.vmid)
if previous_vert and previous_vert not in bm_geom.verts:
- pvert_co = obj_matrix_world * previous_vert.co
- perp_point = intersect_point_line(pvert_co, cache.v0, cache.v1)
- cache.vperp = perp_point[0]
- # factor = point_perpendicular[1]
- cache.v2dperp = location_3d_to_region_2d(region, rv3d, perp_point[0])
+ pvert_co = obj_matrix_world * previous_vert.co
+ perp_point = intersect_point_line(pvert_co, cache.v0, cache.v1)
+ cache.vperp = perp_point[0]
+ # factor = point_perpendicular[1]
+ cache.v2dperp = location_3d_to_region_2d(region, rv3d, perp_point[0])
# else: cache.v2dperp = None
@@ -273,9 +306,8 @@ def snap_utilities(
is_increment = True
r_type = 'EDGE'
- fac = fac_nearest_to_segment_2d(mcursor, cache.v2d0, cache.v2d1)
- fac *= cache.v2d0.z / cache.v2d1.z # convert to fac3d
- r_loc = cache.v0 + fac * (cache.v1 - cache.v0)
+ orig, view_vector = region_2d_to_orig_and_view_vector(region, rv3d, mcursor)
+ r_loc = intersect_line_line(cache.v0, cache.v1, orig, orig + view_vector)[0]
elif isinstance(bm_geom, bmesh.types.BMFace):
is_increment = True
@@ -284,7 +316,7 @@ def snap_utilities(
if cache.bface != bm_geom:
cache.bface = bm_geom
cache.fmid = obj_matrix_world * bm_geom.calc_center_median()
- cache.fnor = bm_geom.normal * obj_matrix_world.inverted()
+ cache.fnor = bm_geom.normal * obj_matrix_world
orig, view_vector = region_2d_to_orig_and_view_vector(region, rv3d, mcursor)
end = orig + view_vector
@@ -302,6 +334,9 @@ def snap_utilities(
face_index = -1
if cache.out_obj is None:
+ ## TODO: The Scene.raycast also tests the edited object.
+ # This is highly inefficient because the edited object
+ # does not keep DerivedMesh which forces rebuilding the bvhtree.
result, r_loc, normal, face_index, cache.out_obj, cache.out_obmat = scene.ray_cast(orig, view_vector)
if result:
r_type = 'FACE'
@@ -354,7 +389,7 @@ def snap_utilities(
is_increment = False
r_loc = intersect_point_line(r_loc, constrain[0], constrain[1])[0]
else:
- r_loc = intersect_line_line(constrain[0], constrain[1], orig, end)[0]
+ r_loc = intersect_line_line(constrain[0], constrain[1], orig, orig + view_vector)[0]
elif not r_loc:
r_loc = out_Location(rv3d, region, orig, view_vector)
@@ -371,117 +406,153 @@ def snap_utilities(
return r_loc, r_type, bm_geom, r_len
-def get_isolated_edges(bmvert):
+def get_loose_linked_edges(bmvert):
linked = [e for e in bmvert.link_edges if not e.link_faces]
for e in linked:
linked += [le for v in e.verts if not v.link_faces for le in v.link_edges if le not in linked]
return linked
-def draw_line(self, obj, Bmesh, bm_geom, location):
+def draw_line(self, obj, bm, bm_geom, location):
if not hasattr(self, 'list_verts'):
self.list_verts = []
if not hasattr(self, 'list_edges'):
self.list_edges = []
- if not hasattr(self, 'list_faces'):
- self.list_faces = []
+ update_edit_mesh = False
+ tessface = False
if bm_geom is None:
- vertices = (bmesh.ops.create_vert(Bmesh, co=(location)))
- self.list_verts.append(vertices['vert'][0])
+ vert = bm.verts.new(location)
+ self.list_verts.append(vert)
elif isinstance(bm_geom, bmesh.types.BMVert):
- if (bm_geom.co - location).length < .01:
+ if (bm_geom.co - location).length_squared < .001:
if self.list_verts == [] or self.list_verts[-1] != bm_geom:
self.list_verts.append(bm_geom)
else:
- vertices = bmesh.ops.create_vert(Bmesh, co=(location))
- self.list_verts.append(vertices['vert'][0])
+ vert = bm.verts.new(location)
+ self.list_verts.append(vert)
elif isinstance(bm_geom, bmesh.types.BMEdge):
self.list_edges.append(bm_geom)
- vector_p0_l = (bm_geom.verts[0].co - location)
- vector_p1_l = (bm_geom.verts[1].co - location)
- cross = vector_p0_l.cross(vector_p1_l) / bm_geom.calc_length()
+ ret = intersect_point_line(location, bm_geom.verts[0].co, bm_geom.verts[1].co)
- if cross < Vector((0.001, 0, 0)): # or round(vector_p0_l.angle(vector_p1_l), 2) == 3.14:
- factor = vector_p0_l.length / bm_geom.calc_length()
- vertex0 = bmesh.utils.edge_split(bm_geom, bm_geom.verts[0], factor)
- self.list_verts.append(vertex0[1])
- # self.list_edges.append(vertex0[0])
+ if (ret[0] - location).length_squared < .001:
+ if ret[1] == 0.0:
+ vert = bm_geom.verts[0]
+ elif ret[1] == 1.0:
+ vert = bm_geom.verts[1]
+ else:
+ edge, vert = bmesh.utils.edge_split(bm_geom, bm_geom.verts[0], ret[1])
+ self.list_verts.append(vert)
+ # self.list_edges.append(edge)
else: # constrain point is near
- vertices = bmesh.ops.create_vert(Bmesh, co=(location))
- self.list_verts.append(vertices['vert'][0])
+ vert = bm.verts.new(location)
+ self.list_verts.append(vert)
elif isinstance(bm_geom, bmesh.types.BMFace):
self.list_faces.append(bm_geom)
- vertices = (bmesh.ops.create_vert(Bmesh, co=(location)))
- self.list_verts.append(vertices['vert'][0])
+ vert = bm.verts.new(location)
+ self.list_verts.append(vert)
# draw, split and create face
if len(self.list_verts) >= 2:
- V1 = self.list_verts[-2]
- V2 = self.list_verts[-1]
- # V2_link_verts = [x for y in [a.verts for a in V2.link_edges] for x in y if x != V2]
- for edge in V2.link_edges:
- if V1 in edge.verts:
+ v1, v2 = self.list_verts[-2:]
+ # v2_link_verts = [x for y in [a.verts for a in v2.link_edges] for x in y if x != v2]
+ for edge in v2.link_edges:
+ if v1 in edge.verts:
self.list_edges.append(edge)
break
- else: # if V1 not in V2_link_verts:
- if not V2.link_edges:
- edge = Bmesh.edges.new([V1, V2])
+ else: # if v1 not in v2_link_verts:
+ if not v2.link_edges:
+ edge = bm.edges.new([v1, v2])
self.list_edges.append(edge)
- else:
- link_two_faces = V1.link_faces and V2.link_faces
- if link_two_faces:
- self.list_faces = [f for f in V2.link_faces if f in V1.link_faces]
+ else: # split face
+ if v1.link_faces and v2.link_faces:
+ split_faces = {f for f in v2.link_faces if f in v1.link_faces}
+
+ else:
+ split_faces = set()
+ if v1.link_faces:
+ faces = v1.link_faces
+ co2 = v2.co.copy()
+ else:
+ faces = v2.link_faces
+ co2 = v1.co.copy()
- elif not self.list_faces:
- faces, co2 = (V1.link_faces, V2.co.copy()) if V1.link_faces else (V2.link_faces, V1.co.copy())
for face in faces:
if bmesh.geometry.intersect_face_point(face, co2):
co = co2 - face.calc_center_median()
if co.dot(face.normal) < 0.001:
- self.list_faces.append(face)
+ split_faces.add(face)
- if self.list_faces:
- edge = Bmesh.edges.new([V1, V2])
+ if split_faces:
+ edge = bm.edges.new([v1, v2])
self.list_edges.append(edge)
- ed_list = get_isolated_edges(V2)
- for face in set(self.list_faces):
- facesp = bmesh.utils.face_split_edgenet(face, list(set(ed_list)))
- self.list_faces = []
+ ed_list = get_loose_linked_edges(v2)
+ for face in split_faces:
+ facesp = bmesh.utils.face_split_edgenet(face, ed_list)
+ del split_faces
+ update_edit_mesh = True
+ tessface = True
else:
if self.intersect:
- facesp = bmesh.ops.connect_vert_pair(Bmesh, verts=[V1, V2], verts_exclude=Bmesh.verts)
+ facesp = bmesh.ops.connect_vert_pair(bm, verts=[v1, v2], verts_exclude=bm.verts)
# print(facesp)
if not self.intersect or not facesp['edges']:
- edge = Bmesh.edges.new([V1, V2])
+ edge = bm.edges.new([v1, v2])
self.list_edges.append(edge)
else:
for edge in facesp['edges']:
self.list_edges.append(edge)
- bmesh.update_edit_mesh(obj.data, tessface=True, destructive=True)
# create face
if self.create_face:
- ed_list = self.list_edges.copy()
- for edge in V2.link_edges:
+ ed_list = set(self.list_edges)
+ for edge in v2.link_edges:
for vert in edge.verts:
- if vert in self.list_verts:
- ed_list.append(edge)
- for edge in get_isolated_edges(V2):
- if edge not in ed_list:
- ed_list.append(edge)
- bmesh.ops.edgenet_fill(Bmesh, edges=list(set(ed_list)))
- bmesh.update_edit_mesh(obj.data, tessface=True, destructive=True)
+ if vert != v2 and vert in self.list_verts:
+ ed_list.add(edge)
break
+ else:
+ continue
+ # Inner loop was broken, break the outer
+ break
+
+ ed_list.update(get_loose_linked_edges(v2))
+
+ bmesh.ops.edgenet_fill(bm, edges=list(ed_list))
+ update_edit_mesh = True
+ tessface = True
# print('face created')
+ if update_edit_mesh:
+ bmesh.update_edit_mesh(obj.data, tessface = tessface, destructive=True)
+ return [obj.matrix_world * v.co for v in self.list_verts]
- return [obj.matrix_world * a.co for a in self.list_verts]
+
+class NavigationKeys:
+ def __init__(self, context):
+ # TO DO:
+ # 'View Orbit', 'View Pan', 'NDOF Orbit View', 'NDOF Pan View'
+ self._rotate = set()
+ self._move = set()
+ self._zoom = set()
+ for key in context.window_manager.keyconfigs.user.keymaps['3D View'].keymap_items:
+ if key.idname == 'view3d.rotate':
+ #self.keys_rotate[key.id]={'Alt': key.alt, 'Ctrl': key.ctrl, 'Shift':key.shift, 'Type':key.type, 'Value':key.value}
+ self._rotate.add((key.alt, key.ctrl, key.shift, key.type, key.value))
+ if key.idname == 'view3d.move':
+ self._move.add((key.alt, key.ctrl, key.shift, key.type, key.value))
+ if key.idname == 'view3d.zoom':
+ if key.type == 'WHEELINMOUSE':
+ self._zoom.add((key.alt, key.ctrl, key.shift, 'WHEELUPMOUSE', key.value, key.properties.delta))
+ elif key.type == 'WHEELOUTMOUSE':
+ self._zoom.add((key.alt, key.ctrl, key.shift, 'WHEELDOWNMOUSE', key.value, key.properties.delta))
+ else:
+ self._zoom.add((key.alt, key.ctrl, key.shift, key.type, key.value, key.properties.delta))
class CharMap:
@@ -542,62 +613,13 @@ class SnapUtilitiesLine(Operator):
(context.object is not None and
context.object.type == 'MESH'))
- def modal_navigation(self, context, event):
- # TO DO:
- # 'View Orbit', 'View Pan', 'NDOF Orbit View', 'NDOF Pan View'
- rv3d = context.region_data
- if not hasattr(self, 'navigation_cache'): # or self.navigation_cache == False:
- # print('update navigation')
- self.navigation_cache = True
- self.keys_rotate = set()
- self.keys_move = set()
- self.keys_zoom = set()
- for key in context.window_manager.keyconfigs.user.keymaps['3D View'].keymap_items:
- if key.idname == 'view3d.rotate':
- # self.keys_rotate[key.id] = {'Alt': key.alt, 'Ctrl': key.ctrl,
- # 'Shift':key.shift, 'Type':key.type, 'Value':key.value}
- self.keys_rotate.add((key.alt, key.ctrl, key.shift, key.type, key.value))
- if key.idname == 'view3d.move':
- self.keys_move.add((key.alt, key.ctrl, key.shift, key.type, key.value))
- if key.idname == 'view3d.zoom':
- self.keys_zoom.add(
- (key.alt, key.ctrl, key.shift, key.type,
- key.value, key.properties.delta)
- )
- if key.type == 'WHEELINMOUSE':
- self.keys_zoom.add(
- (key.alt, key.ctrl, key.shift, 'WHEELDOWNMOUSE',
- key.value, key.properties.delta)
- )
- if key.type == 'WHEELOUTMOUSE':
- self.keys_zoom.add(
- (key.alt, key.ctrl, key.shift, 'WHEELUPMOUSE',
- key.value, key.properties.delta)
- )
-
- evkey = (event.alt, event.ctrl, event.shift, event.type, event.value)
- if evkey in self.keys_rotate:
- bpy.ops.view3d.rotate('INVOKE_DEFAULT')
- elif evkey in self.keys_move:
- if event.shift and self.vector_constrain and \
- self.vector_constrain[2] in {'RIGHT_SHIFT', 'LEFT_SHIFT', 'shift'}:
- self.vector_constrain = None
- bpy.ops.view3d.move('INVOKE_DEFAULT')
- else:
- for key in self.keys_zoom:
- if evkey == key[0:5]:
- delta = key[5]
- if delta == 0:
- bpy.ops.view3d.zoom('INVOKE_DEFAULT')
- else:
- rv3d.view_distance += delta * rv3d.view_distance / 6
- rv3d.view_location -= delta * (self.location - rv3d.view_location) / 6
- break
def draw_callback_px(self, context):
# draw 3d point OpenGL in the 3D View
bgl.glEnable(bgl.GL_BLEND)
bgl.glDisable(bgl.GL_DEPTH_TEST)
+ # bgl.glPushMatrix()
+ # bgl.glMultMatrixf(self.obj_glmatrix)
if self.vector_constrain:
vc = self.vector_constrain
@@ -628,6 +650,8 @@ class SnapUtilitiesLine(Operator):
Color4f = self.center_color
elif self.type == 'PERPENDICULAR':
Color4f = self.perpendicular_color
+ else: # self.type == None
+ Color4f = self.out_color
bgl.glColor4f(*Color4f)
bgl.glPointSize(10)
@@ -648,6 +672,7 @@ class SnapUtilitiesLine(Operator):
bgl.glEnd()
# restore opengl defaults
+ # bgl.glPopMatrix()
bgl.glDepthRange(0, 1)
bgl.glPointSize(1)
bgl.glLineWidth(1)
@@ -655,6 +680,32 @@ class SnapUtilitiesLine(Operator):
bgl.glDisable(bgl.GL_LINE_STIPPLE)
bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+
+ def modal_navigation(self, context, event):
+ evkey = (event.alt, event.ctrl, event.shift, event.type, event.value)
+ if evkey in self.navigation_keys._rotate:
+ bpy.ops.view3d.rotate('INVOKE_DEFAULT')
+ elif evkey in self.navigation_keys._move:
+ if event.shift and self.vector_constrain and \
+ self.vector_constrain[2] in {'RIGHT_SHIFT', 'LEFT_SHIFT', 'shift'}:
+ self.vector_constrain = None
+ bpy.ops.view3d.move('INVOKE_DEFAULT')
+ else:
+ for key in self.navigation_keys._zoom:
+ if evkey == key[0:5]:
+ if True: # TODO: Use Zoom to mouse position
+ v3d = context.space_data
+ dist_range = (v3d.clip_start, v3d.clip_end)
+ rv3d = context.region_data
+ if (key[5] < 0 and rv3d.view_distance < dist_range[1]) or\
+ (key[5] > 0 and rv3d.view_distance > dist_range[0]):
+ rv3d.view_location += key[5] * (self.location - rv3d.view_location) / 6
+ rv3d.view_distance -= key[5] * rv3d.view_distance / 6
+ else:
+ bpy.ops.view3d.zoom('INVOKE_DEFAULT', delta = key[5])
+ break
+
+
def modal(self, context, event):
context.area.tag_redraw()
@@ -680,18 +731,12 @@ class SnapUtilitiesLine(Operator):
mval = Vector((event.mouse_region_x, event.mouse_region_y))
- if self.list_verts != []:
- previous_vert = self.list_verts[-1]
- else:
- previous_vert = None
-
- outer_verts = self.outer_verts and not self.keytab # is this used?
self.location, self.type, self.geom, self.len = snap_utilities(
self.cache, context, self.obj_matrix,
self.bm, mval,
- outer_verts=self.outer_verts,
+ outer_verts=(self.outer_verts and not self.keytab),
constrain=self.vector_constrain,
- previous_vert=previous_vert,
+ previous_vert=(self.list_verts[-1] if self.list_verts else None),
ignore_obj=self.obj,
increment=self.incremental
)
@@ -749,20 +794,15 @@ class SnapUtilitiesLine(Operator):
self.vector_constrain = [loc, loc + self.constrain_keys[event.type]] + [event.type]
elif event.type == 'LEFTMOUSE':
- # SNAP 2D
- snap_3d = self.location
- Lsnap_3d = self.obj_matrix.inverted() * snap_3d
- Snap_2d = location_3d_to_region_2d(self.region, self.rv3d, snap_3d)
- if self.vector_constrain and isinstance(self.geom, bmesh.types.BMVert): # SELECT FIRST
- bpy.ops.view3d.select(location=(int(Snap_2d[0]), int(Snap_2d[1])))
- try:
- geom2 = self.bm.select_history[0]
- except: # IndexError or AttributeError:
- geom2 = None
+ point = self.obj_matinv * self.location
+ # with constraint the intersection can be in a different element of the selected one
+ if self.vector_constrain and self.geom:
+ geom2 = get_closest_edge(self.bm, point, .001)
else:
geom2 = self.geom
+
self.vector_constrain = None
- self.list_verts_co = draw_line(self, self.obj, self.bm, geom2, Lsnap_3d)
+ self.list_verts_co = draw_line(self, self.obj, self.bm, geom2, point)
bpy.ops.ed.undo_push(message="Undo draw line*")
elif event.type == 'TAB':
@@ -783,7 +823,7 @@ class SnapUtilitiesLine(Operator):
text_value = bpy.utils.units.to_value(self.unit_system, 'LENGTH', self.length_entered)
vector = (self.location - self.list_verts_co[-1]).normalized()
location = (self.list_verts_co[-1] + (vector * text_value))
- G_location = self.obj_matrix.inverted() * location
+ G_location = self.obj_matinv * location
self.list_verts_co = draw_line(self, self.obj, self.bm, self.geom, G_location)
self.length_entered = ""
self.vector_constrain = None
@@ -865,6 +905,8 @@ class SnapUtilitiesLine(Operator):
self.rotMat = self.rv3d.view_matrix.copy()
self.obj = bpy.context.active_object
self.obj_matrix = self.obj.matrix_world.copy()
+ self.obj_matinv = self.obj_matrix.inverted()
+ # self.obj_glmatrix = bgl.Buffer(bgl.GL_FLOAT, [4, 4], self.obj_matrix.transposed())
self.bm = bmesh.from_edit_mesh(self.obj.data)
self.cache = SnapCache()
@@ -873,6 +915,7 @@ class SnapUtilitiesLine(Operator):
self.list_verts_co = []
self.bool_update = False
self.vector_constrain = ()
+ self.navigation_keys = NavigationKeys(context)
self.keytab = False
self.keyf8 = False
self.type = 'OUT'
@@ -957,14 +1000,15 @@ panels = (
def update_panel(self, context):
message = "Snap Utilities Line: Updating Panel locations has failed"
+ addon_prefs = context.user_preferences.addons[__name__].preferences
try:
for panel in panels:
- if "bl_rna" in panel.__dict__:
- bpy.utils.unregister_class(panel)
+ if addon_prefs.category != panel.bl_category:
+ if "bl_rna" in panel.__dict__:
+ bpy.utils.unregister_class(panel)
- for panel in panels:
- panel.bl_category = context.user_preferences.addons[__name__].preferences.category
- bpy.utils.register_class(panel)
+ panel.bl_category = addon_prefs.category
+ bpy.utils.register_class(panel)
except Exception as e:
print("\n[{}]\n{}\n\nError:\n{}".format(__name__, message, e))
@@ -1004,7 +1048,7 @@ class SnapAddonPreferences(AddonPreferences):
default=False
)
expand_color_settings = BoolProperty(
- name="Expand Color Settings",
+ name="Color Settings",
description="Expand, to display the color settings",
default=False
)
@@ -1087,11 +1131,11 @@ class SnapAddonPreferences(AddonPreferences):
def draw(self, context):
layout = self.layout
+ icon = "TRIA_DOWN" if self.expand_color_settings else "TRIA_RIGHT"
box = layout.box()
- box.prop(self, "expand_color_settings", toggle=True, emboss=False)
+ box.prop(self, "expand_color_settings", icon=icon, toggle=True, emboss=False)
if self.expand_color_settings:
- box.label(text="Snap Colors:")
split = box.split()
col = split.column()
@@ -1104,7 +1148,6 @@ class SnapAddonPreferences(AddonPreferences):
col.prop(self, "edge_color")
col.prop(self, "perpendicular_color")
col = split.column()
- col.scale_y = 1.5
col.prop(self, "vert_color")
row = layout.row()
@@ -1113,8 +1156,8 @@ class SnapAddonPreferences(AddonPreferences):
box = col.box()
box.label(text="Snap Items:")
box.prop(self, "incremental")
- box.prop(self, "outer_verts", toggle=True)
- box.prop(self, "increments_grid", toggle=True)
+ box.prop(self, "outer_verts")
+ box.prop(self, "increments_grid")
if self.increments_grid:
box.prop(self, "relative_scale")
else:
@@ -1124,9 +1167,9 @@ class SnapAddonPreferences(AddonPreferences):
col = row.column(align=True)
box = col.box()
box.label(text="Line Tool:")
- box.prop(self, "intersect", toggle=True)
- box.prop(self, "create_face", toggle=True)
- box.prop(self, "create_new_obj", toggle=True)
+ box.prop(self, "intersect")
+ box.prop(self, "create_face")
+ box.prop(self, "create_new_obj")
box.separator()
box.separator()