Skip to content

Commit

Permalink
Blender3.0にて、多角形面にナイフツールを使用すると、失敗する問題を修正しました。
Browse files Browse the repository at this point in the history
Blender3.0にて、Shift押しのサイクル選択での、メッシュのリラックス・一括移動・一括削除が失敗する問題を修正しました。
(Blender3.0の仕様変更が原因)
  • Loading branch information
bookyakuno committed Sep 27, 2022
1 parent 5ed6c9a commit a66de00
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 118 deletions.
66 changes: 36 additions & 30 deletions Addons/PolyQuilt/QMesh/QMeshOperators.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def ensure_lookup_table( self ) :
# ensure系は一応ダーティフラグチェックしてるので無暗に呼んでいいっぽい?
self.bm.faces.ensure_lookup_table()
self.bm.verts.ensure_lookup_table()
self.bm.edges.ensure_lookup_table()
self.bm.edges.ensure_lookup_table()

def reload_obj( self , context ) :
self.obj = context.active_object
Expand All @@ -62,7 +62,7 @@ def reload_obj( self , context ) :
self.mesh = None
self.bm = None
self.current_matrix = None
self.reload_tree()
self.reload_tree()

def reload_tree( self ) :
if self.__btree :
Expand All @@ -84,7 +84,7 @@ def UpdateMesh( self ) :
# self.obj.update_from_editmode()
self.__btree = None
self.__kdtree = None
self.current_matrix = None
self.current_matrix = None

@property
def btree(self):
Expand All @@ -103,7 +103,7 @@ def kdtree(self):
return self.__kdtree

@property
def verts(self):
def verts(self):
return self.bm.verts

@property
Expand Down Expand Up @@ -159,7 +159,7 @@ def is_x_zero_pos( pos : Vector ) :
return abs(pos[0]) < dist

def is_x_zero_pos_w2l( self , pos : Vector ) :
wp = self.world_to_local_pos(pos)
wp = self.world_to_local_pos(pos)
dist = bpy.context.scene.tool_settings.double_threshold
return abs(wp[0]) < dist

Expand All @@ -177,7 +177,7 @@ def is_x0_snap( self , p : Vector ) :
p1 = pqutil.location_3d_to_region_2d( self.mirror_pos_w2l(p) )
if p0 == None or p1 == None :
return False
dist = self.preferences.distance_to_highlight * dpm()
dist = self.preferences.distance_to_highlight * dpm()
return ( p0 - p1 ).length <= dist

def mirror_world_pos( self , world_pos ) :
Expand All @@ -193,11 +193,11 @@ def check_near( self , v0 , v1 ) :
if v0 == None or v1 == None :
return False
c0 = pqutil.location_3d_to_region_2d( self.obj.matrix_world @ v0 )
c1 = pqutil.location_3d_to_region_2d( self.obj.matrix_world @ v1 )
c1 = pqutil.location_3d_to_region_2d( self.obj.matrix_world @ v1 )
if c0 == None or c1 == None :
return False
radius = self.preferences.distance_to_highlight * dpm()
return (c0-c1).length <= radius
return (c0-c1).length <= radius


def AddVertex( self , local_pos : Vector , is_mirror = None ) :
Expand Down Expand Up @@ -227,16 +227,16 @@ def AddFace( self , verts , normal = None , is_mirror = None ) :

if linkCount > 0 :
face.normal_flip()
face.normal_update()
face.normal_update()
isLink = True

if linkCount == 0 and normal != None :
face.normal_update()
dp = face.normal.dot( self.obj.matrix_world.inverted().to_3x3() @ normal )
if dp > 0.0 :
face.normal_flip()
face.normal_update()
verts = verts[::-1]
face.normal_update()
verts = verts[::-1]

if self.check_mirror(is_mirror) :
mirror = [ self.find_mirror(v,False) for v in verts[::-1] ]
Expand All @@ -250,7 +250,7 @@ def AddFace( self , verts , normal = None , is_mirror = None ) :
return face

def add_edge( self , v0 , v1 , is_mirror = None ) :
edge = self.bm.edges.get( (v0,v1) )
edge = self.bm.edges.get( (v0,v1) )
if edge is None :
edge = self.bm.edges.new( (v0,v1) )

Expand Down Expand Up @@ -306,8 +306,8 @@ def dissolve_vert( self , vert , use_verts = False , use_face_split = False , u
verts = [vert,mirror]

other_verts = set()
for vt in verts :
for e in vt.link_edges :
for vt in verts :
for e in vt.link_edges :
ov = e.other_vert(vt)
if ov not in verts and len(ov.link_edges) > 2 :
other_verts.add( ov )
Expand Down Expand Up @@ -355,13 +355,13 @@ def calc_limit_verts( self , verts , dissolve_vert_angle = 180 , is_mirror = No
if self.check_mirror(is_mirror) :
mirror = self.find_mirror( vert )
if mirror != None :
removes.add(mirror)
removes.add(mirror)
return list(removes)


def dissolve_limit_verts( self , verts , dissolve_vert_angle = 180 , is_mirror = None ) :
removes = self.calc_limit_verts(verts , dissolve_vert_angle , is_mirror = None)
if removes :
if removes :
bmesh.ops.dissolve_verts( self.bm , verts = removes , use_face_split = False , use_boundary_tear = False )

def dissolve_faces( self , fades , use_verts = False ) :
Expand All @@ -377,13 +377,19 @@ def face_split( self , face , v0 , v1 , coords = () , use_exist=True, example=No
if (mirror_v0 == v0 and mirror_v1 == v1) or (mirror_v0 == v1 and mirror_v1 == v0) :
pass
else :
new_face , new_edge = bmesh.utils.face_split( mirror_face , mirror_v0 , mirror_v1 , coords = coords , use_exist = use_exist )
if bpy.app.version >= (3,0,0):
new_face , new_edge = bmesh.utils.face_split( mirror_face , mirror_v0 , mirror_v1)
else:
new_face , new_edge = bmesh.utils.face_split( mirror_face , mirror_v0 , mirror_v1 , coords , use_exist )
if (v0 not in face.verts or v1 not in face.verts ) and (v0 not in new_face.verts or v1 not in new_face.verts ):
return
if v0 in new_face.verts and v1 in new_face.verts :
return bmesh.utils.face_split( new_face , v0 , v1 )

return bmesh.utils.face_split( face , v0 , v1 , coords = coords , use_exist = use_exist )

if bpy.app.version >= (3,0,0):
return bmesh.utils.face_split( face , v0 , v1)
else:
return bmesh.utils.face_split( face , v0 , v1 , coords , use_exist )

def __calc_split_fac( self , edge , refPos ) :
fac = 0.5
Expand Down Expand Up @@ -413,9 +419,9 @@ def edge_split_from_position( self , edge , refPos , is_mirror = None):
def weld( self , targetmap ) :
bmesh.ops.weld_verts(self.bm,targetmap)

def set_positon( self , geom , pos , is_world = True ) :
def set_positon( self , geom , pos , is_world = True ) :
if is_world :
pos = self.obj.matrix_world.inverted() @ pos
pos = self.obj.matrix_world.inverted() @ pos
geom.co = pos

def test_mirror( self , v0 , v1 ) :
Expand Down Expand Up @@ -449,10 +455,10 @@ def find_mirror( self , geom , check_same = True ) :

if hits != None :
if len(hits) == 1 :
result = self.bm.verts[hits[0][1]]
result = self.bm.verts[hits[0][1]]
elif len(hits) > 0 :
hits = sorted( hits , key=lambda x:x[2])
result = self.bm.verts[ hits[0][1] ]
result = self.bm.verts[ hits[0][1] ]
for h in hits :
hitV = self.bm.verts[h[1]]
for edge in geom.link_edges :
Expand All @@ -467,7 +473,7 @@ def find_mirror( self , geom , check_same = True ) :
hits = self.kdtree.find_range(mirror_cos[0], dist )
if hits != None :
for hit in hits :
hitvert = self.bm.verts[hit[1]]
hitvert = self.bm.verts[hit[1]]
links = hitvert.link_edges if isinstance( geom , bmesh.types.BMEdge ) else hitvert.link_faces
for link in links :
if self.test_mirror_geom( link , geom ) :
Expand All @@ -486,7 +492,7 @@ def find_near( self , pos : mathutils.Vector , is_mirror = None ) :
threshold = bpy.context.scene.tool_settings.double_threshold
hits = set()

ipos = self.obj.matrix_world.inverted() @ pos
ipos = self.obj.matrix_world.inverted() @ pos
pts = self.kdtree.find_range( ipos , threshold )
if pts :
hits = set([ self.bm.verts[i] for p , i ,d in pts ])
Expand All @@ -495,7 +501,7 @@ def find_near( self , pos : mathutils.Vector , is_mirror = None ) :
mpos = self.obj.matrix_world.inverted() @ pos
mpos.x = -mpos.x
mpts = self.kdtree.find_range( mpos , threshold )
if mpts :
if mpts :
mhits = set([ self.bm.verts[i] for p , i ,d in mpts ])
return mhits | hits

Expand Down Expand Up @@ -590,10 +596,10 @@ def append( lst , geom ) :
return edges , verts

def do_edge_loop_cut( self , edges , verts ) :
bmesh.ops.dissolve_edges( self.bm , edges = edges , use_verts = False , use_face_split = False )
bmesh.ops.dissolve_edges( self.bm , edges = edges , use_verts = False , use_face_split = False )
vs = [ v for v in verts if v.is_valid ]
bmesh.ops.dissolve_verts( self.bm , verts = vs , use_face_split = True , use_boundary_tear = False )
bmesh.ops.dissolve_verts( self.bm , verts = vs , use_face_split = True , use_boundary_tear = False )


@staticmethod
def calc_loop_face( edge ) :
Expand Down Expand Up @@ -626,7 +632,7 @@ def step( edge ) :


def calc_shortest_pass( self , bm , start , end ) :
from .QMesh import SelectStack
from .QMesh import SelectStack

if isinstance( start , bmesh.types.BMFace ) :
for edge in start.edges :
Expand Down
10 changes: 5 additions & 5 deletions Addons/PolyQuilt/QMesh/QSnap.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def add_ref( cls , context ) :
cls.ref = cls.ref + 1

@classmethod
def remove_ref( cls ) :
def remove_ref( cls ) :
cls.ref = cls.ref - 1
if cls.ref == 0 :
if cls.instance :
Expand Down Expand Up @@ -69,7 +69,7 @@ def __update( self , context ) :

@staticmethod
def snap_objects( context ) :
active_obj = context.active_object
active_obj = context.active_object
objects = context.visible_objects
# objects = context.selected_objects
objects_array = [obj for obj in objects if obj != active_obj and obj.type == 'MESH']
Expand Down Expand Up @@ -133,7 +133,7 @@ def adjust_local_to_world( cls , matrix_world : mathutils.Matrix , local_pos : m
@classmethod
def adjust_verts( cls , obj , verts , is_fix_to_x_zero ) :
if cls.instance != None and cls.instance.bvh_list :
dist = bpy.context.scene.tool_settings.double_threshold
dist = bpy.context.scene.tool_settings.double_threshold
find_nearest = cls.instance.__find_nearest
matrix = obj.matrix_world
for vert in verts :
Expand Down Expand Up @@ -202,7 +202,7 @@ def __smart_find( self , ray : pqutil.Ray ) :
if (location_r - ray.origin).length <= (location_i - ray.origin).length :
return location_r , normal_r , obj_r
else :
return location_i , normal_i , obj_i
return location_i , normal_i , obj_i

def __raycast_double( self , ray : pqutil.Ray ) :
# ターゲットからビュー方向にレイを飛ばす
Expand All @@ -218,7 +218,7 @@ def __raycast_double( self , ray : pqutil.Ray ) :
if (location_r - ray.origin).length <= (location_i - ray.origin).length :
return location_r , normal_r , face_r
else :
return location_i , normal_i , face_i
return location_i , normal_i , face_i
return None , None , None

def __find_nearest( self, pos : mathutils.Vector ) :
Expand Down
10 changes: 5 additions & 5 deletions Addons/PolyQuilt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
bl_info = {
"name" : "PolyQuilt",
"author" : "Sakana3",
"version": (1, 3, 1),
"blender" : (2, 83, 0),
"version": (1, 3, 11),
"blender" : (3, 3, 0),
"location": "View3D > Mesh > PolyQuilt",
"description": "Lowpoly Tool",
"warning" : "",
Expand All @@ -31,7 +31,7 @@
from .pq_tool import PolyQuiltTools
from .pq_tool_ui import VIEW3D_PT_tools_polyquilt_options
from .pq_keymap_editor import PQ_OT_DirtyKeymap
from .gizmo_preselect import *
from .gizmo_preselect import *
from .pq_preferences import *
from .translation import pq_translation_dict

Expand All @@ -49,7 +49,7 @@


def register():
bpy.app.translations.register(__name__, pq_translation_dict)
bpy.app.translations.register(__name__, pq_translation_dict)
register_icons()
register_updater(bl_info)

Expand All @@ -69,7 +69,7 @@ def unregister():
bpy.utils.unregister_tool(tool['tool'])

for cls in reversed(classes):
bpy.utils.unregister_class(cls)
bpy.utils.unregister_class(cls)

bpy.utils.unregister_class(pq_operator_add_empty_object.OBJECT_OT_add_object)
bpy.utils.unregister_manual_map(pq_operator_add_empty_object.add_object_manual_map)
Expand Down
21 changes: 2 additions & 19 deletions Addons/PolyQuilt/pq_preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,19 +408,11 @@ class PQ_OT_SetupUnityLikeKeymap(bpy.types.Operator) :

def execute(self, context):
for keymap in context.window_manager.keyconfigs.user.keymaps:
# print( keymap.name + "----" + keymap.space_type )
if keymap.space_type == 'EMPTY' or keymap.space_type == 'NODE_EDITOR' or keymap.space_type == 'IMAGE_EDITOR' :
# Add View2D RMB pan
if keymap.name == 'Image' :
PQ_OT_SetupUnityLikeKeymap.AddKeyToKeyMap( keymap , 'image.view_pan', 'MOUSE' , 'RIGHTMOUSE' , 'CLICK_DRAG' )
if keymap.name == "View2D" :
PQ_OT_SetupUnityLikeKeymap.AddKeyToKeyMap( keymap , 'view2d.pan', 'MOUSE' , 'RIGHTMOUSE' , 'CLICK_DRAG' )

if keymap.space_type == 'EMPTY':
for key in keymap.keymap_items:
if True not in [ key.any , key.alt , key.ctrl ,key.shift ]:
if key.map_type == 'MOUSE' and key.type == 'RIGHTMOUSE' and key.value != 'CLICK_DRAG' :
if key.map_type == 'MOUSE' and key.type == 'RIGHTMOUSE' :
key.value = 'CLICK'

for keymap in context.window_manager.keyconfigs.user.keymaps:
if keymap.space_type == 'VIEW_3D':
for key in keymap.keymap_items:
Expand All @@ -440,12 +432,3 @@ def execute(self, context):
key.shift = False

return {'FINISHED'}

def AddKeyToKeyMap( keymap , idname ,map_type, type , value , any=False, shift=0, ctrl=0, alt=0, oskey=0, key_modifier='NONE', repeat=False, head=False) :
for key in keymap.keymap_items:
if key.idname == idname and key.map_type == map_type and key.type ==type and key.value == value and key.any == any and key.alt == alt and key.ctrl == ctrl and key.shift == shift :
key.active = True
break
else :
keymap.keymap_items.new(idname = idname, type = type , value = value , any=any, shift=shift, ctrl=ctrl, alt=alt, oskey=oskey, key_modifier=key_modifier, repeat=repeat, head=head)

Loading

0 comments on commit a66de00

Please sign in to comment.