check links copy path
1.7.7 - feat: add copy path to `check link` ops with multiple path representation choicesgpv2
parent
204553ed47
commit
9389faed22
|
@ -1,5 +1,9 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
1.7.7
|
||||||
|
|
||||||
|
- feat: add copy path to `check link` ops with multiple path representation choices
|
||||||
|
|
||||||
1.7.6
|
1.7.6
|
||||||
|
|
||||||
- ui: expose (almost) all keymap added by the addon to allow user for customize/disable as needed
|
- ui: expose (almost) all keymap added by the addon to allow user for customize/disable as needed
|
||||||
|
|
|
@ -240,6 +240,80 @@ class GPTB_OT_file_checker(bpy.types.Operator):
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class GPTB_OT_copy_string_to_clipboard(bpy.types.Operator):
|
||||||
|
bl_idname = "gp.copy_string_to_clipboard"
|
||||||
|
bl_label = "Copy String"
|
||||||
|
bl_description = "Copy passed string to clipboard"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
|
||||||
|
string : bpy.props.StringProperty(options={'SKIP_SAVE'})
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
if not self.string:
|
||||||
|
# self.report({'ERROR'}, 'Nothing to copy')
|
||||||
|
return {"CANCELLED"}
|
||||||
|
bpy.context.window_manager.clipboard = self.string
|
||||||
|
self.report({'INFO'}, f'Copied: {self.string}')
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
class GPTB_OT_copy_multipath_clipboard(bpy.types.Operator):
|
||||||
|
bl_idname = "gp.copy_multipath_clipboard"
|
||||||
|
bl_label = "Choose Path to Copy"
|
||||||
|
bl_description = "Copy Chosen Path"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
|
||||||
|
string : bpy.props.StringProperty(options={'SKIP_SAVE'})
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
if not self.string:
|
||||||
|
return {"CANCELLED"}
|
||||||
|
self.pathes = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
absolute = os.path.abspath(bpy.path.abspath(self.string))
|
||||||
|
abs_parent = os.path.dirname(os.path.abspath(bpy.path.abspath(self.string)))
|
||||||
|
path_abs = str(Path(bpy.path.abspath(self.string)).resolve())
|
||||||
|
|
||||||
|
except:
|
||||||
|
# case of invalid / non-accessable path
|
||||||
|
bpy.context.window_manager.clipboard = self.string
|
||||||
|
return context.window_manager.invoke_props_dialog(self, width=800)
|
||||||
|
|
||||||
|
self.pathes.append(('Raw Path', self.string))
|
||||||
|
self.pathes.append(('Parent', os.path.dirname(self.string)))
|
||||||
|
|
||||||
|
if absolute != self.string:
|
||||||
|
self.pathes.append(('Absolute', absolute))
|
||||||
|
|
||||||
|
if absolute != self.string:
|
||||||
|
self.pathes.append(('Absolute Parent', abs_parent))
|
||||||
|
|
||||||
|
if absolute != path_abs:
|
||||||
|
self.pathes.append(('Resolved',path_abs))
|
||||||
|
|
||||||
|
self.pathes.append(('File name', os.path.basename(self.string)))
|
||||||
|
|
||||||
|
maxlen = max(len(l[1]) for l in self.pathes)
|
||||||
|
popup_width = 800
|
||||||
|
if maxlen < 50:
|
||||||
|
popup_width = 500
|
||||||
|
elif maxlen > 100:
|
||||||
|
popup_width = 1000
|
||||||
|
return context.window_manager.invoke_props_dialog(self, width=popup_width)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.separator()
|
||||||
|
col = layout.column()
|
||||||
|
for l in self.pathes:
|
||||||
|
split=col.split(factor=0.2, align=True)
|
||||||
|
split.operator('gp.copy_string_to_clipboard', text=l[0], icon='COPYDOWN').string = l[1]
|
||||||
|
split.label(text=l[1])
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class GPTB_OT_links_checker(bpy.types.Operator):
|
class GPTB_OT_links_checker(bpy.types.Operator):
|
||||||
bl_idname = "gp.links_checker"
|
bl_idname = "gp.links_checker"
|
||||||
|
@ -267,14 +341,28 @@ class GPTB_OT_links_checker(bpy.types.Operator):
|
||||||
|
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
# layout = layout.column() # thinner linespace
|
||||||
for l in self.all_lnks:
|
for l in self.all_lnks:
|
||||||
if l[1] == 'LIBRARY_DATA_BROKEN':
|
if l[1] == 'CANCEL':
|
||||||
layout.label(text=l[0], icon=l[1])
|
layout.label(text=l[0], icon=l[1])
|
||||||
else:
|
continue
|
||||||
split=layout.split(factor=0.75)
|
|
||||||
|
if l[1] == 'LIBRARY_DATA_BROKEN':
|
||||||
|
split=layout.split(factor=0.85)
|
||||||
split.label(text=l[0], icon=l[1])
|
split.label(text=l[0], icon=l[1])
|
||||||
split.operator('wm.path_open', text='Open folder', icon='FILE_FOLDER').filepath = Path(bpy.path.abspath(l[0])).resolve().parent.as_posix()
|
# layout.label(text=l[0], icon=l[1])
|
||||||
split.operator('wm.path_open', text='Open file', icon='FILE_TICK').filepath = Path(bpy.path.abspath(l[0])).resolve().as_posix()#os.path.abspath(bpy.path.abspath(dirname(l[0])))
|
else:
|
||||||
|
split=layout.split(factor=0.75, align=True)
|
||||||
|
split.label(text=l[0], icon=l[1])
|
||||||
|
## resolve() return somethin different than os.path.abspath.
|
||||||
|
# split.operator('wm.path_open', text='Open folder', icon='FILE_FOLDER').filepath = Path(bpy.path.abspath(l[0])).resolve().parent.as_posix()
|
||||||
|
# split.operator('wm.path_open', text='Open file', icon='FILE_TICK').filepath = Path(bpy.path.abspath(l[0])).resolve().as_posix()
|
||||||
|
|
||||||
|
split.operator('wm.path_open', text='Open Folder', icon='FILE_FOLDER').filepath = Path(os.path.abspath(bpy.path.abspath(l[0]))).parent.as_posix()
|
||||||
|
split.operator('wm.path_open', text='Open File', icon='FILE_TICK').filepath = Path(os.path.abspath(bpy.path.abspath(l[0]))).as_posix()
|
||||||
|
|
||||||
|
split.operator('gp.copy_multipath_clipboard', text='Copy Path', icon='COPYDOWN').string = l[0]
|
||||||
|
# split.operator('gp.copy_string_to_clipboard', text='Copy Path', icon='COPYDOWN').string = l[0] # copy blend path directly
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
self.all_lnks = []
|
self.all_lnks = []
|
||||||
|
@ -283,19 +371,32 @@ class GPTB_OT_links_checker(bpy.types.Operator):
|
||||||
abs_ct = 0
|
abs_ct = 0
|
||||||
rel_ct = 0
|
rel_ct = 0
|
||||||
## check for broken links
|
## check for broken links
|
||||||
|
viewed = []
|
||||||
for current, lib in zip(bpy.utils.blend_paths(local=True), bpy.utils.blend_paths(absolute=True, local=True)):
|
for current, lib in zip(bpy.utils.blend_paths(local=True), bpy.utils.blend_paths(absolute=True, local=True)):
|
||||||
lfp = Path(lib)
|
# avoid relisting same path mutliple times
|
||||||
realib = Path(current)
|
if current in viewed:
|
||||||
if not lfp.exists():
|
continue
|
||||||
self.broke_ct += 1
|
# TODO find a proper way to show the number of user of this path...
|
||||||
self.all_lnks.append( (f"{realib.as_posix()}", 'LIBRARY_DATA_BROKEN') )#lfp.as_posix()
|
viewed.append(current)
|
||||||
else:
|
|
||||||
if realib.as_posix().startswith('//'):
|
realib = Path(current) # path as-is
|
||||||
rel_ct += 1
|
lfp = Path(lib) # absolute path
|
||||||
self.all_lnks.append( (f"{realib.as_posix()}", 'LINKED') )#lfp.as_posix()
|
|
||||||
|
try: # Try because some path may fail parsing
|
||||||
|
if not lfp.exists():
|
||||||
|
self.broke_ct += 1
|
||||||
|
self.all_lnks.append( (f"{realib.as_posix()}", 'LIBRARY_DATA_BROKEN') )
|
||||||
else:
|
else:
|
||||||
abs_ct += 1
|
if realib.as_posix().startswith('//'):
|
||||||
self.all_lnks.append( (f"{realib.as_posix()}", 'LIBRARY_DATA_INDIRECT') )#lfp.as_posix()
|
rel_ct += 1
|
||||||
|
self.all_lnks.append( (f"{realib.as_posix()}", 'LINKED') )
|
||||||
|
else:
|
||||||
|
abs_ct += 1
|
||||||
|
self.all_lnks.append( (f"{realib.as_posix()}", 'LIBRARY_DATA_INDIRECT') )
|
||||||
|
except:
|
||||||
|
self.broke_ct += 1
|
||||||
|
self.all_lnks.append( (f"{current}" , 'CANCEL') ) # error accessing file
|
||||||
|
|
||||||
|
|
||||||
if not self.all_lnks:
|
if not self.all_lnks:
|
||||||
self.report({'INFO'}, 'No external links in files')
|
self.report({'INFO'}, 'No external links in files')
|
||||||
|
@ -317,14 +418,20 @@ class GPTB_OT_links_checker(bpy.types.Operator):
|
||||||
print(p[0])
|
print(p[0])
|
||||||
# Show in viewport
|
# Show in viewport
|
||||||
|
|
||||||
|
maxlen = max(len(x) for x in viewed)
|
||||||
|
|
||||||
# if broke_ct == 0:
|
# if broke_ct == 0:
|
||||||
# show_message_box(self.all_lnks, _title = self.title, _icon = 'INFO')# Links
|
# show_message_box(self.all_lnks, _title = self.title, _icon = 'INFO')# Links
|
||||||
# return {"FINISHED"}
|
# return {"FINISHED"}
|
||||||
try:
|
popup_width = 800
|
||||||
self.proj = context.preferences.addons['pipe_sync'].preferences['local_folder']
|
if maxlen < 50:
|
||||||
except:
|
popup_width = 500
|
||||||
self.proj = None
|
elif maxlen > 100:
|
||||||
return context.window_manager.invoke_props_dialog(self, width=800)
|
popup_width = 1000
|
||||||
|
|
||||||
|
self.proj = os.environ.get('PROJECT_ROOT')
|
||||||
|
return context.window_manager.invoke_props_dialog(self, width=popup_width)
|
||||||
|
|
||||||
|
|
||||||
""" OLD links checker with show_message_box
|
""" OLD links checker with show_message_box
|
||||||
class GPTB_OT_links_checker(bpy.types.Operator):
|
class GPTB_OT_links_checker(bpy.types.Operator):
|
||||||
|
@ -501,6 +608,8 @@ classes = (
|
||||||
# GPTB_OT_check_scene,
|
# GPTB_OT_check_scene,
|
||||||
GPTB_OT_list_object_visibility,
|
GPTB_OT_list_object_visibility,
|
||||||
GPTB_OT_list_modifier_visibility,
|
GPTB_OT_list_modifier_visibility,
|
||||||
|
GPTB_OT_copy_string_to_clipboard,
|
||||||
|
GPTB_OT_copy_multipath_clipboard,
|
||||||
GPTB_OT_file_checker,
|
GPTB_OT_file_checker,
|
||||||
GPTB_OT_links_checker,
|
GPTB_OT_links_checker,
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,7 +15,7 @@ bl_info = {
|
||||||
"name": "GP toolbox",
|
"name": "GP toolbox",
|
||||||
"description": "Set of tools for Grease Pencil in animation production",
|
"description": "Set of tools for Grease Pencil in animation production",
|
||||||
"author": "Samuel Bernou, Christophe Seux",
|
"author": "Samuel Bernou, Christophe Seux",
|
||||||
"version": (1, 7, 6),
|
"version": (1, 7, 7),
|
||||||
"blender": (2, 91, 0),
|
"blender": (2, 91, 0),
|
||||||
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
|
Loading…
Reference in New Issue