# SPDX-License-Identifier: GPL-3.0-or-later import bpy import re # import bpy_extras # from bpy_extras.io_utils import ImportHelper from pathlib import Path from bpy.types import Operator from .. import core from .. constants import BGCOL, MODULE_DIR ## Plane conversion between multiple types: GP plane / image plane / empty references def convert_background_image(ob, target = 'GPENCIL'): '''Target in ['GPENCIL', 'EMPTY', 'MESH']''' if target == ob.type: print('WARNING', f'{ob.name} Already of type {target}') return scn = bpy.context.scene cam = scn.objects.get('bg_cam') if not cam: cam = ob.parent if not cam: cam = scn.camera if not cam: print('No "bg_cam", no parent, source object is not parented !') return # Get info from Source img_infos = core.get_image_infos_from_object(ob) if not img_infos: print(f'No could not retrieve image source from {ob}') return image_data, opacity = img_infos ### Create new plane type ## RENAME to avoid conflict (always keep same name for list scan ?) ## rename source temporarily ## write type in name ? ## name only holder (if there is a holder) ob.name = f'{ob.name}_temp' ## TODO: ensure image filepath is ok ? suffix = '' if target == 'GPENCIL': ## Create GP plane from Texture source new = core.import_image_as_gp_reference( image_data, pack_image=False, ) suffix = '_texgp' if target == 'MESH': ## HARDCODED text blend path: # blend = '/s/blender/blender-2.9_scripts/addons/bg_plane_manager/texture_plane.blend' blend = str(MODULE_DIR / 'texture_plane.blend') node_group = core.link_nodegroup(blend, 'texture_plane', link=False) new = core.create_image_plane(image_data, node_group) suffix = '_texplane' if target == 'EMPTY': new = core.create_empty_image(image_data) suffix = '_texempty' # Strip after '.' or get original name ? print('source name: ', new.name) new.name = core.clean_image_name(image_data.name) + suffix print('final name:', new.name) new['is_background'] = True ## Without holder ## Transfer attributes # core.create_plane_driver(new, cam) # new.parent = cam # new['distance'] = ob['distance'] # new['scale'] = ob['scale'] # new.lock_location = ob.lock_location # lock only X,Y ? # new.hide_select = ob.hide_select # new.rotation_euler = ob.rotation_euler ## With holder new.parent = ob.parent ## Loc/scale overrided by driver # new.location = ob.location # new.scale = ob.scale ## Transfer current transparency # Destination core.set_opacity(new, opacity) ## Set in collection if not len(ob.users_collection): core.set_collection(new, BGCOL) else: core.set_collection(new, ob.users_collection[0].name) ## Remove old object bpy.data.objects.remove(ob) return new class BPM_OT_convert_planes(Operator): bl_idname = "bpm.convert_planes" bl_label = "Convert Planes" bl_description = "Convert as plane all images inside a folder" bl_options = {"REGISTER"} # , "UNDO" target_type : bpy.props.EnumProperty( name="Convert To", description="", default='GPENCIL', options={'ANIMATABLE'}, items=( ('GPENCIL', 'Gpencil Object', 'Convert bg planes to gpencil objects', 0), ('EMPTY', 'Empty Reference', 'Convert bg planes to empty objects', 1), ('MESH', 'Texture Plane', 'Convert bg planes to mesh objects', 2), )) def invoke(self, context, event): return context.window_manager.invoke_props_dialog(self, width=250) # return self.execute(context) def execute(self, context): print('BPM_OT_convert_planes') holder_list = core.scan_backgrounds(all_bg=True) if not holder_list: self.report({'ERROR'}, 'No Background found to convert, Structure must have a parent holder') return {'CANCELLED'} for holder in holder_list: if not holder.children: print(f'{holder.name} has not child') continue ob = holder.children[0] # take first child FIXME: what if multiple childrens ? new_bg = convert_background_image(ob, target=self.target_type) # if isinstance(new_bg, str): # self.report({'ERROR'}, new_bg) return {"FINISHED"} classes=( BPM_OT_convert_planes, ) def register(): for cls in classes: bpy.utils.register_class(cls) def unregister(): for cls in reversed(classes): bpy.utils.unregister_class(cls)