Merge branch 'develop' into feature/unreal-load_layout

This commit is contained in:
Simone Barbieri 2021-11-09 10:00:48 +00:00
commit 3bea96386b
171 changed files with 16621 additions and 1476 deletions

View file

@ -0,0 +1,217 @@
"""Load audio in Blender."""
from pathlib import Path
from pprint import pformat
from typing import Dict, List, Optional
import bpy
from avalon import api
from avalon.blender.pipeline import AVALON_CONTAINERS
from avalon.blender.pipeline import AVALON_CONTAINER_ID
from avalon.blender.pipeline import AVALON_PROPERTY
from openpype.hosts.blender.api import plugin
class AudioLoader(plugin.AssetLoader):
"""Load audio in Blender."""
families = ["audio"]
representations = ["wav"]
label = "Load Audio"
icon = "volume-up"
color = "orange"
def process_asset(
self, context: dict, name: str, namespace: Optional[str] = None,
options: Optional[Dict] = None
) -> Optional[List]:
"""
Arguments:
name: Use pre-defined name
namespace: Use pre-defined namespace
context: Full parenthood of representation to load
options: Additional settings dictionary
"""
libpath = self.fname
asset = context["asset"]["name"]
subset = context["subset"]["name"]
asset_name = plugin.asset_name(asset, subset)
unique_number = plugin.get_unique_number(asset, subset)
group_name = plugin.asset_name(asset, subset, unique_number)
namespace = namespace or f"{asset}_{unique_number}"
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
if not avalon_container:
avalon_container = bpy.data.collections.new(name=AVALON_CONTAINERS)
bpy.context.scene.collection.children.link(avalon_container)
asset_group = bpy.data.objects.new(group_name, object_data=None)
avalon_container.objects.link(asset_group)
# Blender needs the Sequence Editor in the current window, to be able
# to load the audio. We take one of the areas in the window, save its
# type, and switch to the Sequence Editor. After loading the audio,
# we switch back to the previous area.
window_manager = bpy.context.window_manager
old_type = window_manager.windows[-1].screen.areas[0].type
window_manager.windows[-1].screen.areas[0].type = "SEQUENCE_EDITOR"
# We override the context to load the audio in the sequence editor.
oc = bpy.context.copy()
oc["area"] = window_manager.windows[-1].screen.areas[0]
bpy.ops.sequencer.sound_strip_add(oc, filepath=libpath, frame_start=1)
window_manager.windows[-1].screen.areas[0].type = old_type
p = Path(libpath)
audio = p.name
asset_group[AVALON_PROPERTY] = {
"schema": "openpype:container-2.0",
"id": AVALON_CONTAINER_ID,
"name": name,
"namespace": namespace or '',
"loader": str(self.__class__.__name__),
"representation": str(context["representation"]["_id"]),
"libpath": libpath,
"asset_name": asset_name,
"parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"],
"objectName": group_name,
"audio": audio
}
objects = []
self[:] = objects
return [objects]
def exec_update(self, container: Dict, representation: Dict):
"""Update an audio strip in the sequence editor.
Arguments:
container (openpype:container-1.0): Container to update,
from `host.ls()`.
representation (openpype:representation-1.0): Representation to
update, from `host.ls()`.
"""
object_name = container["objectName"]
asset_group = bpy.data.objects.get(object_name)
libpath = Path(api.get_representation_path(representation))
self.log.info(
"Container: %s\nRepresentation: %s",
pformat(container, indent=2),
pformat(representation, indent=2),
)
assert asset_group, (
f"The asset is not loaded: {container['objectName']}"
)
assert libpath, (
"No existing library file found for {container['objectName']}"
)
assert libpath.is_file(), (
f"The file doesn't exist: {libpath}"
)
metadata = asset_group.get(AVALON_PROPERTY)
group_libpath = metadata["libpath"]
normalized_group_libpath = (
str(Path(bpy.path.abspath(group_libpath)).resolve())
)
normalized_libpath = (
str(Path(bpy.path.abspath(str(libpath))).resolve())
)
self.log.debug(
"normalized_group_libpath:\n %s\nnormalized_libpath:\n %s",
normalized_group_libpath,
normalized_libpath,
)
if normalized_group_libpath == normalized_libpath:
self.log.info("Library already loaded, not updating...")
return
old_audio = container["audio"]
p = Path(libpath)
new_audio = p.name
# Blender needs the Sequence Editor in the current window, to be able
# to update the audio. We take one of the areas in the window, save its
# type, and switch to the Sequence Editor. After updating the audio,
# we switch back to the previous area.
window_manager = bpy.context.window_manager
old_type = window_manager.windows[-1].screen.areas[0].type
window_manager.windows[-1].screen.areas[0].type = "SEQUENCE_EDITOR"
# We override the context to load the audio in the sequence editor.
oc = bpy.context.copy()
oc["area"] = window_manager.windows[-1].screen.areas[0]
# We deselect all sequencer strips, and then select the one we
# need to remove.
bpy.ops.sequencer.select_all(oc, action='DESELECT')
scene = bpy.context.scene
scene.sequence_editor.sequences_all[old_audio].select = True
bpy.ops.sequencer.delete(oc)
bpy.data.sounds.remove(bpy.data.sounds[old_audio])
bpy.ops.sequencer.sound_strip_add(
oc, filepath=str(libpath), frame_start=1)
window_manager.windows[-1].screen.areas[0].type = old_type
metadata["libpath"] = str(libpath)
metadata["representation"] = str(representation["_id"])
metadata["parent"] = str(representation["parent"])
metadata["audio"] = new_audio
def exec_remove(self, container: Dict) -> bool:
"""Remove an audio strip from the sequence editor and the container.
Arguments:
container (openpype:container-1.0): Container to remove,
from `host.ls()`.
Returns:
bool: Whether the container was deleted.
"""
object_name = container["objectName"]
asset_group = bpy.data.objects.get(object_name)
if not asset_group:
return False
audio = container["audio"]
# Blender needs the Sequence Editor in the current window, to be able
# to remove the audio. We take one of the areas in the window, save its
# type, and switch to the Sequence Editor. After removing the audio,
# we switch back to the previous area.
window_manager = bpy.context.window_manager
old_type = window_manager.windows[-1].screen.areas[0].type
window_manager.windows[-1].screen.areas[0].type = "SEQUENCE_EDITOR"
# We override the context to load the audio in the sequence editor.
oc = bpy.context.copy()
oc["area"] = window_manager.windows[-1].screen.areas[0]
# We deselect all sequencer strips, and then select the one we
# need to remove.
bpy.ops.sequencer.select_all(oc, action='DESELECT')
bpy.context.scene.sequence_editor.sequences_all[audio].select = True
bpy.ops.sequencer.delete(oc)
window_manager.windows[-1].screen.areas[0].type = old_type
bpy.data.sounds.remove(bpy.data.sounds[audio])
bpy.data.objects.remove(asset_group)
return True

View file

@ -37,7 +37,8 @@ class ExtractBlend(openpype.api.Extractor):
if tree.type == 'SHADER':
for node in tree.nodes:
if node.bl_idname == 'ShaderNodeTexImage':
node.image.pack()
if node.image:
node.image.pack()
bpy.data.libraries.write(filepath, data_blocks)