refacto to use import_planes as a functions
parent
ba5084e458
commit
11029606df
|
@ -16,11 +16,12 @@ import bpy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from . import operators
|
from . import operators
|
||||||
|
from . import import_planes
|
||||||
from . import export_psd_layers
|
from . import export_psd_layers
|
||||||
from . import ui
|
from . import ui
|
||||||
from . import preferences
|
from . import preferences
|
||||||
|
|
||||||
from . import fn
|
from . import core
|
||||||
|
|
||||||
#from . file_utils import install_module
|
#from . file_utils import install_module
|
||||||
#install_module('psd_tools', 'psd-tools')
|
#install_module('psd_tools', 'psd-tools')
|
||||||
|
@ -69,7 +70,7 @@ def register():
|
||||||
for m in modules:
|
for m in modules:
|
||||||
m.register()
|
m.register()
|
||||||
|
|
||||||
preferences.ui_in_sidebar_update(fn.get_addon_prefs(), bpy.context)
|
preferences.ui_in_sidebar_update(core.get_addon_prefs(), bpy.context)
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
for m in reversed(modules):
|
for m in reversed(modules):
|
||||||
|
|
|
@ -453,14 +453,12 @@ def create_gpencil_reference(
|
||||||
return gps_new
|
return gps_new
|
||||||
|
|
||||||
def import_image_as_gp_reference(
|
def import_image_as_gp_reference(
|
||||||
context: bpy.types.Context,
|
|
||||||
image,
|
image,
|
||||||
pack_image: bool = False,
|
pack_image: bool = False,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Import image from `image` as a textured rectangle in the given
|
Import image from `image` as a textured rectangle in the given
|
||||||
grease pencil object.
|
grease pencil object.
|
||||||
:param context: The active context.
|
|
||||||
:param image: The image filepath or image datablock
|
:param image: The image filepath or image datablock
|
||||||
:param pack_image: Whether to pack the image into the Blender file.
|
:param pack_image: Whether to pack the image into the Blender file.
|
||||||
"""
|
"""
|
||||||
|
@ -468,7 +466,7 @@ def import_image_as_gp_reference(
|
||||||
if not image:
|
if not image:
|
||||||
return
|
return
|
||||||
|
|
||||||
scene = context.scene
|
scene = bpy.context.scene
|
||||||
if not isinstance(image, bpy.types.Image):
|
if not isinstance(image, bpy.types.Image):
|
||||||
image = bpy.data.images.load(str(image), check_existing=True)
|
image = bpy.data.images.load(str(image), check_existing=True)
|
||||||
|
|
||||||
|
@ -806,4 +804,5 @@ def coord_distance_from_cam(coord, context=None, camera=None):
|
||||||
camera = camera or context.scene.camera
|
camera = camera or context.scene.camera
|
||||||
if not camera:
|
if not camera:
|
||||||
return
|
return
|
||||||
return (coord - camera.matrix_world.to_translation()).length
|
return (coord - camera.matrix_world.to_translation()).length
|
||||||
|
|
|
@ -7,7 +7,7 @@ import json
|
||||||
#import psd_tools
|
#import psd_tools
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from time import time
|
from time import time
|
||||||
from . import fn
|
from . import core
|
||||||
from . file_utils import install_module
|
from . file_utils import install_module
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ def export_psd(psd_file, output=None, scale=0.5):
|
||||||
l.visible = True
|
l.visible = True
|
||||||
|
|
||||||
name = layer.name
|
name = layer.name
|
||||||
norm_name = fn.norm_str(name, padding=2) # Gadget normstr
|
norm_name = core.norm_str(name, padding=2) # Gadget normstr
|
||||||
print('name: ', name)
|
print('name: ', name)
|
||||||
png_output = (output/norm_name).with_suffix('.png')
|
png_output = (output/norm_name).with_suffix('.png')
|
||||||
|
|
||||||
|
@ -269,8 +269,8 @@ class BPM_OT_export_psd_layers(bpy.types.Operator, ImportHelper):
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
classes=(
|
classes = (
|
||||||
BPM_OT_export_psd_layers,
|
BPM_OT_export_psd_layers,
|
||||||
)
|
)
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
from . import operators
|
||||||
|
|
||||||
|
modules = (
|
||||||
|
operators,
|
||||||
|
)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
for module in modules:
|
||||||
|
bpy.utils.register_class(module)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
for module in reversed(modules):
|
||||||
|
bpy.utils.unregister_class(module)
|
|
@ -0,0 +1,158 @@
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
from mathutils import Vector, geometry
|
||||||
|
from pprint import pprint as pp
|
||||||
|
from ..constants import PREFIX, BGCOL, INIT_POS
|
||||||
|
from ..core import (create_cam, set_collection, get_image_infos_from_object, get_col,
|
||||||
|
import_image_as_gp_reference, create_image_plane, set_collection, get_image,
|
||||||
|
create_empty_image, create_plane_holder, create_plane_driver, reload_bg_list)
|
||||||
|
|
||||||
|
|
||||||
|
def get_json_infos(json_path) -> tuple((list, tuple)):
|
||||||
|
'''return a tuple with (image paths list, [x, y] original psd resolution'''
|
||||||
|
|
||||||
|
import json
|
||||||
|
setup_json_path = Path(json_path)
|
||||||
|
setup_json = json.loads(setup_json_path.read_text())
|
||||||
|
|
||||||
|
# psd = Path(setup_json['psd']) # path to psd
|
||||||
|
# image_size = setup_json['image_size'] # image size (reduced)
|
||||||
|
# png_dir = Path(setup_json['png_dir']) # path to png directory
|
||||||
|
layers = setup_json['layers'] # dic : name, lbbox, bbox, index, path
|
||||||
|
org_image_size = setup_json['org_image_size'] # original PSD dimensions
|
||||||
|
img_list = [Path(l['path']) for l in layers] # (png_dir /l['name']).with_suffix('.png')
|
||||||
|
|
||||||
|
return img_list, org_image_size
|
||||||
|
|
||||||
|
|
||||||
|
def setup_bg_camera(image_size, scene=None, cam_type=None):
|
||||||
|
'''Create background camera from scene active camera according to background image resolution
|
||||||
|
image_size ::
|
||||||
|
cam_type :: wether the BG camera should be set to perspective or orthographic
|
||||||
|
'''
|
||||||
|
|
||||||
|
scn = scene or bpy.context.scene
|
||||||
|
|
||||||
|
movie_resolution = scn.render.resolution_x, scn.render.resolution_y
|
||||||
|
anim_cam = scn.camera
|
||||||
|
anim_cam_scale = 6 # anim_cam.data.ortho_scale
|
||||||
|
anim_cam_focale = 50 # anim_cam.data.lens
|
||||||
|
cam_type = cam_type or anim_cam.data.type
|
||||||
|
|
||||||
|
## scale up plane scale and bg_cam ortho_scale according to film res
|
||||||
|
bg_factor = (anim_cam_scale * image_size[0]) / movie_resolution[0]
|
||||||
|
#print(f'({anim_cam_scale} * {image_size[0]}) / {movie_resolution[0]} = {bg_factor}')
|
||||||
|
|
||||||
|
## scale down the focal according to film res
|
||||||
|
bg_focale = (anim_cam_focale * movie_resolution[0]) / image_size[0]
|
||||||
|
#print(f'({anim_cam_focale} * {movie_resolution[0]}) / {image_size[0]} = {bg_focale}')
|
||||||
|
|
||||||
|
bg_cam = scn.objects.get('bg_cam')
|
||||||
|
if not bg_cam:
|
||||||
|
bg_cam = create_cam(name='bg_cam', type=cam_type, size=bg_factor, focale=bg_focale)
|
||||||
|
bg_cam['resolution'] = image_size
|
||||||
|
|
||||||
|
bg_cam.matrix_world = anim_cam.matrix_world
|
||||||
|
|
||||||
|
bg_cam.hide_select = True
|
||||||
|
bg_cam.lock_location = bg_cam.lock_rotation = bg_cam.lock_scale = [True]*3
|
||||||
|
|
||||||
|
set_collection(bg_cam, 'Camera')
|
||||||
|
set_collection(anim_cam, 'Camera')
|
||||||
|
return bg_cam
|
||||||
|
|
||||||
|
def import_planes(images, import_type='GPENCIL', mode='REPLACE', image_size=None):
|
||||||
|
scn = bpy.context.scene
|
||||||
|
|
||||||
|
existing_backgrounds = [(o, *img_info) for o in scn.objects \
|
||||||
|
if o.get('is_background') and (img_info := get_image_infos_from_object(o)) and o.get('is_background') and o.parent]
|
||||||
|
|
||||||
|
existing_backgrounds.sort(key=lambda x: x[0].parent.location.z, reverse=True) # sort by parent (holder) location Z
|
||||||
|
|
||||||
|
far_plane = INIT_POS
|
||||||
|
if existing_backgrounds:
|
||||||
|
far_plane = existing_backgrounds[-1][0].parent.location.z
|
||||||
|
|
||||||
|
## Ensure bg_cam setup (option to use active camera ?)
|
||||||
|
bg_cam = scn.objects.get('bg_cam')
|
||||||
|
if not bg_cam:
|
||||||
|
if not image_size:
|
||||||
|
## Get image size from first file
|
||||||
|
img = bpy.data.images.load(str(images[0]), check_existing=True)
|
||||||
|
image_size = (img.size[0], img.size[1])
|
||||||
|
bg_cam = setup_bg_camera(image_size)
|
||||||
|
|
||||||
|
## Ensure Background collection
|
||||||
|
backgrounds = get_col(BGCOL) # Create if needed
|
||||||
|
|
||||||
|
for image_path in images:
|
||||||
|
image_path = Path(image_path)
|
||||||
|
print(f'Importing {image_path.name}')
|
||||||
|
current_holder = None
|
||||||
|
|
||||||
|
file_stem = image_path.stem
|
||||||
|
# current_bg = next((o for o if o.parent and get_image_infos_from_object(o)), None)
|
||||||
|
current_bg = next((o for o in existing_backgrounds if Path(o[1].filepath) == image_path), None)
|
||||||
|
if current_bg:
|
||||||
|
current_holder = current_bg.parent
|
||||||
|
# TODO store opacity or delete existing objects only after loop
|
||||||
|
|
||||||
|
if current_bg and mode == 'SKIP':
|
||||||
|
print(f' - SKIP: existing {current_bg.name}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if current_bg and mode == 'REPLACE':
|
||||||
|
print(f' - DEL: existing {current_bg.name}')
|
||||||
|
bpy.data.objects.remove(current_bg)
|
||||||
|
|
||||||
|
# Import image
|
||||||
|
if import_type == 'GPENCIL':
|
||||||
|
bg_img = import_image_as_gp_reference(
|
||||||
|
image=str(image_path),
|
||||||
|
pack_image=False,
|
||||||
|
)
|
||||||
|
elif import_type == 'MESH':
|
||||||
|
bg_img = create_image_plane(image_path)
|
||||||
|
|
||||||
|
elif import_type == 'EMPTY':
|
||||||
|
bg_img = create_empty_image(image_path)
|
||||||
|
|
||||||
|
|
||||||
|
bg_img.name = file_stem + '_texgp'
|
||||||
|
bg_img.hide_select = True
|
||||||
|
|
||||||
|
if current_holder:
|
||||||
|
bg_img.parent = current_holder
|
||||||
|
set_collection(bg_img, current_holder.users_collection[0].name)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# img, opacity = get_image_infos_from_object(bg_img)
|
||||||
|
print('bg_img: ', bg_img)
|
||||||
|
img = get_image(bg_img)
|
||||||
|
# bg_name = clean_image_name(img.name)
|
||||||
|
file_stem = file_stem
|
||||||
|
|
||||||
|
# Get create collection from image clean name
|
||||||
|
bg_col = get_col(file_stem, parent=backgrounds)
|
||||||
|
|
||||||
|
## Set in collection
|
||||||
|
bg_col.objects.link(bg_img)
|
||||||
|
|
||||||
|
print('img: ', img.name, bg_img.name, bg_img.users_collection)
|
||||||
|
|
||||||
|
## create the holder, parent to camera, set driver and set collection. Could also pass 'fp'
|
||||||
|
holder = create_plane_holder(img, name=PREFIX + file_stem, parent=bg_cam, link_in_col=bg_col)
|
||||||
|
print('holder: ', holder.name)
|
||||||
|
|
||||||
|
create_plane_driver(holder, bg_cam, distance=far_plane)
|
||||||
|
bg_img.parent = holder
|
||||||
|
|
||||||
|
far_plane += 2
|
||||||
|
|
||||||
|
reload_bg_list(scene=scn)
|
|
@ -0,0 +1,130 @@
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
## Standalone based on SPA code
|
||||||
|
## Code from create_gp_texture_ref.py (Copyright (C) 2023, The SPA Studios. All rights reserved.)
|
||||||
|
## adapted to create as a single 'GP as image' and fit in camera with driver
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from bpy_extras.io_utils import ImportHelper
|
||||||
|
from bpy.props import (StringProperty,
|
||||||
|
CollectionProperty,
|
||||||
|
BoolProperty,
|
||||||
|
EnumProperty)
|
||||||
|
import json
|
||||||
|
import bpy_extras
|
||||||
|
from mathutils import Vector
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from .. import core
|
||||||
|
from .. constants import *
|
||||||
|
from .. export_psd_layers import export_psd_bg
|
||||||
|
from . core import import_planes, get_json_infos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class BPM_OT_import_bg_images(bpy.types.Operator, ImportHelper):
|
||||||
|
bl_idname = "bpm.import_bg_images"
|
||||||
|
bl_label = "Import Background images"
|
||||||
|
bl_description = "Import either a Json, a PSD, multiple files"
|
||||||
|
bl_options = {"REGISTER"} # , "INTERNAL"
|
||||||
|
|
||||||
|
# filename_ext = '.json'
|
||||||
|
|
||||||
|
filter_glob: StringProperty(
|
||||||
|
default=';'.join([f'*{i}' for i in bpy.path.extensions_image]) + ';*.json',
|
||||||
|
options={'HIDDEN'} )
|
||||||
|
|
||||||
|
## Active selection
|
||||||
|
filepath : StringProperty(
|
||||||
|
name="File Path",
|
||||||
|
description="File path used for import",
|
||||||
|
maxlen= 1024) # the active file
|
||||||
|
|
||||||
|
## Handle multi-selection
|
||||||
|
files: CollectionProperty(
|
||||||
|
name="File Path",
|
||||||
|
type=bpy.types.OperatorFileListElement,
|
||||||
|
) # The filelist collection
|
||||||
|
|
||||||
|
## Choice to place before or after ?
|
||||||
|
|
||||||
|
import_type : EnumProperty(
|
||||||
|
name="Import As", description="Type of import to ", default='GPENCIL', options={'ANIMATABLE'},
|
||||||
|
items=(
|
||||||
|
('GPENCIL', 'Gpencil Object', 'Import bg planes as gpencil objects', 0),
|
||||||
|
('EMPTY', 'Empty Reference', 'Import bg planes as empty objects', 1),
|
||||||
|
('MESH', 'Texture Plane', 'Import bg planes as mesh objects', 2),
|
||||||
|
))
|
||||||
|
|
||||||
|
mode : EnumProperty(
|
||||||
|
name="Mode", description="", default='REPLACE', options={'ANIMATABLE'},
|
||||||
|
items=(
|
||||||
|
('REPLACE', 'Replace Existing', 'Replace the image if already exists', 0),
|
||||||
|
('SKIP', 'Skip Existing', 'Skip the import if the image alreaady exists in planes', 1),
|
||||||
|
# ('PURGE', 'Purge', 'When object exists, fully delete it before linking, even associated collection and holder', 2),
|
||||||
|
))
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
org_image_size = None
|
||||||
|
scn = context.scene
|
||||||
|
active_file = Path(self.filepath)
|
||||||
|
|
||||||
|
if len(self.files) == 1 and active_file.suffix.lower() in ('.json', '.psd'):
|
||||||
|
json_path = None
|
||||||
|
print('active_file.suffix.lower(): ', active_file.suffix.lower())
|
||||||
|
if active_file.suffix.lower() == '.psd':
|
||||||
|
print('Is a PSD')
|
||||||
|
## Export layers and create json setup file
|
||||||
|
# Export passes in a 'render' or 'render_hd' folder aside psd
|
||||||
|
json_path = export_psd_bg(str(active_file))
|
||||||
|
|
||||||
|
elif active_file.suffix.lower() == '.json':
|
||||||
|
print('Is a json')
|
||||||
|
# Use json data to batch import
|
||||||
|
json_path = active_file
|
||||||
|
|
||||||
|
if not json_path:
|
||||||
|
self.report({'ERROR'}, 'No json path to load, you can try loading from psd or selecting image file directly')
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
file_list, org_image_size = get_json_infos(json_path)
|
||||||
|
folder = Path(json_path).parent # render folder
|
||||||
|
|
||||||
|
else:
|
||||||
|
folder = active_file.parent
|
||||||
|
# Filter out json (we may want ot import the PSD as imagelisted in bpy.path.extensions_image)
|
||||||
|
file_list = [folder / f.name for f in self.files if Path(f.name).suffix in bpy.path.extensions_image]
|
||||||
|
|
||||||
|
if not file_list:
|
||||||
|
self.report({'ERROR'}, 'Image file list is empty')
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
|
||||||
|
## simple_list
|
||||||
|
# existing_backgrounds = [o for o in context.scene.objects if o.get('is_background')]
|
||||||
|
# existing_holders = [o for o in context.scene.objects if o.name.startswith(PREFIX) and o.type == 'MESH' and o.children]
|
||||||
|
|
||||||
|
## Has dict
|
||||||
|
# existing_backgrounds = {o : img_info for o in context.scene.objects if o.get('is_background') and (img_info := o.get('is_background'))}
|
||||||
|
|
||||||
|
# FIXME: Use existing background custom prop? : o.get('is_background')
|
||||||
|
## list of Tuples : [(plane_object, img_data, transparency_value), ...]
|
||||||
|
|
||||||
|
import_planes(file_list, import_type=self.import_type, image_size=org_image_size)
|
||||||
|
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
classes = (
|
||||||
|
BPM_OT_import_bg_images,
|
||||||
|
)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
for cls in classes:
|
||||||
|
bpy.utils.register_class(cls)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
for cls in reversed(classes):
|
||||||
|
bpy.utils.unregister_class(cls)
|
|
@ -1,11 +1,10 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
from . import (manage_objects, manage_planes, import_planes, convert_planes)
|
from . import (manage_objects, manage_planes, convert_planes)
|
||||||
|
|
||||||
modules = (
|
modules = (
|
||||||
manage_objects,
|
manage_objects,
|
||||||
manage_planes,
|
manage_planes,
|
||||||
import_planes,
|
|
||||||
convert_planes
|
convert_planes
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import re
|
||||||
# from bpy_extras.io_utils import ImportHelper
|
# from bpy_extras.io_utils import ImportHelper
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from .. import fn
|
from .. import core
|
||||||
from .. constants import BGCOL, MODULE_DIR
|
from .. constants import BGCOL, MODULE_DIR
|
||||||
|
|
||||||
## Plane conversion between multiple types: GP plane / image plane / empty references
|
## Plane conversion between multiple types: GP plane / image plane / empty references
|
||||||
|
@ -29,7 +29,7 @@ def convert_background_image(ob, target = 'GPENCIL'):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get info from Source
|
# Get info from Source
|
||||||
img_infos = fn.get_image_infos_from_object(ob)
|
img_infos = core.get_image_infos_from_object(ob)
|
||||||
if not img_infos:
|
if not img_infos:
|
||||||
print(f'No could not retrieve image source from {ob}')
|
print(f'No could not retrieve image source from {ob}')
|
||||||
return
|
return
|
||||||
|
@ -51,8 +51,7 @@ def convert_background_image(ob, target = 'GPENCIL'):
|
||||||
suffix = ''
|
suffix = ''
|
||||||
if target == 'GPENCIL':
|
if target == 'GPENCIL':
|
||||||
## Create GP plane from Texture source
|
## Create GP plane from Texture source
|
||||||
new = fn.import_image_as_gp_reference(
|
new = core.import_image_as_gp_reference(
|
||||||
bpy.context,
|
|
||||||
image_data,
|
image_data,
|
||||||
pack_image=False,
|
pack_image=False,
|
||||||
)
|
)
|
||||||
|
@ -62,24 +61,24 @@ def convert_background_image(ob, target = 'GPENCIL'):
|
||||||
## HARDCODED text blend path:
|
## HARDCODED text blend path:
|
||||||
# blend = '/s/blender/blender-2.9_scripts/addons/bg_plane_manager/texture_plane.blend'
|
# blend = '/s/blender/blender-2.9_scripts/addons/bg_plane_manager/texture_plane.blend'
|
||||||
blend = str(MODULE_DIR / 'texture_plane.blend')
|
blend = str(MODULE_DIR / 'texture_plane.blend')
|
||||||
node_group = fn.link_nodegroup(blend, 'texture_plane', link=False)
|
node_group = core.link_nodegroup(blend, 'texture_plane', link=False)
|
||||||
new = fn.create_image_plane(image_data, node_group)
|
new = core.create_image_plane(image_data, node_group)
|
||||||
suffix = '_texplane'
|
suffix = '_texplane'
|
||||||
|
|
||||||
if target == 'EMPTY':
|
if target == 'EMPTY':
|
||||||
new = fn.create_empty_image(image_data)
|
new = core.create_empty_image(image_data)
|
||||||
suffix = '_texempty'
|
suffix = '_texempty'
|
||||||
|
|
||||||
|
|
||||||
# Strip after '.' or get original name ?
|
# Strip after '.' or get original name ?
|
||||||
print('source name: ', new.name)
|
print('source name: ', new.name)
|
||||||
new.name = fn.clean_image_name(image_data.name) + suffix
|
new.name = core.clean_image_name(image_data.name) + suffix
|
||||||
print('final name:', new.name)
|
print('final name:', new.name)
|
||||||
new['is_background'] = True
|
new['is_background'] = True
|
||||||
|
|
||||||
## Without holder
|
## Without holder
|
||||||
## Transfer attributes
|
## Transfer attributes
|
||||||
# fn.create_plane_driver(new, cam)
|
# core.create_plane_driver(new, cam)
|
||||||
# new.parent = cam
|
# new.parent = cam
|
||||||
|
|
||||||
# new['distance'] = ob['distance']
|
# new['distance'] = ob['distance']
|
||||||
|
@ -102,13 +101,13 @@ def convert_background_image(ob, target = 'GPENCIL'):
|
||||||
## Transfer current transparency
|
## Transfer current transparency
|
||||||
|
|
||||||
# Destination
|
# Destination
|
||||||
fn.set_opacity(new, opacity)
|
core.set_opacity(new, opacity)
|
||||||
|
|
||||||
## Set in collection
|
## Set in collection
|
||||||
if not len(ob.users_collection):
|
if not len(ob.users_collection):
|
||||||
fn.set_collection(new, BGCOL)
|
core.set_collection(new, BGCOL)
|
||||||
else:
|
else:
|
||||||
fn.set_collection(new, ob.users_collection[0].name)
|
core.set_collection(new, ob.users_collection[0].name)
|
||||||
|
|
||||||
## Remove old object
|
## Remove old object
|
||||||
bpy.data.objects.remove(ob)
|
bpy.data.objects.remove(ob)
|
||||||
|
@ -136,7 +135,7 @@ class BPM_OT_convert_planes(Operator):
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
print('BPM_OT_convert_planes')
|
print('BPM_OT_convert_planes')
|
||||||
holder_list = fn.scan_backgrounds(all_bg=True)
|
holder_list = core.scan_backgrounds(all_bg=True)
|
||||||
if not holder_list:
|
if not holder_list:
|
||||||
self.report({'ERROR'}, 'No Background found to convert, Structure must have a parent holder')
|
self.report({'ERROR'}, 'No Background found to convert, Structure must have a parent holder')
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
|
@ -1,263 +0,0 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
## Standalone based on SPA code
|
|
||||||
## Code from create_gp_texture_ref.py (Copyright (C) 2023, The SPA Studios. All rights reserved.)
|
|
||||||
## adapted to create as a single 'GP as image' and fit in camera with driver
|
|
||||||
|
|
||||||
import bpy
|
|
||||||
from bpy_extras.io_utils import ImportHelper
|
|
||||||
from bpy.props import (StringProperty,
|
|
||||||
CollectionProperty,
|
|
||||||
BoolProperty,
|
|
||||||
EnumProperty)
|
|
||||||
import json
|
|
||||||
import bpy_extras
|
|
||||||
from mathutils import Vector
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
from .. import fn
|
|
||||||
from .. constants import *
|
|
||||||
from .. export_psd_layers import export_psd_bg
|
|
||||||
|
|
||||||
|
|
||||||
def get_json_infos(json_path) -> tuple((list, tuple)):
|
|
||||||
'''return a tuple with (image paths list, [x, y] original psd resolution'''
|
|
||||||
|
|
||||||
import json
|
|
||||||
setup_json_path = Path(json_path)
|
|
||||||
setup_json = json.loads(setup_json_path.read_text())
|
|
||||||
|
|
||||||
# psd = Path(setup_json['psd']) # path to psd
|
|
||||||
# image_size = setup_json['image_size'] # image size (reduced)
|
|
||||||
# png_dir = Path(setup_json['png_dir']) # path to png directory
|
|
||||||
layers = setup_json['layers'] # dic : name, lbbox, bbox, index, path
|
|
||||||
org_image_size = setup_json['org_image_size'] # original PSD dimensions
|
|
||||||
img_list = [Path(l['path']) for l in layers] # (png_dir /l['name']).with_suffix('.png')
|
|
||||||
|
|
||||||
return img_list, org_image_size
|
|
||||||
|
|
||||||
def setup_bg_camera(image_size, context=None, scn=None, cam_type=None):
|
|
||||||
'''Create background camera from scene active camera according to background image resolution
|
|
||||||
image_size ::
|
|
||||||
cam_type :: wether the BG camera should be set to perspective or orthographic
|
|
||||||
'''
|
|
||||||
context = context or bpy.context
|
|
||||||
scn=scn or context.scene
|
|
||||||
|
|
||||||
movie_resolution = scn.render.resolution_x, scn.render.resolution_y
|
|
||||||
anim_cam = scn.camera
|
|
||||||
anim_cam_scale = 6 # anim_cam.data.ortho_scale
|
|
||||||
anim_cam_focale = 50 # anim_cam.data.lens
|
|
||||||
cam_type = cam_type or anim_cam.data.type
|
|
||||||
|
|
||||||
## scale up plane scale and bg_cam ortho_scale according to film res
|
|
||||||
bg_factor = (anim_cam_scale * image_size[0]) / movie_resolution[0]
|
|
||||||
#print(f'({anim_cam_scale} * {image_size[0]}) / {movie_resolution[0]} = {bg_factor}')
|
|
||||||
|
|
||||||
## scale down the focal according to film res
|
|
||||||
bg_focale = (anim_cam_focale * movie_resolution[0]) / image_size[0]
|
|
||||||
#print(f'({anim_cam_focale} * {movie_resolution[0]}) / {image_size[0]} = {bg_focale}')
|
|
||||||
|
|
||||||
bg_cam = scn.objects.get('bg_cam')
|
|
||||||
if not bg_cam:
|
|
||||||
bg_cam = fn.create_cam(name='bg_cam', type=cam_type, size=bg_factor, focale=bg_focale)
|
|
||||||
bg_cam['resolution'] = image_size
|
|
||||||
|
|
||||||
bg_cam.matrix_world = anim_cam.matrix_world
|
|
||||||
|
|
||||||
bg_cam.hide_select = True
|
|
||||||
bg_cam.lock_location = bg_cam.lock_rotation = bg_cam.lock_scale = [True]*3
|
|
||||||
|
|
||||||
fn.set_collection(bg_cam, 'Camera')
|
|
||||||
fn.set_collection(anim_cam, 'Camera')
|
|
||||||
return bg_cam
|
|
||||||
|
|
||||||
class BPM_OT_import_bg_images(bpy.types.Operator, ImportHelper):
|
|
||||||
bl_idname = "bpm.import_bg_images"
|
|
||||||
bl_label = "Import Background images"
|
|
||||||
bl_description = "Import either a Json, a PSD, multiple files"
|
|
||||||
bl_options = {"REGISTER"} # , "INTERNAL"
|
|
||||||
|
|
||||||
# filename_ext = '.json'
|
|
||||||
|
|
||||||
filter_glob: StringProperty(
|
|
||||||
default=';'.join([f'*{i}' for i in bpy.path.extensions_image]) + ';*.json',
|
|
||||||
options={'HIDDEN'} )
|
|
||||||
|
|
||||||
## Active selection
|
|
||||||
filepath : StringProperty(
|
|
||||||
name="File Path",
|
|
||||||
description="File path used for import",
|
|
||||||
maxlen= 1024) # the active file
|
|
||||||
|
|
||||||
## Handle multi-selection
|
|
||||||
files: CollectionProperty(
|
|
||||||
name="File Path",
|
|
||||||
type=bpy.types.OperatorFileListElement,
|
|
||||||
) # The filelist collection
|
|
||||||
|
|
||||||
## Choice to place before or after ?
|
|
||||||
|
|
||||||
import_type : EnumProperty(
|
|
||||||
name="Import As", description="Type of import to ", default='GPENCIL', options={'ANIMATABLE'},
|
|
||||||
items=(
|
|
||||||
('GPENCIL', 'Gpencil Object', 'Import bg planes as gpencil objects', 0),
|
|
||||||
('EMPTY', 'Empty Reference', 'Import bg planes as empty objects', 1),
|
|
||||||
('MESH', 'Texture Plane', 'Import bg planes as mesh objects', 2),
|
|
||||||
))
|
|
||||||
|
|
||||||
mode : EnumProperty(
|
|
||||||
name="Mode", description="", default='REPLACE', options={'ANIMATABLE'},
|
|
||||||
items=(
|
|
||||||
('REPLACE', 'Replace Existing', 'Replace the image if already exists', 0),
|
|
||||||
('SKIP', 'Skip Existing', 'Skip the import if the image alreaady exists in planes', 1),
|
|
||||||
# ('PURGE', 'Purge', 'When object exists, fully delete it before linking, even associated collection and holder', 2),
|
|
||||||
))
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
org_image_size = None
|
|
||||||
scn = context.scene
|
|
||||||
active_file = Path(self.filepath)
|
|
||||||
|
|
||||||
if len(self.files) == 1 and active_file.suffix.lower() in ('.json', '.psd'):
|
|
||||||
json_path = None
|
|
||||||
print('active_file.suffix.lower(): ', active_file.suffix.lower())
|
|
||||||
if active_file.suffix.lower() == '.psd':
|
|
||||||
print('Is a PSD')
|
|
||||||
## Export layers and create json setup file
|
|
||||||
# Export passes in a 'render' or 'render_hd' folder aside psd
|
|
||||||
json_path = export_psd_bg(str(active_file))
|
|
||||||
|
|
||||||
elif active_file.suffix.lower() == '.json':
|
|
||||||
print('Is a json')
|
|
||||||
# Use json data to batch import
|
|
||||||
json_path = active_file
|
|
||||||
|
|
||||||
if not json_path:
|
|
||||||
self.report({'ERROR'}, 'No json path to load, you can try loading from psd or selecting image file directly')
|
|
||||||
return {'CANCELLED'}
|
|
||||||
|
|
||||||
file_list, org_image_size = get_json_infos(json_path)
|
|
||||||
folder = Path(json_path).parent # render folder
|
|
||||||
|
|
||||||
else:
|
|
||||||
folder = active_file.parent
|
|
||||||
# Filter out json (we may want ot import the PSD as imagelisted in bpy.path.extensions_image)
|
|
||||||
file_list = [folder / f.name for f in self.files if Path(f.name).suffix in bpy.path.extensions_image]
|
|
||||||
|
|
||||||
if not file_list:
|
|
||||||
self.report({'ERROR'}, 'Image file list is empty')
|
|
||||||
return {'CANCELLED'}
|
|
||||||
|
|
||||||
|
|
||||||
## simple_list
|
|
||||||
# existing_backgrounds = [o for o in context.scene.objects if o.get('is_background')]
|
|
||||||
# existing_holders = [o for o in context.scene.objects if o.name.startswith(PREFIX) and o.type == 'MESH' and o.children]
|
|
||||||
|
|
||||||
## Has dict
|
|
||||||
# existing_backgrounds = {o : img_info for o in context.scene.objects if o.get('is_background') and (img_info := o.get('is_background'))}
|
|
||||||
|
|
||||||
# FIXME: Use existing background custom prop? : o.get('is_background')
|
|
||||||
## list of Tuples : [(plane_object, img_data, transparency_value), ...]
|
|
||||||
|
|
||||||
existing_backgrounds = [(o, *img_info) for o in context.scene.objects \
|
|
||||||
if o.get('is_background') and (img_info := fn.get_image_infos_from_object(o)) and o.get('is_background') and o.parent]
|
|
||||||
|
|
||||||
existing_backgrounds.sort(key=lambda x: x[0].parent.location.z, reverse=True) # sort by parent (holder) location Z
|
|
||||||
|
|
||||||
far_plane = INIT_POS
|
|
||||||
if existing_backgrounds:
|
|
||||||
far_plane = existing_backgrounds[-1][0].parent.location.z
|
|
||||||
|
|
||||||
## Ensure bg_cam setup (option to use active camera ?)
|
|
||||||
bg_cam = scn.objects.get('bg_cam')
|
|
||||||
if not bg_cam:
|
|
||||||
if not org_image_size:
|
|
||||||
## Get image size from first file
|
|
||||||
img = bpy.data.images.load(file_list[0], check_existing=True)
|
|
||||||
org_image_size = (img.size[0], img.size[1])
|
|
||||||
bg_cam = setup_bg_camera(
|
|
||||||
org_image_size, context=context, scn=scn, cam_type=scn.camera.data.type)
|
|
||||||
|
|
||||||
## Ensure Background collection
|
|
||||||
backgrounds = fn.get_col(BGCOL) # Create if needed
|
|
||||||
|
|
||||||
for fp in file_list:
|
|
||||||
print(f'Importing {fp.name}')
|
|
||||||
current_holder = None
|
|
||||||
|
|
||||||
file_stem = Path(fp).stem
|
|
||||||
# current_bg = next((o for o if o.parent and fn.get_image_infos_from_object(o)), None)
|
|
||||||
current_bg = next((o for o in existing_backgrounds if o[1].filepath == fp), None)
|
|
||||||
if current_bg:
|
|
||||||
current_holder = current_bg.parent
|
|
||||||
# TODO store opacity or delete existing objects only after loop
|
|
||||||
|
|
||||||
if current_bg and self.mode == 'SKIP':
|
|
||||||
print(f' - SKIP: existing {current_bg.name}')
|
|
||||||
continue
|
|
||||||
|
|
||||||
if current_bg and self.mode == 'REPLACE':
|
|
||||||
print(f' - DEL: existing {current_bg.name}')
|
|
||||||
bpy.data.objects.remove(current_bg)
|
|
||||||
|
|
||||||
# Import image
|
|
||||||
if self.import_type == 'GPENCIL':
|
|
||||||
bg_img = fn.import_image_as_gp_reference(
|
|
||||||
context=context,
|
|
||||||
image=fp,
|
|
||||||
pack_image=False,
|
|
||||||
)
|
|
||||||
elif self.import_type == 'MESH':
|
|
||||||
bg_img = fn.create_image_plane(fp)
|
|
||||||
|
|
||||||
elif self.import_type == 'EMPTY':
|
|
||||||
bg_img = fn.create_empty_image(fp)
|
|
||||||
|
|
||||||
|
|
||||||
bg_img.name = file_stem + '_texgp'
|
|
||||||
bg_img.hide_select = True
|
|
||||||
|
|
||||||
if current_holder:
|
|
||||||
bg_img.parent = current_holder
|
|
||||||
fn.set_collection(bg_img, current_holder.users_collection[0].name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# img, opacity = fn.get_image_infos_from_object(bg_img)
|
|
||||||
print('bg_img: ', bg_img)
|
|
||||||
img = fn.get_image(bg_img)
|
|
||||||
# bg_name = fn.clean_image_name(img.name)
|
|
||||||
file_stem = file_stem
|
|
||||||
|
|
||||||
# Get create collection from image clean name
|
|
||||||
bg_col = fn.get_col(file_stem, parent=backgrounds)
|
|
||||||
|
|
||||||
## Set in collection
|
|
||||||
bg_col.objects.link(bg_img)
|
|
||||||
|
|
||||||
print('img: ', img.name, bg_img.name, bg_img.users_collection)
|
|
||||||
|
|
||||||
## create the holder, parent to camera, set driver and set collection. Could also pass 'fp'
|
|
||||||
holder = fn.create_plane_holder(img, name=PREFIX + file_stem, parent=bg_cam, link_in_col=bg_col)
|
|
||||||
print('holder: ', holder.name)
|
|
||||||
|
|
||||||
fn.create_plane_driver(holder, bg_cam, distance=far_plane)
|
|
||||||
bg_img.parent = holder
|
|
||||||
|
|
||||||
far_plane += 2
|
|
||||||
|
|
||||||
fn.reload_bg_list(scene=scn)
|
|
||||||
self.report({'INFO'}, f'Settings loaded from: {os.path.basename(self.filepath)}')
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
classes=(
|
|
||||||
BPM_OT_import_bg_images,
|
|
||||||
)
|
|
||||||
|
|
||||||
def register():
|
|
||||||
for cls in classes:
|
|
||||||
bpy.utils.register_class(cls)
|
|
||||||
|
|
||||||
def unregister():
|
|
||||||
for cls in reversed(classes):
|
|
||||||
bpy.utils.unregister_class(cls)
|
|
|
@ -6,7 +6,7 @@ import mathutils
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from mathutils import Matrix, Vector
|
from mathutils import Matrix, Vector
|
||||||
|
|
||||||
from .. import fn
|
from .. import core
|
||||||
|
|
||||||
|
|
||||||
def set_resolution_from_cam_prop(cam=None):
|
def set_resolution_from_cam_prop(cam=None):
|
||||||
|
@ -292,8 +292,8 @@ class BPM_OT_create_and_place_in_camera(Operator):
|
||||||
self.create = False
|
self.create = False
|
||||||
|
|
||||||
## Set placeholder name (Comment to let an empty string)
|
## Set placeholder name (Comment to let an empty string)
|
||||||
self.name = fn.placeholder_name(self.name, context)
|
self.name = core.placeholder_name(self.name, context)
|
||||||
prefs = fn.get_addon_prefs()
|
prefs = core.get_addon_prefs()
|
||||||
self.use_light = prefs.use_light
|
self.use_light = prefs.use_light
|
||||||
self.edit_line_opacity = prefs.edit_line_opacity
|
self.edit_line_opacity = prefs.edit_line_opacity
|
||||||
|
|
||||||
|
@ -306,9 +306,9 @@ class BPM_OT_create_and_place_in_camera(Operator):
|
||||||
|
|
||||||
if settings.planes and settings.planes[settings.index].plane:
|
if settings.planes and settings.planes[settings.index].plane:
|
||||||
plane = settings.planes[settings.index].plane
|
plane = settings.planes[settings.index].plane
|
||||||
self.distance = fn.coord_distance_from_cam_straight(plane.matrix_world.to_translation()) - 0.005
|
self.distance = core.coord_distance_from_cam_straight(plane.matrix_world.to_translation()) - 0.005
|
||||||
else:
|
else:
|
||||||
self.distance = fn.coord_distance_from_cam_straight(context.scene.cursor.location)
|
self.distance = core.coord_distance_from_cam_straight(context.scene.cursor.location)
|
||||||
self.distance = max([1.0, self.distance]) # minimum one meter away from cam
|
self.distance = max([1.0, self.distance]) # minimum one meter away from cam
|
||||||
|
|
||||||
if self.create:
|
if self.create:
|
||||||
|
@ -331,10 +331,10 @@ class BPM_OT_create_and_place_in_camera(Operator):
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
if self.create:
|
if self.create:
|
||||||
ob_name = fn.placeholder_name(self.name, context)
|
ob_name = core.placeholder_name(self.name, context)
|
||||||
|
|
||||||
## Create Object
|
## Create Object
|
||||||
prefs = fn.get_addon_prefs()
|
prefs = core.get_addon_prefs()
|
||||||
gp_data = bpy.data.grease_pencils.new(ob_name)
|
gp_data = bpy.data.grease_pencils.new(ob_name)
|
||||||
ob = bpy.data.objects.new(ob_name, gp_data)
|
ob = bpy.data.objects.new(ob_name, gp_data)
|
||||||
ob.use_grease_pencil_lights = prefs.use_light
|
ob.use_grease_pencil_lights = prefs.use_light
|
||||||
|
@ -342,7 +342,7 @@ class BPM_OT_create_and_place_in_camera(Operator):
|
||||||
l = gp_data.layers.new('GP_Layer')
|
l = gp_data.layers.new('GP_Layer')
|
||||||
l.frames.new(context.scene.frame_current)
|
l.frames.new(context.scene.frame_current)
|
||||||
|
|
||||||
fn.set_collection(ob, 'GP') # Gpencils
|
core.set_collection(ob, 'GP') # Gpencils
|
||||||
|
|
||||||
# Add to bg_plane collection
|
# Add to bg_plane collection
|
||||||
new_item = context.scene.bg_props.planes.add()
|
new_item = context.scene.bg_props.planes.add()
|
||||||
|
@ -351,7 +351,7 @@ class BPM_OT_create_and_place_in_camera(Operator):
|
||||||
|
|
||||||
# Set active on last
|
# Set active on last
|
||||||
context.scene.bg_props.index = len(context.scene.bg_props.planes) - 1
|
context.scene.bg_props.index = len(context.scene.bg_props.planes) - 1
|
||||||
fn.gp_transfer_mode(ob)
|
core.gp_transfer_mode(ob)
|
||||||
|
|
||||||
loaded_palette = False
|
loaded_palette = False
|
||||||
if hasattr(bpy.types, "GPTB_OT_load_default_palette"):
|
if hasattr(bpy.types, "GPTB_OT_load_default_palette"):
|
||||||
|
|
|
@ -5,7 +5,7 @@ from bpy.types import Operator
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
from os.path import abspath
|
from os.path import abspath
|
||||||
|
|
||||||
from .. import fn
|
from .. import core
|
||||||
from .. constants import BGCOL
|
from .. constants import BGCOL
|
||||||
|
|
||||||
## Open image folder
|
## Open image folder
|
||||||
|
@ -39,7 +39,7 @@ class BPM_OT_open_bg_folder(Operator):
|
||||||
self.report({'ERROR'}, f'Could not found child for holder: {ob.name}')
|
self.report({'ERROR'}, f'Could not found child for holder: {ob.name}')
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
img = fn.get_image(tex_obj)
|
img = core.get_image(tex_obj)
|
||||||
fp = Path(abspath(bpy.path.abspath(img.filepath)))
|
fp = Path(abspath(bpy.path.abspath(img.filepath)))
|
||||||
if not fp.exists():
|
if not fp.exists():
|
||||||
self.report({'ERROR'}, f'Not found: {fp}')
|
self.report({'ERROR'}, f'Not found: {fp}')
|
||||||
|
@ -290,7 +290,7 @@ class BPM_OT_reload(Operator):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
error = fn.reload_bg_list()
|
error = core.reload_bg_list()
|
||||||
if error:
|
if error:
|
||||||
if isinstance(error, list):
|
if isinstance(error, list):
|
||||||
self.report({'WARNING'}, 'Wrong name for some object, see console:' + '\n'.join(error))
|
self.report({'WARNING'}, 'Wrong name for some object, see console:' + '\n'.join(error))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import bpy
|
import bpy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from .. import fn
|
from .. import core
|
||||||
from .. constants import PREFIX
|
from .. constants import PREFIX
|
||||||
from bpy.types import UIList, PropertyGroup, Menu
|
from bpy.types import UIList, PropertyGroup, Menu
|
||||||
from bpy.props import (PointerProperty,
|
from bpy.props import (PointerProperty,
|
||||||
|
@ -51,7 +51,7 @@ class BPM_UL_bg_list(UIList):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
layercol = context.view_layer.layer_collection.children['Background'].children.get(fn.clean_image_name(item.plane.name[len(PREFIX):]))
|
layercol = context.view_layer.layer_collection.children['Background'].children.get(core.clean_image_name(item.plane.name[len(PREFIX):]))
|
||||||
if not layercol:
|
if not layercol:
|
||||||
layout.label(text=f'{item.plane.name} (problem with name)', icon='ERROR')
|
layout.label(text=f'{item.plane.name} (problem with name)', icon='ERROR')
|
||||||
return
|
return
|
||||||
|
@ -63,7 +63,7 @@ class BPM_UL_bg_list(UIList):
|
||||||
layout.label(text=f'{item.plane.name} (No children)', icon='ERROR')
|
layout.label(text=f'{item.plane.name} (No children)', icon='ERROR')
|
||||||
|
|
||||||
## Image preview
|
## Image preview
|
||||||
image = fn.get_image(item.plane.children[0])
|
image = core.get_image(item.plane.children[0])
|
||||||
# layout.label(icon_value=image.preview_ensure().icon_id)
|
# layout.label(icon_value=image.preview_ensure().icon_id)
|
||||||
# layout.template_icon(icon_value=image.preview_ensure().icon_id)
|
# layout.template_icon(icon_value=image.preview_ensure().icon_id)
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ class BPM_UL_bg_list(UIList):
|
||||||
## TODO: Find a better solution to get the collection
|
## TODO: Find a better solution to get the collection
|
||||||
## Get Collection from plane name -> problem: prefix "BG_" and suffix
|
## Get Collection from plane name -> problem: prefix "BG_" and suffix
|
||||||
|
|
||||||
layercol = context.view_layer.layer_collection.children['Background'].children.get(fn.clean_image_name(item.plane.name[len(PREFIX):]))
|
layercol = context.view_layer.layer_collection.children['Background'].children.get(core.clean_image_name(item.plane.name[len(PREFIX):]))
|
||||||
if not layercol:
|
if not layercol:
|
||||||
layout.label(text=f'{item.plane.name} (problem with name)', icon='ERROR')
|
layout.label(text=f'{item.plane.name} (problem with name)', icon='ERROR')
|
||||||
return
|
return
|
||||||
|
@ -181,7 +181,7 @@ class BPM_UL_bg_list(UIList):
|
||||||
layout.label(text=f'{item.plane.name} (No children)', icon='ERROR')
|
layout.label(text=f'{item.plane.name} (No children)', icon='ERROR')
|
||||||
|
|
||||||
## Image preview
|
## Image preview
|
||||||
image = fn.get_image(item.plane.children[0])
|
image = core.get_image(item.plane.children[0])
|
||||||
# layout.label(icon_value=image.preview_ensure().icon_id)
|
# layout.label(icon_value=image.preview_ensure().icon_id)
|
||||||
# layout.template_icon(icon_value=image.preview_ensure().icon_id)
|
# layout.template_icon(icon_value=image.preview_ensure().icon_id)
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ def update_opacity(self, context):
|
||||||
for ob in pool:
|
for ob in pool:
|
||||||
if not ob or not ob.children:
|
if not ob or not ob.children:
|
||||||
continue
|
continue
|
||||||
fn.set_opacity(ob.children[0], opacity=context.scene.bg_props.opacity)
|
core.set_opacity(ob.children[0], opacity=context.scene.bg_props.opacity)
|
||||||
|
|
||||||
def update_on_index_change(self, context):
|
def update_on_index_change(self, context):
|
||||||
# print('index change:', context.scene.bg_props.index)
|
# print('index change:', context.scene.bg_props.index)
|
||||||
|
@ -287,13 +287,13 @@ def update_on_index_change(self, context):
|
||||||
plane = item.plane
|
plane = item.plane
|
||||||
if not plane.children:
|
if not plane.children:
|
||||||
return
|
return
|
||||||
opacity = fn.get_opacity(plane.children[0])
|
opacity = core.get_opacity(plane.children[0])
|
||||||
if not opacity:
|
if not opacity:
|
||||||
return
|
return
|
||||||
props['opacity'] = opacity
|
props['opacity'] = opacity
|
||||||
|
|
||||||
elif item.type == 'obj':
|
elif item.type == 'obj':
|
||||||
fn.gp_transfer_mode(item.plane, context)
|
core.gp_transfer_mode(item.plane, context)
|
||||||
|
|
||||||
|
|
||||||
def update_select(self, context):
|
def update_select(self, context):
|
||||||
|
|
Loading…
Reference in New Issue