metaforce/hecl/blender/hecl/Patching.py

145 lines
4.9 KiB
Python

import bpy
import os
import os.path
from pathlib import Path
def _mkdir(path):
try:
os.mkdir(path)
except:
pass
def path_components(path):
retval = []
base, end = os.path.split(path)
while end != '':
retval.insert(0, end)
base, end = os.path.split(base)
return retval
def find_project_root():
if bpy.data.filepath == '':
return None
path = os.path.split(bpy.data.filepath)
test_path = os.path.join(path[0], '.hecl')
while not os.path.exists(test_path):
path = os.path.split(path[0])
test_path = os.path.join(path[0], '.hecl')
if os.path.exists(test_path):
return path[0]
return None
def get_patching_dirs(make_dirs=False):
proj_root = find_project_root()
if not proj_root:
return None, None
rel_to_blend = os.path.relpath(bpy.data.filepath, start=proj_root)
rel_to_blend_comps = path_components(rel_to_blend)
trace_dir = os.path.join(proj_root, '.hecl', 'patches')
global_out = trace_dir
if not make_dirs and not os.path.exists(trace_dir):
return None, global_out
_mkdir(trace_dir)
for comp in rel_to_blend_comps:
ext_pair = os.path.splitext(comp)
if ext_pair[1] == '.blend':
trace_dir = os.path.join(trace_dir, ext_pair[0])
if not make_dirs and not os.path.exists(trace_dir):
return None, global_out
_mkdir(trace_dir)
return trace_dir, global_out
trace_dir = os.path.join(trace_dir, comp)
if not make_dirs and not os.path.exists(trace_dir):
return None, global_out
_mkdir(trace_dir)
class FILE_OT_hecl_patching_save(bpy.types.Operator):
'''Save text datablocks to hecl patching directory'''
bl_idname = "file.hecl_patching_save"
bl_label = "Save HECL Patches"
bl_options = {'REGISTER'}
def execute(self, context):
patching_dir, global_dir = get_patching_dirs(make_dirs=True)
if not patching_dir:
self.report({'WARNING'}, 'Unable to save patches for ' + bpy.data.filepath)
return {'CANCELLED'}
count = 0
for text in bpy.data.texts:
if not text.name.endswith('.py') or text.name.startswith('g_'):
continue
text_abspath = os.path.join(patching_dir, text.name)
text_file = open(text_abspath, 'w')
text_file.write(text.as_string())
text_file.close()
count += 1
if count == 1:
self.report({'INFO'}, 'saved 1 patch')
else:
self.report({'INFO'}, 'saved %d patches' % count)
return {'FINISHED'}
class FILE_OT_hecl_patching_load(bpy.types.Operator):
'''Load text datablocks from hecl patching directory'''
bl_idname = "file.hecl_patching_load"
bl_label = "Load HECL Patches"
bl_options = {'REGISTER'}
def execute(self, context):
patching_dir, global_dir = get_patching_dirs()
count = 0
# Locals
if patching_dir:
p = Path(patching_dir)
for path in p.glob('*.py'):
path = path.name
text_abspath = os.path.join(patching_dir, path)
text_file = open(text_abspath, 'r')
if path in bpy.data.texts:
text = bpy.data.texts[path]
else:
text = bpy.data.texts.new(path)
text.from_string(text_file.read())
text_file.close()
count += 1
# Globals
if global_dir:
p = Path(global_dir)
for path in p.glob('g_*.py'):
path = path.name
text_abspath = os.path.join(global_dir, path)
text_file = open(text_abspath, 'r')
if path in bpy.data.texts:
text = bpy.data.texts[path]
else:
text = bpy.data.texts.new(path)
text.from_string(text_file.read())
text_file.close()
count += 1
if count == 1:
self.report({'INFO'}, 'loaded 1 patch')
else:
self.report({'INFO'}, 'loaded %d patches' % count)
return {'FINISHED'}
def save_func(self, context):
self.layout.operator("file.hecl_patching_save", text="Save HECL Patches")
def load_func(self, context):
self.layout.operator("file.hecl_patching_load", text="Load HECL Patches")
def register():
bpy.utils.register_class(FILE_OT_hecl_patching_save)
bpy.utils.register_class(FILE_OT_hecl_patching_load)
bpy.types.TOPBAR_MT_file_external_data.append(load_func)
bpy.types.TOPBAR_MT_file_external_data.append(save_func)
def unregister():
bpy.utils.unregister_class(FILE_OT_hecl_patching_save)
bpy.utils.unregister_class(FILE_OT_hecl_patching_load)
bpy.types.TOPBAR_MT_file_external_data.remove(load_func)
bpy.types.TOPBAR_MT_file_external_data.remove(save_func)