mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 21:32:15 +01:00
Merge branch 'develop' of https://github.com/pypeclub/OpenPype into feature/multiverse
This commit is contained in:
commit
0bf37ddffc
259 changed files with 4653 additions and 1939 deletions
65
CHANGELOG.md
65
CHANGELOG.md
|
|
@ -1,13 +1,65 @@
|
|||
# Changelog
|
||||
|
||||
## [3.9.0-nightly.9](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||
## [3.9.2-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.2...HEAD)
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.9.1...HEAD)
|
||||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- CI: change the version bump logic [\#2919](https://github.com/pypeclub/OpenPype/pull/2919)
|
||||
- Deadline: Add headless argument [\#2916](https://github.com/pypeclub/OpenPype/pull/2916)
|
||||
- Ftrack: Fill workfile in custom attribute [\#2906](https://github.com/pypeclub/OpenPype/pull/2906)
|
||||
- Settings UI: Add simple tooltips for settings entities [\#2901](https://github.com/pypeclub/OpenPype/pull/2901)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- Ftrack: Missing Ftrack id after editorial publish [\#2905](https://github.com/pypeclub/OpenPype/pull/2905)
|
||||
- AfterEffects: Fix rendering for single frame in DL [\#2875](https://github.com/pypeclub/OpenPype/pull/2875)
|
||||
|
||||
**🔀 Refactored code**
|
||||
|
||||
- General: Move formatting and workfile functions [\#2914](https://github.com/pypeclub/OpenPype/pull/2914)
|
||||
|
||||
## [3.9.1](https://github.com/pypeclub/OpenPype/tree/3.9.1) (2022-03-18)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.9.1-nightly.3...3.9.1)
|
||||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- General: Change how OPENPYPE\_DEBUG value is handled [\#2907](https://github.com/pypeclub/OpenPype/pull/2907)
|
||||
- nuke: imageio adding ocio config version 1.2 [\#2897](https://github.com/pypeclub/OpenPype/pull/2897)
|
||||
- Flame: support for comment with xml attribute overrides [\#2892](https://github.com/pypeclub/OpenPype/pull/2892)
|
||||
- Nuke: ExtractReviewSlate can handle more codes and profiles [\#2879](https://github.com/pypeclub/OpenPype/pull/2879)
|
||||
- Flame: sequence used for reference video [\#2869](https://github.com/pypeclub/OpenPype/pull/2869)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- General: Fix use of Anatomy roots [\#2904](https://github.com/pypeclub/OpenPype/pull/2904)
|
||||
- Fixing gap detection in extract review [\#2902](https://github.com/pypeclub/OpenPype/pull/2902)
|
||||
- Pyblish Pype - ensure current state is correct when entering new group order [\#2899](https://github.com/pypeclub/OpenPype/pull/2899)
|
||||
- SceneInventory: Fix import of load function [\#2894](https://github.com/pypeclub/OpenPype/pull/2894)
|
||||
- Harmony - fixed creator issue [\#2891](https://github.com/pypeclub/OpenPype/pull/2891)
|
||||
- General: Remove forgotten use of avalon Creator [\#2885](https://github.com/pypeclub/OpenPype/pull/2885)
|
||||
- General: Avoid circular import [\#2884](https://github.com/pypeclub/OpenPype/pull/2884)
|
||||
- Fixes for attaching loaded containers \(\#2837\) [\#2874](https://github.com/pypeclub/OpenPype/pull/2874)
|
||||
|
||||
**🔀 Refactored code**
|
||||
|
||||
- General: Reduce style usage to OpenPype repository [\#2889](https://github.com/pypeclub/OpenPype/pull/2889)
|
||||
- General: Move loader logic from avalon to openpype [\#2886](https://github.com/pypeclub/OpenPype/pull/2886)
|
||||
|
||||
## [3.9.0](https://github.com/pypeclub/OpenPype/tree/3.9.0) (2022-03-14)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.9.0-nightly.9...3.9.0)
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
- AssetCreator: Remove the tool [\#2845](https://github.com/pypeclub/OpenPype/pull/2845)
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Documentation: Change Photoshop & AfterEffects plugin path [\#2878](https://github.com/pypeclub/OpenPype/pull/2878)
|
||||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- General: Subset name filtering in ExtractReview outpus [\#2872](https://github.com/pypeclub/OpenPype/pull/2872)
|
||||
|
|
@ -27,6 +79,7 @@
|
|||
|
||||
- General: Missing time function [\#2877](https://github.com/pypeclub/OpenPype/pull/2877)
|
||||
- Deadline: Fix plugin name for tile assemble [\#2868](https://github.com/pypeclub/OpenPype/pull/2868)
|
||||
- Nuke: gizmo precollect fix [\#2866](https://github.com/pypeclub/OpenPype/pull/2866)
|
||||
- General: Fix hardlink for windows [\#2864](https://github.com/pypeclub/OpenPype/pull/2864)
|
||||
- General: ffmpeg was crashing on slate merge [\#2860](https://github.com/pypeclub/OpenPype/pull/2860)
|
||||
- WebPublisher: Video file was published with one too many frame [\#2858](https://github.com/pypeclub/OpenPype/pull/2858)
|
||||
|
|
@ -35,11 +88,13 @@
|
|||
- Nuke: slate resolution to input video resolution [\#2853](https://github.com/pypeclub/OpenPype/pull/2853)
|
||||
- WebPublisher: Fix username stored in DB [\#2852](https://github.com/pypeclub/OpenPype/pull/2852)
|
||||
- WebPublisher: Fix wrong number of frames for video file [\#2851](https://github.com/pypeclub/OpenPype/pull/2851)
|
||||
- Nuke: Fix family test in validate\_write\_legacy to work with stillImage [\#2847](https://github.com/pypeclub/OpenPype/pull/2847)
|
||||
- Nuke: fix multiple baking profile farm publishing [\#2842](https://github.com/pypeclub/OpenPype/pull/2842)
|
||||
- Blender: Fixed parameters for FBX export of the camera [\#2840](https://github.com/pypeclub/OpenPype/pull/2840)
|
||||
- Maya: Stop creation of reviews for Cryptomattes [\#2832](https://github.com/pypeclub/OpenPype/pull/2832)
|
||||
- Deadline: Remove recreated event [\#2828](https://github.com/pypeclub/OpenPype/pull/2828)
|
||||
- Deadline: Added missing events folder [\#2827](https://github.com/pypeclub/OpenPype/pull/2827)
|
||||
- Maya: Deformer node ids validation plugin [\#2826](https://github.com/pypeclub/OpenPype/pull/2826)
|
||||
- Settings: Missing document with OP versions may break start of OpenPype [\#2825](https://github.com/pypeclub/OpenPype/pull/2825)
|
||||
- Deadline: more detailed temp file name for environment json [\#2824](https://github.com/pypeclub/OpenPype/pull/2824)
|
||||
- General: Host name was formed from obsolete code [\#2821](https://github.com/pypeclub/OpenPype/pull/2821)
|
||||
|
|
@ -57,12 +112,6 @@
|
|||
- General: Move change context functions [\#2839](https://github.com/pypeclub/OpenPype/pull/2839)
|
||||
- Tools: Don't use avalon tools code [\#2829](https://github.com/pypeclub/OpenPype/pull/2829)
|
||||
- Move Unreal Implementation to OpenPype [\#2823](https://github.com/pypeclub/OpenPype/pull/2823)
|
||||
- General: Extract template formatting from anatomy [\#2766](https://github.com/pypeclub/OpenPype/pull/2766)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Nuke: gizmo precollect fix [\#2866](https://github.com/pypeclub/OpenPype/pull/2866)
|
||||
- Nuke: Fix family test in validate\_write\_legacy to work with stillImage [\#2847](https://github.com/pypeclub/OpenPype/pull/2847)
|
||||
|
||||
## [3.8.2](https://github.com/pypeclub/OpenPype/tree/3.8.2) (2022-02-07)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import platform
|
|||
import functools
|
||||
import logging
|
||||
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from .settings import get_project_settings
|
||||
from .lib import (
|
||||
Anatomy,
|
||||
|
|
@ -76,6 +75,11 @@ def install():
|
|||
"""Install Pype to Avalon."""
|
||||
from pyblish.lib import MessageHandler
|
||||
from openpype.modules import load_modules
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
register_inventory_action,
|
||||
)
|
||||
from avalon import pipeline
|
||||
|
||||
# Make sure modules are loaded
|
||||
|
|
@ -91,7 +95,7 @@ def install():
|
|||
log.info("Registering global plug-ins..")
|
||||
pyblish.register_plugin_path(PUBLISH_PATH)
|
||||
pyblish.register_discovery_filter(filter_pyblish_plugins)
|
||||
avalon.register_plugin_path(avalon.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
|
||||
project_name = os.environ.get("AVALON_PROJECT")
|
||||
|
||||
|
|
@ -119,9 +123,9 @@ def install():
|
|||
continue
|
||||
|
||||
pyblish.register_plugin_path(path)
|
||||
avalon.register_plugin_path(avalon.Loader, path)
|
||||
register_loader_plugin_path(path)
|
||||
avalon.register_plugin_path(LegacyCreator, path)
|
||||
avalon.register_plugin_path(avalon.InventoryAction, path)
|
||||
register_inventory_action(path)
|
||||
|
||||
# apply monkey patched discover to original one
|
||||
log.info("Patching discovery")
|
||||
|
|
@ -139,10 +143,12 @@ def _on_task_change():
|
|||
@import_wrapper
|
||||
def uninstall():
|
||||
"""Uninstall Pype from Avalon."""
|
||||
from openpype.pipeline import deregister_loader_plugin_path
|
||||
|
||||
log.info("Deregistering global plug-ins..")
|
||||
pyblish.deregister_plugin_path(PUBLISH_PATH)
|
||||
pyblish.deregister_discovery_filter(filter_pyblish_plugins)
|
||||
avalon.deregister_plugin_path(avalon.Loader, LOAD_PATH)
|
||||
deregister_loader_plugin_path(LOAD_PATH)
|
||||
log.info("Global plug-ins unregistred")
|
||||
|
||||
# restore original discover
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ def eventserver(debug,
|
|||
on linux and window service).
|
||||
"""
|
||||
if debug:
|
||||
os.environ['OPENPYPE_DEBUG'] = "3"
|
||||
os.environ["OPENPYPE_DEBUG"] = "1"
|
||||
|
||||
PypeCommands().launch_eventservercli(
|
||||
ftrack_url,
|
||||
|
|
@ -128,7 +128,7 @@ def webpublisherwebserver(debug, executable, upload_dir, host=None, port=None):
|
|||
Expect "pype.club" user created on Ftrack.
|
||||
"""
|
||||
if debug:
|
||||
os.environ['OPENPYPE_DEBUG'] = "3"
|
||||
os.environ["OPENPYPE_DEBUG"] = "1"
|
||||
|
||||
PypeCommands().launch_webpublisher_webservercli(
|
||||
upload_dir=upload_dir,
|
||||
|
|
@ -176,7 +176,7 @@ def publish(debug, paths, targets, gui):
|
|||
More than one path is allowed.
|
||||
"""
|
||||
if debug:
|
||||
os.environ['OPENPYPE_DEBUG'] = '3'
|
||||
os.environ["OPENPYPE_DEBUG"] = "1"
|
||||
PypeCommands.publish(list(paths), targets, gui)
|
||||
|
||||
|
||||
|
|
@ -195,7 +195,7 @@ def remotepublishfromapp(debug, project, path, host, user=None, targets=None):
|
|||
More than one path is allowed.
|
||||
"""
|
||||
if debug:
|
||||
os.environ['OPENPYPE_DEBUG'] = '3'
|
||||
os.environ["OPENPYPE_DEBUG"] = "1"
|
||||
PypeCommands.remotepublishfromapp(
|
||||
project, path, host, user, targets=targets
|
||||
)
|
||||
|
|
@ -215,7 +215,7 @@ def remotepublish(debug, project, path, user=None, targets=None):
|
|||
More than one path is allowed.
|
||||
"""
|
||||
if debug:
|
||||
os.environ['OPENPYPE_DEBUG'] = '3'
|
||||
os.environ["OPENPYPE_DEBUG"] = "1"
|
||||
PypeCommands.remotepublish(project, path, user, targets=targets)
|
||||
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ def texturecopy(debug, project, asset, path):
|
|||
Nothing is written to database.
|
||||
"""
|
||||
if debug:
|
||||
os.environ['OPENPYPE_DEBUG'] = '3'
|
||||
os.environ["OPENPYPE_DEBUG"] = "1"
|
||||
PypeCommands().texture_copy(project, asset, path)
|
||||
|
||||
|
||||
|
|
@ -409,7 +409,7 @@ def syncserver(debug, active_site):
|
|||
var OPENPYPE_LOCAL_ID set to 'active_site'.
|
||||
"""
|
||||
if debug:
|
||||
os.environ['OPENPYPE_DEBUG'] = '3'
|
||||
os.environ["OPENPYPE_DEBUG"] = "1"
|
||||
PypeCommands().syncserver(active_site)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,20 @@ import os
|
|||
import sys
|
||||
|
||||
from Qt import QtWidgets
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
import pyblish.api
|
||||
import avalon.api
|
||||
from avalon import io, pipeline
|
||||
from avalon import io
|
||||
|
||||
from openpype import lib
|
||||
from openpype.api import Logger
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
deregister_loader_plugin_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
import openpype.hosts.aftereffects
|
||||
from openpype.lib import register_event_callback
|
||||
|
||||
|
|
@ -25,7 +31,6 @@ PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
|
|||
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
|
||||
LOAD_PATH = os.path.join(PLUGINS_DIR, "load")
|
||||
CREATE_PATH = os.path.join(PLUGINS_DIR, "create")
|
||||
INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory")
|
||||
|
||||
|
||||
def check_inventory():
|
||||
|
|
@ -38,7 +43,7 @@ def check_inventory():
|
|||
representation = container['representation']
|
||||
representation_doc = io.find_one(
|
||||
{
|
||||
"_id": io.ObjectId(representation),
|
||||
"_id": ObjectId(representation),
|
||||
"type": "representation"
|
||||
},
|
||||
projection={"parent": True}
|
||||
|
|
@ -67,7 +72,7 @@ def install():
|
|||
pyblish.api.register_host("aftereffects")
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
|
||||
avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.register_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
log.info(PUBLISH_PATH)
|
||||
|
||||
|
|
@ -80,7 +85,7 @@ def install():
|
|||
|
||||
def uninstall():
|
||||
pyblish.api.deregister_plugin_path(PUBLISH_PATH)
|
||||
avalon.api.deregister_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
deregister_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.deregister_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
|
||||
|
||||
|
|
@ -145,7 +150,7 @@ def containerise(name,
|
|||
"""
|
||||
data = {
|
||||
"schema": "openpype:container-2.0",
|
||||
"id": pipeline.AVALON_CONTAINER_ID,
|
||||
"id": AVALON_CONTAINER_ID,
|
||||
"name": name,
|
||||
"namespace": namespace,
|
||||
"loader": str(loader),
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import avalon.api
|
||||
from openpype.pipeline import LoaderPlugin
|
||||
from .launch_logic import get_stub
|
||||
|
||||
|
||||
class AfterEffectsLoader(avalon.api.Loader):
|
||||
class AfterEffectsLoader(LoaderPlugin):
|
||||
@staticmethod
|
||||
def get_stub():
|
||||
return get_stub()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"""Host API required Work Files tool"""
|
||||
import os
|
||||
|
||||
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS
|
||||
from .launch_logic import get_stub
|
||||
from avalon import api
|
||||
|
||||
|
||||
def _active_document():
|
||||
|
|
@ -14,7 +14,7 @@ def _active_document():
|
|||
|
||||
|
||||
def file_extensions():
|
||||
return api.HOST_WORKFILE_EXTENSIONS["aftereffects"]
|
||||
return HOST_WORKFILE_EXTENSIONS["aftereffects"]
|
||||
|
||||
|
||||
def has_unsaved_changes():
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import re
|
||||
|
||||
import avalon.api
|
||||
|
||||
from openpype.lib import (
|
||||
get_background_layers,
|
||||
get_unique_layer_name
|
||||
)
|
||||
from openpype.pipeline import get_representation_path
|
||||
from openpype.hosts.aftereffects.api import (
|
||||
AfterEffectsLoader,
|
||||
containerise
|
||||
|
|
@ -78,7 +77,7 @@ class BackgroundLoader(AfterEffectsLoader):
|
|||
else: # switching version - keep same name
|
||||
comp_name = container["namespace"]
|
||||
|
||||
path = avalon.api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
|
||||
layers = get_background_layers(path)
|
||||
comp = stub.reload_background(container["members"][1],
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import re
|
||||
|
||||
import avalon.api
|
||||
from openpype import lib
|
||||
|
||||
from openpype.pipeline import get_representation_path
|
||||
from openpype.hosts.aftereffects.api import (
|
||||
AfterEffectsLoader,
|
||||
containerise
|
||||
|
|
@ -92,7 +92,7 @@ class FileLoader(AfterEffectsLoader):
|
|||
"{}_{}".format(context["asset"], context["subset"]))
|
||||
else: # switching version - keep same name
|
||||
layer_name = container["namespace"]
|
||||
path = avalon.api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
# with aftereffects.maintained_selection(): # TODO
|
||||
stub.replace_item(layer.id, path, stub.LOADED_ICON + layer_name)
|
||||
stub.imprint(
|
||||
|
|
|
|||
|
|
@ -328,7 +328,6 @@ class LaunchWorkFiles(LaunchQtApp):
|
|||
result = super().execute(context)
|
||||
self._window.set_context({
|
||||
"asset": avalon.api.Session["AVALON_ASSET"],
|
||||
"silo": avalon.api.Session["AVALON_SILO"],
|
||||
"task": avalon.api.Session["AVALON_TASK"]
|
||||
})
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -12,9 +12,13 @@ from . import ops
|
|||
import pyblish.api
|
||||
import avalon.api
|
||||
from avalon import io, schema
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
deregister_loader_plugin_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.api import Logger
|
||||
from openpype.lib import (
|
||||
register_event_callback,
|
||||
|
|
@ -27,7 +31,6 @@ PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
|
|||
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
|
||||
LOAD_PATH = os.path.join(PLUGINS_DIR, "load")
|
||||
CREATE_PATH = os.path.join(PLUGINS_DIR, "create")
|
||||
INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory")
|
||||
|
||||
ORIGINAL_EXCEPTHOOK = sys.excepthook
|
||||
|
||||
|
|
@ -50,7 +53,7 @@ def install():
|
|||
pyblish.api.register_host("blender")
|
||||
pyblish.api.register_plugin_path(str(PUBLISH_PATH))
|
||||
|
||||
avalon.api.register_plugin_path(avalon.api.Loader, str(LOAD_PATH))
|
||||
register_loader_plugin_path(str(LOAD_PATH))
|
||||
avalon.api.register_plugin_path(LegacyCreator, str(CREATE_PATH))
|
||||
|
||||
lib.append_user_scripts()
|
||||
|
|
@ -72,7 +75,7 @@ def uninstall():
|
|||
pyblish.api.deregister_host("blender")
|
||||
pyblish.api.deregister_plugin_path(str(PUBLISH_PATH))
|
||||
|
||||
avalon.api.deregister_plugin_path(avalon.api.Loader, str(LOAD_PATH))
|
||||
deregister_loader_plugin_path(str(LOAD_PATH))
|
||||
avalon.api.deregister_plugin_path(LegacyCreator, str(CREATE_PATH))
|
||||
|
||||
if not IS_HEADLESS:
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
import avalon.api
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
LoaderPlugin,
|
||||
)
|
||||
from .pipeline import AVALON_CONTAINERS
|
||||
from .ops import (
|
||||
MainThreadItem,
|
||||
|
|
@ -145,13 +147,13 @@ class Creator(LegacyCreator):
|
|||
return collection
|
||||
|
||||
|
||||
class Loader(avalon.api.Loader):
|
||||
class Loader(LoaderPlugin):
|
||||
"""Base class for Loader plug-ins."""
|
||||
|
||||
hosts = ["blender"]
|
||||
|
||||
|
||||
class AssetLoader(avalon.api.Loader):
|
||||
class AssetLoader(LoaderPlugin):
|
||||
"""A basic AssetLoader for Blender
|
||||
|
||||
This will implement the basic logic for linking/appending assets
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ from pathlib import Path
|
|||
from typing import List, Optional
|
||||
|
||||
import bpy
|
||||
from avalon import api
|
||||
|
||||
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS
|
||||
|
||||
|
||||
class OpenFileCacher:
|
||||
|
|
@ -77,7 +78,7 @@ def has_unsaved_changes() -> bool:
|
|||
def file_extensions() -> List[str]:
|
||||
"""Return the supported file extensions for Blender scene files."""
|
||||
|
||||
return api.HOST_WORKFILE_EXTENSIONS["blender"]
|
||||
return HOST_WORKFILE_EXTENSIONS["blender"]
|
||||
|
||||
|
||||
def work_root(session: dict) -> str:
|
||||
|
|
|
|||
|
|
@ -6,11 +6,14 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
from openpype.hosts.blender.api import plugin, lib
|
||||
|
||||
|
|
@ -178,7 +181,7 @@ class CacheModelLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@ from pathlib import Path
|
|||
from pprint import pformat
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from avalon import api, blender
|
||||
import bpy
|
||||
from openpype.pipeline import get_representation_path
|
||||
import openpype.hosts.blender.api.plugin
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
containerise_existing,
|
||||
AVALON_PROPERTY,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("openpype").getChild("blender").getChild("load_action")
|
||||
|
||||
|
|
@ -49,7 +53,7 @@ class BlendActionLoader(openpype.hosts.blender.api.plugin.AssetLoader):
|
|||
|
||||
container = bpy.data.collections.new(lib_container)
|
||||
container.name = container_name
|
||||
blender.pipeline.containerise_existing(
|
||||
containerise_existing(
|
||||
container,
|
||||
name,
|
||||
namespace,
|
||||
|
|
@ -57,8 +61,7 @@ class BlendActionLoader(openpype.hosts.blender.api.plugin.AssetLoader):
|
|||
self.__class__.__name__,
|
||||
)
|
||||
|
||||
container_metadata = container.get(
|
||||
blender.pipeline.AVALON_PROPERTY)
|
||||
container_metadata = container.get(AVALON_PROPERTY)
|
||||
|
||||
container_metadata["libpath"] = libpath
|
||||
container_metadata["lib_container"] = lib_container
|
||||
|
|
@ -90,16 +93,16 @@ class BlendActionLoader(openpype.hosts.blender.api.plugin.AssetLoader):
|
|||
|
||||
anim_data.action.make_local()
|
||||
|
||||
if not obj.get(blender.pipeline.AVALON_PROPERTY):
|
||||
if not obj.get(AVALON_PROPERTY):
|
||||
|
||||
obj[blender.pipeline.AVALON_PROPERTY] = dict()
|
||||
obj[AVALON_PROPERTY] = dict()
|
||||
|
||||
avalon_info = obj[blender.pipeline.AVALON_PROPERTY]
|
||||
avalon_info = obj[AVALON_PROPERTY]
|
||||
avalon_info.update({"container_name": container_name})
|
||||
|
||||
objects_list.append(obj)
|
||||
|
||||
animation_container.pop(blender.pipeline.AVALON_PROPERTY)
|
||||
animation_container.pop(AVALON_PROPERTY)
|
||||
|
||||
# Save the list of objects in the metadata container
|
||||
container_metadata["objects"] = objects_list
|
||||
|
|
@ -128,7 +131,7 @@ class BlendActionLoader(openpype.hosts.blender.api.plugin.AssetLoader):
|
|||
container["objectName"]
|
||||
)
|
||||
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
logger.info(
|
||||
|
|
@ -153,8 +156,7 @@ class BlendActionLoader(openpype.hosts.blender.api.plugin.AssetLoader):
|
|||
f"Unsupported file: {libpath}"
|
||||
)
|
||||
|
||||
collection_metadata = collection.get(
|
||||
blender.pipeline.AVALON_PROPERTY)
|
||||
collection_metadata = collection.get(AVALON_PROPERTY)
|
||||
|
||||
collection_libpath = collection_metadata["libpath"]
|
||||
normalized_collection_libpath = (
|
||||
|
|
@ -225,16 +227,16 @@ class BlendActionLoader(openpype.hosts.blender.api.plugin.AssetLoader):
|
|||
strip.action = anim_data.action
|
||||
strip.action_frame_end = anim_data.action.frame_range[1]
|
||||
|
||||
if not obj.get(blender.pipeline.AVALON_PROPERTY):
|
||||
if not obj.get(AVALON_PROPERTY):
|
||||
|
||||
obj[blender.pipeline.AVALON_PROPERTY] = dict()
|
||||
obj[AVALON_PROPERTY] = dict()
|
||||
|
||||
avalon_info = obj[blender.pipeline.AVALON_PROPERTY]
|
||||
avalon_info = obj[AVALON_PROPERTY]
|
||||
avalon_info.update({"container_name": collection.name})
|
||||
|
||||
objects_list.append(obj)
|
||||
|
||||
anim_container.pop(blender.pipeline.AVALON_PROPERTY)
|
||||
anim_container.pop(AVALON_PROPERTY)
|
||||
|
||||
# Save the list of objects in the metadata container
|
||||
collection_metadata["objects"] = objects_list
|
||||
|
|
@ -266,8 +268,7 @@ class BlendActionLoader(openpype.hosts.blender.api.plugin.AssetLoader):
|
|||
"Nested collections are not supported."
|
||||
)
|
||||
|
||||
collection_metadata = collection.get(
|
||||
blender.pipeline.AVALON_PROPERTY)
|
||||
collection_metadata = collection.get(AVALON_PROPERTY)
|
||||
objects = collection_metadata["objects"]
|
||||
lib_container = collection_metadata["lib_container"]
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.blender.api import plugin
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -102,7 +104,7 @@ class AudioLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
|
||||
self.log.info(
|
||||
"Container: %s\nRepresentation: %s",
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.blender.api import plugin
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
|
||||
logger = logging.getLogger("openpype").getChild(
|
||||
|
|
@ -155,7 +157,7 @@ class BlendCameraLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.blender.api import plugin, lib
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -143,7 +145,7 @@ class FbxCameraLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.blender.api import plugin, lib
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -187,7 +189,7 @@ class FbxModelLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -6,14 +6,16 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype import lib
|
||||
from openpype.pipeline import legacy_create
|
||||
from openpype.pipeline import (
|
||||
legacy_create,
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.blender.api import plugin
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -309,7 +311,7 @@ class BlendLayoutLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -7,12 +7,18 @@ from typing import Dict, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
discover_loader_plugins,
|
||||
remove_container,
|
||||
load_container,
|
||||
get_representation_path,
|
||||
loaders_from_representation,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_INSTANCES,
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
from openpype.hosts.blender.api import plugin
|
||||
|
||||
|
|
@ -33,7 +39,7 @@ class JsonLayoutLoader(plugin.AssetLoader):
|
|||
objects = list(asset_group.children)
|
||||
|
||||
for obj in objects:
|
||||
api.remove(obj.get(AVALON_PROPERTY))
|
||||
remove_container(obj.get(AVALON_PROPERTY))
|
||||
|
||||
def _remove_animation_instances(self, asset_group):
|
||||
instances = bpy.data.collections.get(AVALON_INSTANCES)
|
||||
|
|
@ -66,13 +72,13 @@ class JsonLayoutLoader(plugin.AssetLoader):
|
|||
with open(libpath, "r") as fp:
|
||||
data = json.load(fp)
|
||||
|
||||
all_loaders = api.discover(api.Loader)
|
||||
all_loaders = discover_loader_plugins()
|
||||
|
||||
for element in data:
|
||||
reference = element.get('reference')
|
||||
family = element.get('family')
|
||||
|
||||
loaders = api.loaders_from_representation(all_loaders, reference)
|
||||
loaders = loaders_from_representation(all_loaders, reference)
|
||||
loader = self._get_loader(loaders, family)
|
||||
|
||||
if not loader:
|
||||
|
|
@ -102,7 +108,7 @@ class JsonLayoutLoader(plugin.AssetLoader):
|
|||
# at this time it will not return anything. The assets will be
|
||||
# loaded in the next Blender cycle, so we use the options to
|
||||
# set the transform, parent and assign the action, if there is one.
|
||||
api.load(
|
||||
load_container(
|
||||
loader,
|
||||
reference,
|
||||
namespace=instance_name,
|
||||
|
|
@ -188,7 +194,7 @@ class JsonLayoutLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import os
|
|||
import json
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import get_representation_path
|
||||
from openpype.hosts.blender.api import plugin
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
containerise_existing,
|
||||
|
|
@ -140,7 +140,7 @@ class BlendLookLoader(plugin.AssetLoader):
|
|||
|
||||
def update(self, container: Dict, representation: Dict):
|
||||
collection = bpy.data.collections.get(container["objectName"])
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.blender.api import plugin
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -195,7 +197,7 @@ class BlendModelLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -6,15 +6,19 @@ from typing import Dict, List, Optional
|
|||
|
||||
import bpy
|
||||
|
||||
from avalon import api
|
||||
from avalon.blender import lib as avalon_lib
|
||||
from openpype import lib
|
||||
from openpype.pipeline import legacy_create
|
||||
from openpype.hosts.blender.api import plugin
|
||||
from openpype.pipeline import (
|
||||
legacy_create,
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.blender.api import (
|
||||
plugin,
|
||||
get_selection,
|
||||
)
|
||||
from openpype.hosts.blender.api.pipeline import (
|
||||
AVALON_CONTAINERS,
|
||||
AVALON_PROPERTY,
|
||||
AVALON_CONTAINER_ID
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -263,7 +267,7 @@ class BlendRigLoader(plugin.AssetLoader):
|
|||
if anim_file:
|
||||
bpy.ops.import_scene.fbx(filepath=anim_file, anim_offset=0.0)
|
||||
|
||||
imported = avalon_lib.get_selection()
|
||||
imported = get_selection()
|
||||
|
||||
armature = [
|
||||
o for o in asset_group.children if o.type == 'ARMATURE'][0]
|
||||
|
|
@ -307,7 +311,7 @@ class BlendRigLoader(plugin.AssetLoader):
|
|||
"""
|
||||
object_name = container["objectName"]
|
||||
asset_group = bpy.data.objects.get(object_name)
|
||||
libpath = Path(api.get_representation_path(representation))
|
||||
libpath = Path(get_representation_path(representation))
|
||||
extension = libpath.suffix.lower()
|
||||
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import os
|
||||
import json
|
||||
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
import bpy
|
||||
import bpy_extras
|
||||
import bpy_extras.anim_utils
|
||||
|
|
@ -140,7 +142,7 @@ class ExtractLayout(openpype.api.Extractor):
|
|||
blend = io.find_one(
|
||||
{
|
||||
"type": "representation",
|
||||
"parent": io.ObjectId(parent),
|
||||
"parent": ObjectId(parent),
|
||||
"name": "blend"
|
||||
},
|
||||
projection={"_id": True})
|
||||
|
|
@ -151,7 +153,7 @@ class ExtractLayout(openpype.api.Extractor):
|
|||
fbx = io.find_one(
|
||||
{
|
||||
"type": "representation",
|
||||
"parent": io.ObjectId(parent),
|
||||
"parent": ObjectId(parent),
|
||||
"name": "fbx"
|
||||
},
|
||||
projection={"_id": True})
|
||||
|
|
@ -162,7 +164,7 @@ class ExtractLayout(openpype.api.Extractor):
|
|||
abc = io.find_one(
|
||||
{
|
||||
"type": "representation",
|
||||
"parent": io.ObjectId(parent),
|
||||
"parent": ObjectId(parent),
|
||||
"name": "abc"
|
||||
},
|
||||
projection={"_id": True})
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ from .workio import (
|
|||
)
|
||||
from .render_utils import (
|
||||
export_clip,
|
||||
get_preset_path_by_xml_name
|
||||
get_preset_path_by_xml_name,
|
||||
modify_preset_file
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
|
|
@ -140,5 +141,6 @@ __all__ = [
|
|||
|
||||
# render utils
|
||||
"export_clip",
|
||||
"get_preset_path_by_xml_name"
|
||||
"get_preset_path_by_xml_name",
|
||||
"modify_preset_file"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -4,10 +4,15 @@ Basic avalon integration
|
|||
import os
|
||||
import contextlib
|
||||
from avalon import api as avalon
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
from pyblish import api as pyblish
|
||||
|
||||
from openpype.api import Logger
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
deregister_loader_plugin_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from .lib import (
|
||||
set_segment_data_marker,
|
||||
set_publish_attribute,
|
||||
|
|
@ -22,7 +27,6 @@ PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
|
|||
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
|
||||
LOAD_PATH = os.path.join(PLUGINS_DIR, "load")
|
||||
CREATE_PATH = os.path.join(PLUGINS_DIR, "create")
|
||||
INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory")
|
||||
|
||||
AVALON_CONTAINERS = "AVALON_CONTAINERS"
|
||||
|
||||
|
|
@ -30,12 +34,10 @@ log = Logger.get_logger(__name__)
|
|||
|
||||
|
||||
def install():
|
||||
|
||||
pyblish.register_host("flame")
|
||||
pyblish.register_plugin_path(PUBLISH_PATH)
|
||||
avalon.register_plugin_path(avalon.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
avalon.register_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
avalon.register_plugin_path(avalon.InventoryAction, INVENTORY_PATH)
|
||||
log.info("OpenPype Flame plug-ins registred ...")
|
||||
|
||||
# register callback for switching publishable
|
||||
|
|
@ -43,14 +45,14 @@ def install():
|
|||
|
||||
log.info("OpenPype Flame host installed ...")
|
||||
|
||||
|
||||
def uninstall():
|
||||
pyblish.deregister_host("flame")
|
||||
|
||||
log.info("Deregistering Flame plug-ins..")
|
||||
pyblish.deregister_plugin_path(PUBLISH_PATH)
|
||||
avalon.deregister_plugin_path(avalon.Loader, LOAD_PATH)
|
||||
deregister_loader_plugin_path(LOAD_PATH)
|
||||
avalon.deregister_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
avalon.deregister_plugin_path(avalon.InventoryAction, INVENTORY_PATH)
|
||||
|
||||
# register callback for switching publishable
|
||||
pyblish.deregister_callback("instanceToggled", on_pyblish_instance_toggled)
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@ import six
|
|||
import qargparse
|
||||
from Qt import QtWidgets, QtCore
|
||||
import openpype.api as openpype
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
LoaderPlugin,
|
||||
)
|
||||
from openpype import style
|
||||
import avalon.api as avalon
|
||||
from . import (
|
||||
lib as flib,
|
||||
pipeline as fpipeline,
|
||||
|
|
@ -660,7 +662,7 @@ class PublishableClip:
|
|||
# Publishing plugin functions
|
||||
# Loader plugin functions
|
||||
|
||||
class ClipLoader(avalon.Loader):
|
||||
class ClipLoader(LoaderPlugin):
|
||||
"""A basic clip loader for Flame
|
||||
|
||||
This will implement the basic behavior for a loader to inherit from that
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
|
||||
def export_clip(export_path, clip, preset_path, **kwargs):
|
||||
|
|
@ -123,3 +124,29 @@ def get_preset_path_by_xml_name(xml_preset_name):
|
|||
|
||||
# if nothing found then return False
|
||||
return False
|
||||
|
||||
|
||||
def modify_preset_file(xml_path, staging_dir, data):
|
||||
"""Modify xml preset with input data
|
||||
|
||||
Args:
|
||||
xml_path (str ): path for input xml preset
|
||||
staging_dir (str): staging dir path
|
||||
data (dict): data where key is xmlTag and value as string
|
||||
|
||||
Returns:
|
||||
str: _description_
|
||||
"""
|
||||
# create temp path
|
||||
dirname, basename = os.path.split(xml_path)
|
||||
temp_path = os.path.join(staging_dir, basename)
|
||||
|
||||
# change xml following data keys
|
||||
with open(xml_path, "r") as datafile:
|
||||
tree = ET.parse(datafile)
|
||||
for key, value in data.items():
|
||||
for element in tree.findall(".//{}".format(key)):
|
||||
element.text = str(value)
|
||||
tree.write(temp_path)
|
||||
|
||||
return temp_path
|
||||
|
|
|
|||
|
|
@ -420,13 +420,20 @@ class WireTapCom(object):
|
|||
RuntimeError: Not able to set colorspace policy
|
||||
"""
|
||||
color_policy = color_policy or "Legacy"
|
||||
|
||||
# check if the colour policy in custom dir
|
||||
if not os.path.exists(color_policy):
|
||||
color_policy = "/syncolor/policies/Autodesk/{}".format(
|
||||
color_policy)
|
||||
|
||||
# create arguments
|
||||
project_colorspace_cmd = [
|
||||
os.path.join(
|
||||
self.wiretap_tools_dir,
|
||||
"wiretap_duplicate_node"
|
||||
),
|
||||
"-s",
|
||||
"/syncolor/policies/Autodesk/{}".format(color_policy),
|
||||
color_policy,
|
||||
"-n",
|
||||
"/projects/{}/syncolor".format(project_name)
|
||||
]
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class FlamePrelaunch(PreLaunchHook):
|
|||
"FrameWidth": int(width),
|
||||
"FrameHeight": int(height),
|
||||
"AspectRatio": float((width / height) * _db_p_data["pixelAspect"]),
|
||||
"FrameRate": "{} fps".format(fps),
|
||||
"FrameRate": self._get_flame_fps(fps),
|
||||
"FrameDepth": str(imageio_flame["project"]["frameDepth"]),
|
||||
"FieldDominance": str(imageio_flame["project"]["fieldDominance"])
|
||||
}
|
||||
|
|
@ -101,6 +101,28 @@ class FlamePrelaunch(PreLaunchHook):
|
|||
|
||||
self.launch_context.launch_args.extend(app_arguments)
|
||||
|
||||
def _get_flame_fps(self, fps_num):
|
||||
fps_table = {
|
||||
float(23.976): "23.976 fps",
|
||||
int(25): "25 fps",
|
||||
int(24): "24 fps",
|
||||
float(29.97): "29.97 fps DF",
|
||||
int(30): "30 fps",
|
||||
int(50): "50 fps",
|
||||
float(59.94): "59.94 fps DF",
|
||||
int(60): "60 fps"
|
||||
}
|
||||
|
||||
match_key = min(fps_table.keys(), key=lambda x: abs(x - fps_num))
|
||||
|
||||
try:
|
||||
return fps_table[match_key]
|
||||
except KeyError as msg:
|
||||
raise KeyError((
|
||||
"Missing FPS key in conversion table. "
|
||||
"Following keys are available: {}".format(fps_table.keys())
|
||||
)) from msg
|
||||
|
||||
def _add_pythonpath(self):
|
||||
pythonpath = self.launch_context.env.get("PYTHONPATH")
|
||||
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ class LoadClip(opfapi.ClipLoader):
|
|||
# version_name = version.get("name", None)
|
||||
# colorspace = version_data.get("colorspace", None)
|
||||
# object_name = "{}_{}".format(name, namespace)
|
||||
# file = api.get_representation_path(representation).replace("\\", "/")
|
||||
# file = get_representation_path(representation).replace("\\", "/")
|
||||
# clip = track_item.source()
|
||||
|
||||
# # reconnect media to new path
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import re
|
||||
import pyblish
|
||||
import openpype
|
||||
import openpype.hosts.flame.api as opfapi
|
||||
|
|
@ -6,6 +7,10 @@ from openpype.hosts.flame.otio import flame_export
|
|||
# # developer reload modules
|
||||
from pprint import pformat
|
||||
|
||||
# constatns
|
||||
NUM_PATERN = re.compile(r"([0-9\.]+)")
|
||||
TXT_PATERN = re.compile(r"([a-zA-Z]+)")
|
||||
|
||||
|
||||
class CollectTimelineInstances(pyblish.api.ContextPlugin):
|
||||
"""Collect all Timeline segment selection."""
|
||||
|
|
@ -16,6 +21,16 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin):
|
|||
|
||||
audio_track_items = []
|
||||
|
||||
# TODO: add to settings
|
||||
# settings
|
||||
xml_preset_attrs_from_comments = {
|
||||
"width": "number",
|
||||
"height": "number",
|
||||
"pixelRatio": "float",
|
||||
"resizeType": "string",
|
||||
"resizeFilter": "string"
|
||||
}
|
||||
|
||||
def process(self, context):
|
||||
project = context.data["flameProject"]
|
||||
sequence = context.data["flameSequence"]
|
||||
|
|
@ -26,6 +41,10 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin):
|
|||
# process all sellected
|
||||
with opfapi.maintained_segment_selection(sequence) as segments:
|
||||
for segment in segments:
|
||||
comment_attributes = self._get_comment_attributes(segment)
|
||||
self.log.debug("_ comment_attributes: {}".format(
|
||||
pformat(comment_attributes)))
|
||||
|
||||
clip_data = opfapi.get_segment_attributes(segment)
|
||||
clip_name = clip_data["segment_name"]
|
||||
self.log.debug("clip_name: {}".format(clip_name))
|
||||
|
|
@ -101,6 +120,9 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin):
|
|||
# add resolution
|
||||
self._get_resolution_to_data(inst_data, context)
|
||||
|
||||
# add comment attributes if any
|
||||
inst_data.update(comment_attributes)
|
||||
|
||||
# create instance
|
||||
instance = context.create_instance(**inst_data)
|
||||
|
||||
|
|
@ -126,6 +148,94 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin):
|
|||
if marker_data.get("reviewTrack") is not None:
|
||||
instance.data["reviewAudio"] = True
|
||||
|
||||
def _get_comment_attributes(self, segment):
|
||||
comment = segment.comment.get_value()
|
||||
|
||||
# try to find attributes
|
||||
attributes = {
|
||||
"xml_overrides": {
|
||||
"pixelRatio": 1.00}
|
||||
}
|
||||
# search for `:`
|
||||
for split in self._split_comments(comment):
|
||||
# make sure we ignore if not `:` in key
|
||||
if ":" not in split:
|
||||
continue
|
||||
|
||||
self._get_xml_preset_attrs(
|
||||
attributes, split)
|
||||
|
||||
# add xml overides resolution to instance data
|
||||
xml_overrides = attributes["xml_overrides"]
|
||||
if xml_overrides.get("width"):
|
||||
attributes.update({
|
||||
"resolutionWidth": xml_overrides["width"],
|
||||
"resolutionHeight": xml_overrides["height"],
|
||||
"pixelAspect": xml_overrides["pixelRatio"]
|
||||
})
|
||||
|
||||
return attributes
|
||||
|
||||
def _get_xml_preset_attrs(self, attributes, split):
|
||||
|
||||
# split to key and value
|
||||
key, value = split.split(":")
|
||||
|
||||
for a_name, a_type in self.xml_preset_attrs_from_comments.items():
|
||||
# exclude all not related attributes
|
||||
if a_name.lower() not in key.lower():
|
||||
continue
|
||||
|
||||
# get pattern defined by type
|
||||
pattern = TXT_PATERN
|
||||
if a_type in ("number" , "float"):
|
||||
pattern = NUM_PATERN
|
||||
|
||||
res_goup = pattern.findall(value)
|
||||
|
||||
# raise if nothing is found as it is not correctly defined
|
||||
if not res_goup:
|
||||
raise ValueError((
|
||||
"Value for `{}` attribute is not "
|
||||
"set correctly: `{}`").format(a_name, split))
|
||||
|
||||
if "string" in a_type:
|
||||
_value = res_goup[0]
|
||||
if "float" in a_type:
|
||||
_value = float(res_goup[0])
|
||||
if "number" in a_type:
|
||||
_value = int(res_goup[0])
|
||||
|
||||
attributes["xml_overrides"][a_name] = _value
|
||||
|
||||
# condition for resolution in key
|
||||
if "resolution" in key.lower():
|
||||
res_goup = NUM_PATERN.findall(value)
|
||||
# check if axpect was also defined
|
||||
# 1920x1080x1.5
|
||||
aspect = res_goup[2] if len(res_goup) > 2 else 1
|
||||
|
||||
width = int(res_goup[0])
|
||||
height = int(res_goup[1])
|
||||
pixel_ratio = float(aspect)
|
||||
attributes["xml_overrides"].update({
|
||||
"width": width,
|
||||
"height": height,
|
||||
"pixelRatio": pixel_ratio
|
||||
})
|
||||
|
||||
def _split_comments(self, comment_string):
|
||||
# first split comment by comma
|
||||
split_comments = []
|
||||
if "," in comment_string:
|
||||
split_comments.extend(comment_string.split(","))
|
||||
elif ";" in comment_string:
|
||||
split_comments.extend(comment_string.split(";"))
|
||||
else:
|
||||
split_comments.append(comment_string)
|
||||
|
||||
return split_comments
|
||||
|
||||
def _get_head_tail(self, clip_data, first_frame):
|
||||
# calculate head and tail with forward compatibility
|
||||
head = clip_data.get("segment_head")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
from pprint import pformat
|
||||
from copy import deepcopy
|
||||
|
||||
import pyblish.api
|
||||
import openpype.api
|
||||
from openpype.hosts.flame import api as opfapi
|
||||
|
|
@ -22,6 +23,8 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
"ext": "jpg",
|
||||
"xml_preset_file": "Jpeg (8-bit).xml",
|
||||
"xml_preset_dir": "",
|
||||
"export_type": "File Sequence",
|
||||
"ignore_comment_attrs": True,
|
||||
"colorspace_out": "Output - sRGB",
|
||||
"representation_add_range": False,
|
||||
"representation_tags": ["thumbnail"]
|
||||
|
|
@ -30,6 +33,8 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
"ext": "mov",
|
||||
"xml_preset_file": "Apple iPad (1920x1080).xml",
|
||||
"xml_preset_dir": "",
|
||||
"export_type": "Movie",
|
||||
"ignore_comment_attrs": True,
|
||||
"colorspace_out": "Output - Rec.709",
|
||||
"representation_add_range": True,
|
||||
"representation_tags": [
|
||||
|
|
@ -54,21 +59,35 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
):
|
||||
instance.data["representations"] = []
|
||||
|
||||
frame_start = instance.data["frameStart"]
|
||||
handle_start = instance.data["handleStart"]
|
||||
frame_start_handle = frame_start - handle_start
|
||||
source_first_frame = instance.data["sourceFirstFrame"]
|
||||
source_start_handles = instance.data["sourceStartH"]
|
||||
source_end_handles = instance.data["sourceEndH"]
|
||||
source_duration_handles = (
|
||||
source_end_handles - source_start_handles) + 1
|
||||
|
||||
# flame objects
|
||||
segment = instance.data["item"]
|
||||
sequence_clip = instance.context.data["flameSequence"]
|
||||
clip_data = instance.data["flameSourceClip"]
|
||||
clip = clip_data["PyClip"]
|
||||
|
||||
in_mark = (source_start_handles - source_first_frame) + 1
|
||||
out_mark = in_mark + source_duration_handles
|
||||
# segment's parent track name
|
||||
s_track_name = segment.parent.name.get_value()
|
||||
|
||||
# get configured workfile frame start/end (handles excluded)
|
||||
frame_start = instance.data["frameStart"]
|
||||
# get media source first frame
|
||||
source_first_frame = instance.data["sourceFirstFrame"]
|
||||
|
||||
# get timeline in/out of segment
|
||||
clip_in = instance.data["clipIn"]
|
||||
clip_out = instance.data["clipOut"]
|
||||
|
||||
# get handles value - take only the max from both
|
||||
handle_start = instance.data["handleStart"]
|
||||
handle_end = instance.data["handleStart"]
|
||||
handles = max(handle_start, handle_end)
|
||||
|
||||
# get media source range with handles
|
||||
source_end_handles = instance.data["sourceEndH"]
|
||||
source_start_handles = instance.data["sourceStartH"]
|
||||
source_end_handles = instance.data["sourceEndH"]
|
||||
|
||||
# create staging dir path
|
||||
staging_dir = self.staging_dir(instance)
|
||||
|
||||
# add default preset type for thumbnail and reviewable video
|
||||
|
|
@ -77,15 +96,61 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
export_presets = deepcopy(self.default_presets)
|
||||
export_presets.update(self.export_presets_mapping)
|
||||
|
||||
# with maintained duplication loop all presets
|
||||
with opfapi.maintained_object_duplication(clip) as duplclip:
|
||||
# loop all preset names and
|
||||
for unique_name, preset_config in export_presets.items():
|
||||
# loop all preset names and
|
||||
for unique_name, preset_config in export_presets.items():
|
||||
modify_xml_data = {}
|
||||
|
||||
# get all presets attributes
|
||||
preset_file = preset_config["xml_preset_file"]
|
||||
preset_dir = preset_config["xml_preset_dir"]
|
||||
export_type = preset_config["export_type"]
|
||||
repre_tags = preset_config["representation_tags"]
|
||||
ignore_comment_attrs = preset_config["ignore_comment_attrs"]
|
||||
color_out = preset_config["colorspace_out"]
|
||||
|
||||
# get frame range with handles for representation range
|
||||
frame_start_handle = frame_start - handle_start
|
||||
source_duration_handles = (
|
||||
source_end_handles - source_start_handles) + 1
|
||||
|
||||
# define in/out marks
|
||||
in_mark = (source_start_handles - source_first_frame) + 1
|
||||
out_mark = in_mark + source_duration_handles
|
||||
|
||||
# by default export source clips
|
||||
exporting_clip = clip
|
||||
|
||||
if export_type == "Sequence Publish":
|
||||
# change export clip to sequence
|
||||
exporting_clip = sequence_clip
|
||||
|
||||
# change in/out marks to timeline in/out
|
||||
in_mark = clip_in
|
||||
out_mark = clip_out
|
||||
|
||||
# add xml tags modifications
|
||||
modify_xml_data.update({
|
||||
"exportHandles": True,
|
||||
"nbHandles": handles,
|
||||
"startFrame": frame_start
|
||||
})
|
||||
|
||||
if not ignore_comment_attrs:
|
||||
# add any xml overrides collected form segment.comment
|
||||
modify_xml_data.update(instance.data["xml_overrides"])
|
||||
|
||||
self.log.debug("__ modify_xml_data: {}".format(pformat(
|
||||
modify_xml_data
|
||||
)))
|
||||
|
||||
# with maintained duplication loop all presets
|
||||
with opfapi.maintained_object_duplication(
|
||||
exporting_clip) as duplclip:
|
||||
kwargs = {}
|
||||
preset_file = preset_config["xml_preset_file"]
|
||||
preset_dir = preset_config["xml_preset_dir"]
|
||||
repre_tags = preset_config["representation_tags"]
|
||||
color_out = preset_config["colorspace_out"]
|
||||
|
||||
if export_type == "Sequence Publish":
|
||||
# only keep visible layer where instance segment is child
|
||||
self.hide_other_tracks(duplclip, s_track_name)
|
||||
|
||||
# validate xml preset file is filled
|
||||
if preset_file == "":
|
||||
|
|
@ -108,10 +173,13 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
)
|
||||
|
||||
# create preset path
|
||||
preset_path = str(os.path.join(
|
||||
preset_orig_xml_path = str(os.path.join(
|
||||
preset_dir, preset_file
|
||||
))
|
||||
|
||||
preset_path = opfapi.modify_preset_file(
|
||||
preset_orig_xml_path, staging_dir, modify_xml_data)
|
||||
|
||||
# define kwargs based on preset type
|
||||
if "thumbnail" in unique_name:
|
||||
kwargs["thumb_frame_number"] = in_mark + (
|
||||
|
|
@ -122,6 +190,7 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
"out_mark": out_mark
|
||||
})
|
||||
|
||||
# get and make export dir paths
|
||||
export_dir_path = str(os.path.join(
|
||||
staging_dir, unique_name
|
||||
))
|
||||
|
|
@ -132,6 +201,7 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
export_dir_path, duplclip, preset_path, **kwargs)
|
||||
|
||||
extension = preset_config["ext"]
|
||||
|
||||
# create representation data
|
||||
representation_data = {
|
||||
"name": unique_name,
|
||||
|
|
@ -159,7 +229,12 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
# add files to represetation but add
|
||||
# imagesequence as list
|
||||
if (
|
||||
"movie_file" in preset_path
|
||||
# first check if path in files is not mov extension
|
||||
[
|
||||
f for f in files
|
||||
if os.path.splitext(f)[-1] == ".mov"
|
||||
]
|
||||
# then try if thumbnail is not in unique name
|
||||
or unique_name == "thumbnail"
|
||||
):
|
||||
representation_data["files"] = files.pop()
|
||||
|
|
@ -246,3 +321,19 @@ class ExtractSubsetResources(openpype.api.Extractor):
|
|||
)
|
||||
|
||||
return new_stage_dir, new_files_list
|
||||
|
||||
def hide_other_tracks(self, sequence_clip, track_name):
|
||||
"""Helper method used only if sequence clip is used
|
||||
|
||||
Args:
|
||||
sequence_clip (flame.Clip): sequence clip
|
||||
track_name (str): track name
|
||||
"""
|
||||
# create otio tracks and clips
|
||||
for ver in sequence_clip.versions:
|
||||
for track in ver.tracks:
|
||||
if len(track.segments) == 0 and track.hidden:
|
||||
continue
|
||||
|
||||
if track.name.get_value() != track_name:
|
||||
track.hidden = True
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ import sys
|
|||
import re
|
||||
import contextlib
|
||||
|
||||
from bson.objectid import ObjectId
|
||||
from Qt import QtGui
|
||||
|
||||
import avalon.api
|
||||
from avalon import io
|
||||
from openpype.pipeline import switch_container
|
||||
from .pipeline import get_current_comp, comp_lock_and_undo_chunk
|
||||
|
||||
self = sys.modules[__name__]
|
||||
|
|
@ -92,7 +93,7 @@ def switch_item(container,
|
|||
# Collect any of current asset, subset and representation if not provided
|
||||
# so we can use the original name from those.
|
||||
if any(not x for x in [asset_name, subset_name, representation_name]):
|
||||
_id = io.ObjectId(container["representation"])
|
||||
_id = ObjectId(container["representation"])
|
||||
representation = io.find_one({"type": "representation", "_id": _id})
|
||||
version, subset, asset, project = io.parenthood(representation)
|
||||
|
||||
|
|
@ -142,7 +143,7 @@ def switch_item(container,
|
|||
assert representation, ("Could not find representation in the database "
|
||||
"with the name '%s'" % representation_name)
|
||||
|
||||
avalon.api.switch(container, representation)
|
||||
switch_container(container, representation)
|
||||
|
||||
return representation
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,16 @@ import contextlib
|
|||
|
||||
import pyblish.api
|
||||
import avalon.api
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
|
||||
from openpype.api import Logger
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
deregister_loader_plugin_path,
|
||||
register_inventory_action_path,
|
||||
deregister_inventory_action_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
import openpype.hosts.fusion
|
||||
|
||||
log = Logger().get_logger(__name__)
|
||||
|
|
@ -63,9 +69,9 @@ def install():
|
|||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
log.info("Registering Fusion plug-ins..")
|
||||
|
||||
avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.register_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
avalon.api.register_plugin_path(avalon.api.InventoryAction, INVENTORY_PATH)
|
||||
register_inventory_action_path(INVENTORY_PATH)
|
||||
|
||||
pyblish.api.register_callback(
|
||||
"instanceToggled", on_pyblish_instance_toggled
|
||||
|
|
@ -87,11 +93,9 @@ def uninstall():
|
|||
pyblish.api.deregister_plugin_path(PUBLISH_PATH)
|
||||
log.info("Deregistering Fusion plug-ins..")
|
||||
|
||||
avalon.api.deregister_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
deregister_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.deregister_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
avalon.api.deregister_plugin_path(
|
||||
avalon.api.InventoryAction, INVENTORY_PATH
|
||||
)
|
||||
deregister_inventory_action_path(INVENTORY_PATH)
|
||||
|
||||
pyblish.api.deregister_callback(
|
||||
"instanceToggled", on_pyblish_instance_toggled
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
"""Host API required Work Files tool"""
|
||||
import sys
|
||||
import os
|
||||
from avalon import api
|
||||
|
||||
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS
|
||||
|
||||
from .pipeline import get_current_comp
|
||||
|
||||
|
||||
def file_extensions():
|
||||
return api.HOST_WORKFILE_EXTENSIONS["fusion"]
|
||||
return HOST_WORKFILE_EXTENSIONS["fusion"]
|
||||
|
||||
|
||||
def has_unsaved_changes():
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from avalon import api
|
||||
from openpype.pipeline import InventoryAction
|
||||
|
||||
|
||||
class FusionSelectContainers(api.InventoryAction):
|
||||
class FusionSelectContainers(InventoryAction):
|
||||
|
||||
label = "Select Containers"
|
||||
icon = "mouse-pointer"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from avalon import api
|
||||
from Qt import QtGui, QtWidgets
|
||||
|
||||
from openpype.pipeline import InventoryAction
|
||||
from openpype import style
|
||||
from openpype.hosts.fusion.api import (
|
||||
get_current_comp,
|
||||
|
|
@ -8,7 +8,7 @@ from openpype.hosts.fusion.api import (
|
|||
)
|
||||
|
||||
|
||||
class FusionSetToolColor(api.InventoryAction):
|
||||
class FusionSetToolColor(InventoryAction):
|
||||
"""Update the color of the selected tools"""
|
||||
|
||||
label = "Set Tool Color"
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
"""
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import load
|
||||
|
||||
|
||||
class FusionSetFrameRangeLoader(api.Loader):
|
||||
class FusionSetFrameRangeLoader(load.LoaderPlugin):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["animation",
|
||||
|
|
@ -39,7 +39,7 @@ class FusionSetFrameRangeLoader(api.Loader):
|
|||
lib.update_frame_range(start, end)
|
||||
|
||||
|
||||
class FusionSetFrameRangeWithHandlesLoader(api.Loader):
|
||||
class FusionSetFrameRangeWithHandlesLoader(load.LoaderPlugin):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["animation",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
import os
|
||||
import contextlib
|
||||
|
||||
from avalon import api, io
|
||||
from avalon import io
|
||||
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from openpype.hosts.fusion.api import (
|
||||
imprint_container,
|
||||
get_current_comp,
|
||||
|
|
@ -117,7 +121,7 @@ def loader_shift(loader, frame, relative=True):
|
|||
return int(shift)
|
||||
|
||||
|
||||
class FusionLoadSequence(api.Loader):
|
||||
class FusionLoadSequence(load.LoaderPlugin):
|
||||
"""Load image sequence into Fusion"""
|
||||
|
||||
families = ["imagesequence", "review", "render"]
|
||||
|
|
@ -204,7 +208,7 @@ class FusionLoadSequence(api.Loader):
|
|||
assert tool.ID == "Loader", "Must be Loader"
|
||||
comp = tool.Comp()
|
||||
|
||||
root = os.path.dirname(api.get_representation_path(representation))
|
||||
root = os.path.dirname(get_representation_path(representation))
|
||||
path = self._get_first_image(root)
|
||||
|
||||
# Get start frame from version data
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ replace_files = """function %s_replace_files(args)
|
|||
""" % (signature, signature)
|
||||
|
||||
|
||||
class ImageSequenceLoader(api.Loader):
|
||||
class ImageSequenceLoader(load.LoaderPlugin):
|
||||
"""Load images
|
||||
Stores the imported asset in a container named after the asset.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -272,8 +272,8 @@ function Client() {
|
|||
|
||||
app.avalonClient.send(
|
||||
{
|
||||
'module': 'avalon.api',
|
||||
'method': 'emit',
|
||||
'module': 'openpype.lib',
|
||||
'method': 'emit_event',
|
||||
'args': ['application.launched']
|
||||
}, false);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,15 +2,20 @@ import os
|
|||
from pathlib import Path
|
||||
import logging
|
||||
|
||||
from bson.objectid import ObjectId
|
||||
import pyblish.api
|
||||
|
||||
from avalon import io
|
||||
import avalon.api
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
|
||||
from openpype import lib
|
||||
from openpype.lib import register_event_callback
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
deregister_loader_plugin_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
import openpype.hosts.harmony
|
||||
import openpype.hosts.harmony.api as harmony
|
||||
|
||||
|
|
@ -109,7 +114,7 @@ def check_inventory():
|
|||
representation = container['representation']
|
||||
representation_doc = io.find_one(
|
||||
{
|
||||
"_id": io.ObjectId(representation),
|
||||
"_id": ObjectId(representation),
|
||||
"type": "representation"
|
||||
},
|
||||
projection={"parent": True}
|
||||
|
|
@ -180,7 +185,7 @@ def install():
|
|||
|
||||
pyblish.api.register_host("harmony")
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.register_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
log.info(PUBLISH_PATH)
|
||||
|
||||
|
|
@ -194,7 +199,7 @@ def install():
|
|||
|
||||
def uninstall():
|
||||
pyblish.api.deregister_plugin_path(PUBLISH_PATH)
|
||||
avalon.api.deregister_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
deregister_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.deregister_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,20 +2,21 @@
|
|||
import os
|
||||
import shutil
|
||||
|
||||
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS
|
||||
|
||||
from .lib import (
|
||||
ProcessContext,
|
||||
get_local_harmony_path,
|
||||
zip_and_move,
|
||||
launch_zip_file
|
||||
)
|
||||
from avalon import api
|
||||
|
||||
# used to lock saving until previous save is done.
|
||||
save_disabled = False
|
||||
|
||||
|
||||
def file_extensions():
|
||||
return api.HOST_WORKFILE_EXTENSIONS["harmony"]
|
||||
return HOST_WORKFILE_EXTENSIONS["harmony"]
|
||||
|
||||
|
||||
def has_unsaved_changes():
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
import openpype.hosts.harmony.api as harmony
|
||||
|
||||
sig = harmony.signature()
|
||||
|
|
@ -29,7 +32,7 @@ function %s(args)
|
|||
""" % (sig, sig)
|
||||
|
||||
|
||||
class ImportAudioLoader(api.Loader):
|
||||
class ImportAudioLoader(load.LoaderPlugin):
|
||||
"""Import audio."""
|
||||
|
||||
families = ["shot", "audio"]
|
||||
|
|
@ -37,7 +40,7 @@ class ImportAudioLoader(api.Loader):
|
|||
label = "Import Audio"
|
||||
|
||||
def load(self, context, name=None, namespace=None, data=None):
|
||||
wav_file = api.get_representation_path(context["representation"])
|
||||
wav_file = get_representation_path(context["representation"])
|
||||
harmony.send(
|
||||
{"function": func, "args": [context["subset"]["name"], wav_file]}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import os
|
||||
import json
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
import openpype.hosts.harmony.api as harmony
|
||||
import openpype.lib
|
||||
|
||||
|
|
@ -226,7 +229,7 @@ replace_files
|
|||
"""
|
||||
|
||||
|
||||
class BackgroundLoader(api.Loader):
|
||||
class BackgroundLoader(load.LoaderPlugin):
|
||||
"""Load images
|
||||
Stores the imported asset in a container named after the asset.
|
||||
"""
|
||||
|
|
@ -278,7 +281,7 @@ class BackgroundLoader(api.Loader):
|
|||
|
||||
def update(self, container, representation):
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
|
||||
with open(path) as json_file:
|
||||
data = json.load(json_file)
|
||||
|
|
@ -297,7 +300,7 @@ class BackgroundLoader(api.Loader):
|
|||
|
||||
bg_folder = os.path.dirname(path)
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
|
||||
print(container)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,15 @@ from pathlib import Path
|
|||
|
||||
import clique
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
import openpype.hosts.harmony.api as harmony
|
||||
import openpype.lib
|
||||
|
||||
|
||||
class ImageSequenceLoader(api.Loader):
|
||||
class ImageSequenceLoader(load.LoaderPlugin):
|
||||
"""Load image sequences.
|
||||
|
||||
Stores the imported asset in a container named after the asset.
|
||||
|
|
@ -79,7 +82,7 @@ class ImageSequenceLoader(api.Loader):
|
|||
self_name = self.__class__.__name__
|
||||
node = container.get("nodes").pop()
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
collections, remainder = clique.assemble(
|
||||
os.listdir(os.path.dirname(path))
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import os
|
||||
import shutil
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
import openpype.hosts.harmony.api as harmony
|
||||
|
||||
|
||||
class ImportPaletteLoader(api.Loader):
|
||||
class ImportPaletteLoader(load.LoaderPlugin):
|
||||
"""Import palettes."""
|
||||
|
||||
families = ["palette", "harmony.palette"]
|
||||
|
|
@ -31,7 +34,7 @@ class ImportPaletteLoader(api.Loader):
|
|||
scene_path = harmony.send(
|
||||
{"function": "scene.currentProjectPath"}
|
||||
)["result"]
|
||||
src = api.get_representation_path(representation)
|
||||
src = get_representation_path(representation)
|
||||
dst = os.path.join(
|
||||
scene_path,
|
||||
"palette-library",
|
||||
|
|
|
|||
|
|
@ -6,12 +6,15 @@ import os
|
|||
import shutil
|
||||
import uuid
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
import openpype.hosts.harmony.api as harmony
|
||||
import openpype.lib
|
||||
|
||||
|
||||
class TemplateLoader(api.Loader):
|
||||
class TemplateLoader(load.LoaderPlugin):
|
||||
"""Load Harmony template as container.
|
||||
|
||||
.. todo::
|
||||
|
|
@ -38,7 +41,7 @@ class TemplateLoader(api.Loader):
|
|||
# Load template.
|
||||
self_name = self.__class__.__name__
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
zip_file = api.get_representation_path(context["representation"])
|
||||
zip_file = get_representation_path(context["representation"])
|
||||
template_path = os.path.join(temp_dir, "temp.tpl")
|
||||
with zipfile.ZipFile(zip_file, "r") as zip_ref:
|
||||
zip_ref.extractall(template_path)
|
||||
|
|
|
|||
|
|
@ -3,11 +3,14 @@ import zipfile
|
|||
import os
|
||||
import shutil
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
import openpype.hosts.harmony.api as harmony
|
||||
|
||||
|
||||
class ImportTemplateLoader(api.Loader):
|
||||
class ImportTemplateLoader(load.LoaderPlugin):
|
||||
"""Import templates."""
|
||||
|
||||
families = ["harmony.template", "workfile"]
|
||||
|
|
@ -17,7 +20,7 @@ class ImportTemplateLoader(api.Loader):
|
|||
def load(self, context, name=None, namespace=None, data=None):
|
||||
# Import template.
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
zip_file = api.get_representation_path(context["representation"])
|
||||
zip_file = get_representation_path(context["representation"])
|
||||
template_path = os.path.join(temp_dir, "temp.tpl")
|
||||
with zipfile.ZipFile(zip_file, "r") as zip_ref:
|
||||
zip_ref.extractall(template_path)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import os
|
||||
import hiero.core.events
|
||||
from openpype.api import Logger
|
||||
from openpype.lib import register_event_callback
|
||||
from .lib import (
|
||||
sync_avalon_data_to_workfile,
|
||||
launch_workfiles_app,
|
||||
selection_changed_timeline,
|
||||
before_project_save,
|
||||
register_event_callback
|
||||
)
|
||||
from .tags import add_tags_to_workfile
|
||||
from .menu import update_menu_task_label
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ import platform
|
|||
import ast
|
||||
import shutil
|
||||
import hiero
|
||||
|
||||
from Qt import QtWidgets
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
import avalon.api as avalon
|
||||
import avalon.io
|
||||
from openpype.api import (Logger, Anatomy, get_anatomy_settings)
|
||||
|
|
@ -1006,7 +1009,7 @@ def check_inventory_versions():
|
|||
# get representation from io
|
||||
representation = io.find_one({
|
||||
"type": "representation",
|
||||
"_id": io.ObjectId(container["representation"])
|
||||
"_id": ObjectId(container["representation"])
|
||||
})
|
||||
|
||||
# Get start frame from version data
|
||||
|
|
|
|||
|
|
@ -4,12 +4,17 @@ Basic avalon integration
|
|||
import os
|
||||
import contextlib
|
||||
from collections import OrderedDict
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
|
||||
from avalon import api as avalon
|
||||
from avalon import schema
|
||||
from pyblish import api as pyblish
|
||||
from openpype.api import Logger
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
deregister_loader_plugin_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.tools.utils import host_tools
|
||||
from . import lib, menu, events
|
||||
|
||||
|
|
@ -24,7 +29,6 @@ PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
|
|||
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish").replace("\\", "/")
|
||||
LOAD_PATH = os.path.join(PLUGINS_DIR, "load").replace("\\", "/")
|
||||
CREATE_PATH = os.path.join(PLUGINS_DIR, "create").replace("\\", "/")
|
||||
INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory").replace("\\", "/")
|
||||
|
||||
AVALON_CONTAINERS = ":AVALON_CONTAINERS"
|
||||
|
||||
|
|
@ -45,9 +49,8 @@ def install():
|
|||
log.info("Registering Hiero plug-ins..")
|
||||
pyblish.register_host("hiero")
|
||||
pyblish.register_plugin_path(PUBLISH_PATH)
|
||||
avalon.register_plugin_path(avalon.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
avalon.register_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
avalon.register_plugin_path(avalon.InventoryAction, INVENTORY_PATH)
|
||||
|
||||
# register callback for switching publishable
|
||||
pyblish.register_callback("instanceToggled", on_pyblish_instance_toggled)
|
||||
|
|
@ -67,7 +70,7 @@ def uninstall():
|
|||
log.info("Deregistering Hiero plug-ins..")
|
||||
pyblish.deregister_host("hiero")
|
||||
pyblish.deregister_plugin_path(PUBLISH_PATH)
|
||||
avalon.deregister_plugin_path(avalon.Loader, LOAD_PATH)
|
||||
deregister_loader_plugin_path(LOAD_PATH)
|
||||
avalon.deregister_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
|
||||
# register callback for switching publishable
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import hiero
|
|||
|
||||
from Qt import QtWidgets, QtCore
|
||||
import qargparse
|
||||
import avalon.api as avalon
|
||||
|
||||
import openpype.api as openpype
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import LoaderPlugin, LegacyCreator
|
||||
from . import lib
|
||||
|
||||
log = openpype.Logger().get_logger(__name__)
|
||||
|
|
@ -306,7 +306,7 @@ def get_reference_node_parents(ref):
|
|||
return parents
|
||||
|
||||
|
||||
class SequenceLoader(avalon.Loader):
|
||||
class SequenceLoader(LoaderPlugin):
|
||||
"""A basic SequenceLoader for Resolve
|
||||
|
||||
This will implement the basic behavior for a loader to inherit from that
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import os
|
||||
import hiero
|
||||
from avalon import api
|
||||
|
||||
from openpype.api import Logger
|
||||
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS
|
||||
|
||||
|
||||
log = Logger().get_logger(__name__)
|
||||
log = Logger.get_logger(__name__)
|
||||
|
||||
|
||||
def file_extensions():
|
||||
return api.HOST_WORKFILE_EXTENSIONS["hiero"]
|
||||
return HOST_WORKFILE_EXTENSIONS["hiero"]
|
||||
|
||||
|
||||
def has_unsaved_changes():
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from avalon import io, api
|
||||
from avalon import io
|
||||
from openpype.pipeline import get_representation_path
|
||||
import openpype.hosts.hiero.api as phiero
|
||||
# from openpype.hosts.hiero.api import plugin, lib
|
||||
# reload(lib)
|
||||
|
|
@ -112,7 +113,7 @@ class LoadClip(phiero.SequenceLoader):
|
|||
version_name = version.get("name", None)
|
||||
colorspace = version_data.get("colorspace", None)
|
||||
object_name = "{}_{}".format(name, namespace)
|
||||
file = api.get_representation_path(representation).replace("\\", "/")
|
||||
file = get_representation_path(representation).replace("\\", "/")
|
||||
clip = track_item.source()
|
||||
|
||||
# reconnect media to new path
|
||||
|
|
|
|||
|
|
@ -8,10 +8,13 @@ import hdefereval
|
|||
|
||||
import pyblish.api
|
||||
import avalon.api
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
from avalon.lib import find_submodule
|
||||
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
import openpype.hosts.houdini
|
||||
from openpype.hosts.houdini.api import lib
|
||||
|
||||
|
|
@ -50,7 +53,7 @@ def install():
|
|||
pyblish.api.register_host("hpython")
|
||||
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.register_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
|
||||
log.info("Installing callbacks ... ")
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
import os
|
||||
|
||||
import hou
|
||||
from avalon import api
|
||||
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS
|
||||
|
||||
|
||||
def file_extensions():
|
||||
return api.HOST_WORKFILE_EXTENSIONS["houdini"]
|
||||
return HOST_WORKFILE_EXTENSIONS["houdini"]
|
||||
|
||||
|
||||
def has_unsaved_changes():
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
"""
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import load
|
||||
|
||||
|
||||
class SetFrameRangeLoader(api.Loader):
|
||||
class SetFrameRangeLoader(load.LoaderPlugin):
|
||||
"""Set Houdini frame range"""
|
||||
|
||||
families = [
|
||||
|
|
@ -43,7 +43,7 @@ class SetFrameRangeLoader(api.Loader):
|
|||
hou.playbar.setPlaybackRange(start, end)
|
||||
|
||||
|
||||
class SetFrameRangeWithHandlesLoader(api.Loader):
|
||||
class SetFrameRangeWithHandlesLoader(load.LoaderPlugin):
|
||||
"""Set Maya frame range including pre- and post-handles"""
|
||||
|
||||
families = [
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import os
|
||||
from avalon import api
|
||||
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from openpype.hosts.houdini.api import pipeline
|
||||
|
||||
|
||||
class AbcLoader(api.Loader):
|
||||
class AbcLoader(load.LoaderPlugin):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["model", "animation", "pointcache", "gpuCache"]
|
||||
|
|
@ -90,7 +92,7 @@ class AbcLoader(api.Loader):
|
|||
return
|
||||
|
||||
# Update the file path
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = get_representation_path(representation)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
|
||||
alembic_node.setParms({"fileName": file_path})
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
import os
|
||||
|
||||
from avalon import api
|
||||
from avalon.houdini import pipeline
|
||||
import clique
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
|
||||
from openpype.hosts.houdini.api import pipeline
|
||||
|
||||
|
||||
class AssLoader(api.Loader):
|
||||
class AssLoader(load.LoaderPlugin):
|
||||
"""Load .ass with Arnold Procedural"""
|
||||
|
||||
families = ["ass"]
|
||||
|
|
@ -88,7 +92,7 @@ class AssLoader(api.Loader):
|
|||
def update(self, container, representation):
|
||||
|
||||
# Update the file path
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = get_representation_path(representation)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
|
||||
procedural = container["node"]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from openpype.hosts.houdini.api import pipeline
|
||||
|
||||
|
||||
|
|
@ -74,7 +77,7 @@ def transfer_non_default_values(src, dest, ignore=None):
|
|||
dest_parm.setFromParm(parm)
|
||||
|
||||
|
||||
class CameraLoader(api.Loader):
|
||||
class CameraLoader(load.LoaderPlugin):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["camera"]
|
||||
|
|
@ -129,7 +132,7 @@ class CameraLoader(api.Loader):
|
|||
node = container["node"]
|
||||
|
||||
# Update the file path
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = get_representation_path(representation)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
|
||||
# Update attributes
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from avalon import api
|
||||
|
||||
import os
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from openpype.hosts.houdini.api import pipeline
|
||||
|
||||
|
||||
class HdaLoader(api.Loader):
|
||||
class HdaLoader(load.LoaderPlugin):
|
||||
"""Load Houdini Digital Asset file."""
|
||||
|
||||
families = ["hda"]
|
||||
|
|
@ -15,7 +18,6 @@ class HdaLoader(api.Loader):
|
|||
color = "orange"
|
||||
|
||||
def load(self, context, name=None, namespace=None, data=None):
|
||||
import os
|
||||
import hou
|
||||
|
||||
# Format file name, Houdini only wants forward slashes
|
||||
|
|
@ -49,7 +51,7 @@ class HdaLoader(api.Loader):
|
|||
import hou
|
||||
|
||||
hda_node = container["node"]
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = get_representation_path(representation)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
hou.hda.installFile(file_path)
|
||||
defs = hda_node.type().allInstalledDefinitions()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import os
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.houdini.api import lib, pipeline
|
||||
|
||||
import hou
|
||||
|
|
@ -37,7 +41,7 @@ def get_image_avalon_container():
|
|||
return image_container
|
||||
|
||||
|
||||
class ImageLoader(api.Loader):
|
||||
class ImageLoader(load.LoaderPlugin):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["colorbleed.imagesequence"]
|
||||
|
|
@ -70,7 +74,7 @@ class ImageLoader(api.Loader):
|
|||
# Imprint it manually
|
||||
data = {
|
||||
"schema": "avalon-core:container-2.0",
|
||||
"id": pipeline.AVALON_CONTAINER_ID,
|
||||
"id": AVALON_CONTAINER_ID,
|
||||
"name": node_name,
|
||||
"namespace": namespace,
|
||||
"loader": str(self.__class__.__name__),
|
||||
|
|
@ -87,7 +91,7 @@ class ImageLoader(api.Loader):
|
|||
node = container["node"]
|
||||
|
||||
# Update the file path
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = get_representation_path(representation)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
file_path = self._get_file_sequence(file_path)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
from avalon import api
|
||||
from openpype.hosts.houdini.api import lib, pipeline
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.houdini.api import lib
|
||||
|
||||
|
||||
class USDSublayerLoader(api.Loader):
|
||||
class USDSublayerLoader(load.LoaderPlugin):
|
||||
"""Sublayer USD file in Solaris"""
|
||||
|
||||
families = [
|
||||
|
|
@ -40,7 +44,7 @@ class USDSublayerLoader(api.Loader):
|
|||
# Imprint it manually
|
||||
data = {
|
||||
"schema": "avalon-core:container-2.0",
|
||||
"id": pipeline.AVALON_CONTAINER_ID,
|
||||
"id": AVALON_CONTAINER_ID,
|
||||
"name": node_name,
|
||||
"namespace": namespace,
|
||||
"loader": str(self.__class__.__name__),
|
||||
|
|
@ -57,7 +61,7 @@ class USDSublayerLoader(api.Loader):
|
|||
node = container["node"]
|
||||
|
||||
# Update the file path
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = get_representation_path(representation)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
|
||||
# Update attributes
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
from avalon import api
|
||||
from openpype.hosts.houdini.api import lib, pipeline
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.houdini.api import lib
|
||||
|
||||
|
||||
class USDReferenceLoader(api.Loader):
|
||||
class USDReferenceLoader(load.LoaderPlugin):
|
||||
"""Reference USD file in Solaris"""
|
||||
|
||||
families = [
|
||||
|
|
@ -40,7 +44,7 @@ class USDReferenceLoader(api.Loader):
|
|||
# Imprint it manually
|
||||
data = {
|
||||
"schema": "avalon-core:container-2.0",
|
||||
"id": pipeline.AVALON_CONTAINER_ID,
|
||||
"id": AVALON_CONTAINER_ID,
|
||||
"name": node_name,
|
||||
"namespace": namespace,
|
||||
"loader": str(self.__class__.__name__),
|
||||
|
|
@ -57,7 +61,7 @@ class USDReferenceLoader(api.Loader):
|
|||
node = container["node"]
|
||||
|
||||
# Update the file path
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = get_representation_path(representation)
|
||||
file_path = file_path.replace("\\", "/")
|
||||
|
||||
# Update attributes
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import os
|
||||
import re
|
||||
from avalon import api
|
||||
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from openpype.hosts.houdini.api import pipeline
|
||||
|
||||
|
||||
class VdbLoader(api.Loader):
|
||||
class VdbLoader(load.LoaderPlugin):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["vdbcache"]
|
||||
|
|
@ -96,7 +99,7 @@ class VdbLoader(api.Loader):
|
|||
return
|
||||
|
||||
# Update the file path
|
||||
file_path = api.get_representation_path(representation)
|
||||
file_path = get_representation_path(representation)
|
||||
file_path = self.format_path(file_path)
|
||||
|
||||
file_node.setParms({"fileName": file_path})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from avalon import api
|
||||
from openpype.pipeline import load
|
||||
|
||||
|
||||
class ShowInUsdview(api.Loader):
|
||||
class ShowInUsdview(load.LoaderPlugin):
|
||||
"""Open USD file in usdview"""
|
||||
|
||||
families = ["colorbleed.usd"]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from collections import deque
|
|||
import pyblish.api
|
||||
import openpype.api
|
||||
|
||||
from openpype.pipeline import get_representation_path
|
||||
import openpype.hosts.houdini.api.usd as hou_usdlib
|
||||
from openpype.hosts.houdini.api.lib import render_rop
|
||||
|
||||
|
|
@ -308,7 +309,7 @@ class ExtractUSDLayered(openpype.api.Extractor):
|
|||
self.log.debug("No existing representation..")
|
||||
return False
|
||||
|
||||
old_file = api.get_representation_path(representation)
|
||||
old_file = get_representation_path(representation)
|
||||
if not os.path.exists(old_file):
|
||||
return False
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,6 @@ class AvalonURIOutputProcessor(base.OutputProcessorBase):
|
|||
path = self._template.format(**{
|
||||
"root": root,
|
||||
"project": PROJECT,
|
||||
"silo": asset_doc["silo"],
|
||||
"asset": asset_doc["name"],
|
||||
"subset": subset,
|
||||
"representation": ext,
|
||||
|
|
@ -165,4 +164,3 @@ output_processor = AvalonURIOutputProcessor()
|
|||
|
||||
def usdOutputProcessor():
|
||||
return output_processor
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,16 @@ import bson
|
|||
from maya import cmds, mel
|
||||
import maya.api.OpenMaya as om
|
||||
|
||||
from avalon import api, io, pipeline
|
||||
from avalon import api, io
|
||||
|
||||
from openpype import lib
|
||||
from openpype.api import get_anatomy_settings
|
||||
from openpype.pipeline import (
|
||||
discover_loader_plugins,
|
||||
loaders_from_representation,
|
||||
get_representation_path,
|
||||
load_container,
|
||||
)
|
||||
from .commands import reset_frame_range
|
||||
|
||||
|
||||
|
|
@ -1580,21 +1586,21 @@ def assign_look_by_version(nodes, version_id):
|
|||
log.info("Using look for the first time ..")
|
||||
|
||||
# Load file
|
||||
loaders = api.loaders_from_representation(api.discover(api.Loader),
|
||||
representation_id)
|
||||
_loaders = discover_loader_plugins()
|
||||
loaders = loaders_from_representation(_loaders, representation_id)
|
||||
Loader = next((i for i in loaders if i.__name__ == "LookLoader"), None)
|
||||
if Loader is None:
|
||||
raise RuntimeError("Could not find LookLoader, this is a bug")
|
||||
|
||||
# Reference the look file
|
||||
with maintained_selection():
|
||||
container_node = pipeline.load(Loader, look_representation)
|
||||
container_node = load_container(Loader, look_representation)
|
||||
|
||||
# Get container members
|
||||
shader_nodes = get_container_members(container_node)
|
||||
|
||||
# Load relationships
|
||||
shader_relation = api.get_representation_path(json_representation)
|
||||
shader_relation = get_representation_path(json_representation)
|
||||
with open(shader_relation, "r") as f:
|
||||
relationships = json.load(f)
|
||||
|
||||
|
|
@ -1931,18 +1937,26 @@ def remove_other_uv_sets(mesh):
|
|||
cmds.removeMultiInstance(attr, b=True)
|
||||
|
||||
|
||||
def get_id_from_history(node):
|
||||
def get_id_from_sibling(node, history_only=True):
|
||||
"""Return first node id in the history chain that matches this node.
|
||||
|
||||
The nodes in history must be of the exact same node type and must be
|
||||
parented under the same parent.
|
||||
|
||||
Optionally, if no matching node is found from the history, all the
|
||||
siblings of the node that are of the same type are checked.
|
||||
Additionally to having the same parent, the sibling must be marked as
|
||||
'intermediate object'.
|
||||
|
||||
Args:
|
||||
node (str): node to retrieve the
|
||||
node (str): node to retrieve the history from
|
||||
history_only (bool): if True and if nothing found in history,
|
||||
look for an 'intermediate object' in all the node's siblings
|
||||
of same type
|
||||
|
||||
Returns:
|
||||
str or None: The id from the node in history or None when no id found
|
||||
on any valid nodes in the history.
|
||||
str or None: The id from the sibling node or None when no id found
|
||||
on any valid nodes in the history or siblings.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1971,6 +1985,45 @@ def get_id_from_history(node):
|
|||
if _id:
|
||||
return _id
|
||||
|
||||
if not history_only:
|
||||
# Get siblings of same type
|
||||
similar_nodes = cmds.listRelatives(parent,
|
||||
type=node_type,
|
||||
fullPath=True)
|
||||
similar_nodes = cmds.ls(similar_nodes, exactType=node_type, long=True)
|
||||
|
||||
# Exclude itself
|
||||
similar_nodes = [x for x in similar_nodes if x != node]
|
||||
|
||||
# Get all unique ids from siblings in order since
|
||||
# we consistently take the first one found
|
||||
sibling_ids = OrderedDict()
|
||||
for similar_node in similar_nodes:
|
||||
# Check if "intermediate object"
|
||||
if not cmds.getAttr(similar_node + ".intermediateObject"):
|
||||
continue
|
||||
|
||||
_id = get_id(similar_node)
|
||||
if not _id:
|
||||
continue
|
||||
|
||||
if _id in sibling_ids:
|
||||
sibling_ids[_id].append(similar_node)
|
||||
else:
|
||||
sibling_ids[_id] = [similar_node]
|
||||
|
||||
if sibling_ids:
|
||||
first_id, found_nodes = next(iter(sibling_ids.items()))
|
||||
|
||||
# Log a warning if we've found multiple unique ids
|
||||
if len(sibling_ids) > 1:
|
||||
log.warning(("Found more than 1 intermediate shape with"
|
||||
" unique id for '{}'. Using id of first"
|
||||
" found: '{}'".format(node, found_nodes[0])))
|
||||
|
||||
return first_id
|
||||
|
||||
|
||||
|
||||
# Project settings
|
||||
def set_scene_fps(fps, update=True):
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import pyblish.api
|
|||
import avalon.api
|
||||
|
||||
from avalon.lib import find_submodule
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
|
||||
import openpype.hosts.maya
|
||||
from openpype.tools.utils import host_tools
|
||||
|
|
@ -20,7 +19,14 @@ from openpype.lib import (
|
|||
emit_event
|
||||
)
|
||||
from openpype.lib.path_tools import HostDirmap
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
register_inventory_action_path,
|
||||
deregister_loader_plugin_path,
|
||||
deregister_inventory_action_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.hosts.maya.lib import copy_workspace_mel
|
||||
from . import menu, lib
|
||||
|
||||
|
|
@ -53,9 +59,9 @@ def install():
|
|||
pyblish.api.register_host("mayapy")
|
||||
pyblish.api.register_host("maya")
|
||||
|
||||
avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.register_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
avalon.api.register_plugin_path(avalon.api.InventoryAction, INVENTORY_PATH)
|
||||
register_inventory_action_path(INVENTORY_PATH)
|
||||
log.info(PUBLISH_PATH)
|
||||
|
||||
log.info("Installing callbacks ... ")
|
||||
|
|
@ -182,11 +188,9 @@ def uninstall():
|
|||
pyblish.api.deregister_host("mayapy")
|
||||
pyblish.api.deregister_host("maya")
|
||||
|
||||
avalon.api.deregister_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
deregister_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.deregister_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
avalon.api.deregister_plugin_path(
|
||||
avalon.api.InventoryAction, INVENTORY_PATH
|
||||
)
|
||||
deregister_inventory_action_path(INVENTORY_PATH)
|
||||
|
||||
menu.uninstall()
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,12 @@ from maya import cmds
|
|||
|
||||
import qargparse
|
||||
|
||||
from avalon import api
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
LoaderPlugin,
|
||||
get_representation_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
|
||||
from .pipeline import containerise
|
||||
from . import lib
|
||||
|
|
@ -95,7 +98,7 @@ class Creator(LegacyCreator):
|
|||
return instance
|
||||
|
||||
|
||||
class Loader(api.Loader):
|
||||
class Loader(LoaderPlugin):
|
||||
hosts = ["maya"]
|
||||
|
||||
|
||||
|
|
@ -178,7 +181,7 @@ class ReferenceLoader(Loader):
|
|||
loader=self.__class__.__name__
|
||||
)
|
||||
loaded_containers.append(container)
|
||||
self._organize_containers([ref_node], container)
|
||||
self._organize_containers(nodes, container)
|
||||
c += 1
|
||||
namespace = None
|
||||
|
||||
|
|
@ -194,7 +197,7 @@ class ReferenceLoader(Loader):
|
|||
|
||||
node = container["objectName"]
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
|
||||
# Get reference node from container members
|
||||
members = get_container_members(node)
|
||||
|
|
@ -247,6 +250,8 @@ class ReferenceLoader(Loader):
|
|||
|
||||
self.log.warning("Ignoring file read error:\n%s", exc)
|
||||
|
||||
self._organize_containers(content, container["objectName"])
|
||||
|
||||
# Reapply alembic settings.
|
||||
if representation["name"] == "abc" and alembic_data:
|
||||
alembic_nodes = cmds.ls(
|
||||
|
|
@ -284,7 +289,6 @@ class ReferenceLoader(Loader):
|
|||
to remove from scene.
|
||||
|
||||
"""
|
||||
|
||||
from maya import cmds
|
||||
|
||||
node = container["objectName"]
|
||||
|
|
@ -318,6 +322,7 @@ class ReferenceLoader(Loader):
|
|||
@staticmethod
|
||||
def _organize_containers(nodes, container):
|
||||
# type: (list, str) -> None
|
||||
"""Put containers in loaded data to correct hierarchy."""
|
||||
for node in nodes:
|
||||
id_attr = "{}.id".format(node)
|
||||
if not cmds.attributeQuery("id", node=node, exists=True):
|
||||
|
|
|
|||
|
|
@ -6,9 +6,19 @@ import contextlib
|
|||
import copy
|
||||
|
||||
import six
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
from maya import cmds
|
||||
|
||||
from avalon import api, io
|
||||
from avalon import io
|
||||
from openpype.pipeline import (
|
||||
discover_loader_plugins,
|
||||
loaders_from_representation,
|
||||
load_container,
|
||||
update_container,
|
||||
remove_container,
|
||||
get_representation_path,
|
||||
)
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
matrix_equals,
|
||||
unique_namespace
|
||||
|
|
@ -120,12 +130,13 @@ def load_package(filepath, name, namespace=None):
|
|||
root = "{}:{}".format(namespace, name)
|
||||
|
||||
containers = []
|
||||
all_loaders = api.discover(api.Loader)
|
||||
all_loaders = discover_loader_plugins()
|
||||
for representation_id, instances in data.items():
|
||||
|
||||
# Find the compatible loaders
|
||||
loaders = api.loaders_from_representation(all_loaders,
|
||||
representation_id)
|
||||
loaders = loaders_from_representation(
|
||||
all_loaders, representation_id
|
||||
)
|
||||
|
||||
for instance in instances:
|
||||
container = _add(instance=instance,
|
||||
|
|
@ -180,9 +191,11 @@ def _add(instance, representation_id, loaders, namespace, root="|"):
|
|||
instance['loader'], instance)
|
||||
raise RuntimeError("Loader is missing.")
|
||||
|
||||
container = api.load(Loader,
|
||||
representation_id,
|
||||
namespace=instance['namespace'])
|
||||
container = load_container(
|
||||
Loader,
|
||||
representation_id,
|
||||
namespace=instance['namespace']
|
||||
)
|
||||
|
||||
# Get the root from the loaded container
|
||||
loaded_root = get_container_transforms({"objectName": container},
|
||||
|
|
@ -271,7 +284,7 @@ def update_package_version(container, version):
|
|||
|
||||
# Versioning (from `core.maya.pipeline`)
|
||||
current_representation = io.find_one({
|
||||
"_id": io.ObjectId(container["representation"])
|
||||
"_id": ObjectId(container["representation"])
|
||||
})
|
||||
|
||||
assert current_representation is not None, "This is a bug"
|
||||
|
|
@ -316,17 +329,17 @@ def update_package(set_container, representation):
|
|||
|
||||
# Load the original package data
|
||||
current_representation = io.find_one({
|
||||
"_id": io.ObjectId(set_container['representation']),
|
||||
"_id": ObjectId(set_container['representation']),
|
||||
"type": "representation"
|
||||
})
|
||||
|
||||
current_file = api.get_representation_path(current_representation)
|
||||
current_file = get_representation_path(current_representation)
|
||||
assert current_file.endswith(".json")
|
||||
with open(current_file, "r") as fp:
|
||||
current_data = json.load(fp)
|
||||
|
||||
# Load the new package data
|
||||
new_file = api.get_representation_path(representation)
|
||||
new_file = get_representation_path(representation)
|
||||
assert new_file.endswith(".json")
|
||||
with open(new_file, "r") as fp:
|
||||
new_data = json.load(fp)
|
||||
|
|
@ -460,17 +473,17 @@ def update_scene(set_container, containers, current_data, new_data, new_file):
|
|||
# considered as new element and added afterwards.
|
||||
processed_containers.pop()
|
||||
processed_namespaces.remove(container_ns)
|
||||
api.remove(container)
|
||||
remove_container(container)
|
||||
continue
|
||||
|
||||
# Check whether the conversion can be done by the Loader.
|
||||
# They *must* use the same asset, subset and Loader for
|
||||
# `api.update` to make sense.
|
||||
# `update_container` to make sense.
|
||||
old = io.find_one({
|
||||
"_id": io.ObjectId(representation_current)
|
||||
"_id": ObjectId(representation_current)
|
||||
})
|
||||
new = io.find_one({
|
||||
"_id": io.ObjectId(representation_new)
|
||||
"_id": ObjectId(representation_new)
|
||||
})
|
||||
is_valid = compare_representations(old=old, new=new)
|
||||
if not is_valid:
|
||||
|
|
@ -479,20 +492,21 @@ def update_scene(set_container, containers, current_data, new_data, new_file):
|
|||
continue
|
||||
|
||||
new_version = new["context"]["version"]
|
||||
api.update(container, version=new_version)
|
||||
update_container(container, version=new_version)
|
||||
|
||||
else:
|
||||
# Remove this container because it's not in the new data
|
||||
log.warning("Removing content: %s", container_ns)
|
||||
api.remove(container)
|
||||
remove_container(container)
|
||||
|
||||
# Add new assets
|
||||
all_loaders = api.discover(api.Loader)
|
||||
all_loaders = discover_loader_plugins()
|
||||
for representation_id, instances in new_data.items():
|
||||
|
||||
# Find the compatible loaders
|
||||
loaders = api.loaders_from_representation(all_loaders,
|
||||
representation_id)
|
||||
loaders = loaders_from_representation(
|
||||
all_loaders, representation_id
|
||||
)
|
||||
for instance in instances:
|
||||
|
||||
# Already processed in update functionality
|
||||
|
|
@ -517,7 +531,7 @@ def update_scene(set_container, containers, current_data, new_data, new_file):
|
|||
def compare_representations(old, new):
|
||||
"""Check if the old representation given can be updated
|
||||
|
||||
Due to limitations of the `api.update` function we cannot allow
|
||||
Due to limitations of the `update_container` function we cannot allow
|
||||
differences in the following data:
|
||||
|
||||
* Representation name (extension)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
"""Host API required Work Files tool"""
|
||||
import os
|
||||
from maya import cmds
|
||||
from avalon import api
|
||||
|
||||
from openpype.pipeline import HOST_WORKFILE_EXTENSIONS
|
||||
|
||||
|
||||
def file_extensions():
|
||||
return api.HOST_WORKFILE_EXTENSIONS["maya"]
|
||||
return HOST_WORKFILE_EXTENSIONS["maya"]
|
||||
|
||||
|
||||
def has_unsaved_changes():
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
import json
|
||||
from avalon import api, io, pipeline
|
||||
from avalon import io
|
||||
from bson.objectid import ObjectId
|
||||
from openpype.pipeline import (
|
||||
InventoryAction,
|
||||
get_representation_context,
|
||||
get_representation_path_from_context,
|
||||
)
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
maintained_selection,
|
||||
apply_shaders
|
||||
)
|
||||
|
||||
|
||||
class ImportModelRender(api.InventoryAction):
|
||||
class ImportModelRender(InventoryAction):
|
||||
|
||||
label = "Import Model Render Sets"
|
||||
icon = "industry"
|
||||
|
|
@ -35,7 +41,7 @@ class ImportModelRender(api.InventoryAction):
|
|||
nodes.append(n)
|
||||
|
||||
repr_doc = io.find_one({
|
||||
"_id": io.ObjectId(container["representation"]),
|
||||
"_id": ObjectId(container["representation"]),
|
||||
})
|
||||
version_id = repr_doc["parent"]
|
||||
|
||||
|
|
@ -73,11 +79,11 @@ class ImportModelRender(api.InventoryAction):
|
|||
"name": self.look_data_type,
|
||||
})
|
||||
|
||||
context = pipeline.get_representation_context(look_repr["_id"])
|
||||
maya_file = pipeline.get_representation_path_from_context(context)
|
||||
context = get_representation_context(look_repr["_id"])
|
||||
maya_file = get_representation_path_from_context(context)
|
||||
|
||||
context = pipeline.get_representation_context(json_repr["_id"])
|
||||
json_file = pipeline.get_representation_path_from_context(context)
|
||||
context = get_representation_context(json_repr["_id"])
|
||||
json_file = get_representation_path_from_context(context)
|
||||
|
||||
# Import the look file
|
||||
with maintained_selection():
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from maya import cmds
|
||||
|
||||
from avalon import api
|
||||
|
||||
from openpype.pipeline import InventoryAction
|
||||
from openpype.hosts.maya.api.plugin import get_reference_node
|
||||
|
||||
|
||||
class ImportReference(api.InventoryAction):
|
||||
class ImportReference(InventoryAction):
|
||||
"""Imports selected reference to inside of the file."""
|
||||
|
||||
label = "Import Reference"
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
"""
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import load
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
maintained_selection,
|
||||
unique_namespace
|
||||
)
|
||||
|
||||
|
||||
class SetFrameRangeLoader(api.Loader):
|
||||
class SetFrameRangeLoader(load.LoaderPlugin):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["animation",
|
||||
|
|
@ -43,7 +43,7 @@ class SetFrameRangeLoader(api.Loader):
|
|||
animationEndTime=end)
|
||||
|
||||
|
||||
class SetFrameRangeWithHandlesLoader(api.Loader):
|
||||
class SetFrameRangeWithHandlesLoader(load.LoaderPlugin):
|
||||
"""Specific loader of Alembic for the avalon.animation family"""
|
||||
|
||||
families = ["animation",
|
||||
|
|
@ -81,7 +81,7 @@ class SetFrameRangeWithHandlesLoader(api.Loader):
|
|||
animationEndTime=end)
|
||||
|
||||
|
||||
class ImportMayaLoader(api.Loader):
|
||||
class ImportMayaLoader(load.LoaderPlugin):
|
||||
"""Import action for Maya (unmanaged)
|
||||
|
||||
Warning:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import os
|
||||
import clique
|
||||
|
||||
from avalon import api
|
||||
from openpype.api import get_project_settings
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
import openpype.hosts.maya.api.plugin
|
||||
from openpype.hosts.maya.api.plugin import get_reference_node
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
|
|
@ -106,7 +109,7 @@ class AssProxyLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
node = container["objectName"]
|
||||
|
||||
representation["context"].pop("frame", None)
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
print(path)
|
||||
# path = self.fname
|
||||
print(self.fname)
|
||||
|
|
@ -164,7 +167,7 @@ class AssProxyLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
type="string")
|
||||
|
||||
|
||||
class AssStandinLoader(api.Loader):
|
||||
class AssStandinLoader(load.LoaderPlugin):
|
||||
"""Load .ASS file as standin"""
|
||||
|
||||
families = ["ass"]
|
||||
|
|
@ -240,7 +243,7 @@ class AssStandinLoader(api.Loader):
|
|||
|
||||
import pymel.core as pm
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
|
||||
files_in_path = os.listdir(os.path.split(path)[0])
|
||||
sequence = 0
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
remove_container
|
||||
)
|
||||
|
||||
|
||||
class AssemblyLoader(api.Loader):
|
||||
class AssemblyLoader(load.LoaderPlugin):
|
||||
|
||||
families = ["assembly"]
|
||||
representations = ["json"]
|
||||
|
|
@ -48,13 +51,11 @@ class AssemblyLoader(api.Loader):
|
|||
def update(self, container, representation):
|
||||
|
||||
from openpype import setdress
|
||||
return setdress.update_package(container,
|
||||
representation)
|
||||
return setdress.update_package(container, representation)
|
||||
|
||||
def remove(self, container):
|
||||
"""Remove all sub containers"""
|
||||
|
||||
from avalon import api
|
||||
from openpype import setdress
|
||||
import maya.cmds as cmds
|
||||
|
||||
|
|
@ -63,7 +64,7 @@ class AssemblyLoader(api.Loader):
|
|||
for member_container in member_containers:
|
||||
self.log.info("Removing container %s",
|
||||
member_container['objectName'])
|
||||
api.remove(member_container)
|
||||
remove_container(member_container)
|
||||
|
||||
# Remove alembic hierarchy reference
|
||||
# TODO: Check whether removing all contained references is safe enough
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
from maya import cmds, mel
|
||||
from avalon import api, io
|
||||
from avalon import io
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
from openpype.hosts.maya.api.pipeline import containerise
|
||||
from openpype.hosts.maya.api.lib import unique_namespace
|
||||
|
||||
|
||||
class AudioLoader(api.Loader):
|
||||
class AudioLoader(load.LoaderPlugin):
|
||||
"""Specific loader of audio."""
|
||||
|
||||
families = ["audio"]
|
||||
|
|
@ -51,7 +55,7 @@ class AudioLoader(api.Loader):
|
|||
|
||||
assert audio_node is not None, "Audio node not found."
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
audio_node.filename.set(path)
|
||||
cmds.setAttr(
|
||||
container["objectName"] + ".representation",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
import os
|
||||
from avalon import api
|
||||
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
from openpype.api import get_project_settings
|
||||
|
||||
|
||||
class GpuCacheLoader(api.Loader):
|
||||
class GpuCacheLoader(load.LoaderPlugin):
|
||||
"""Load model Alembic as gpuCache"""
|
||||
|
||||
families = ["model"]
|
||||
|
|
@ -73,7 +77,7 @@ class GpuCacheLoader(api.Loader):
|
|||
|
||||
import maya.cmds as cmds
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
|
||||
# Update the cache
|
||||
members = cmds.sets(container['objectName'], query=True)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
from Qt import QtWidgets, QtCore
|
||||
|
||||
from avalon import api, io
|
||||
from avalon import io
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
from openpype.hosts.maya.api.pipeline import containerise
|
||||
from openpype.hosts.maya.api.lib import unique_namespace
|
||||
|
||||
|
|
@ -74,7 +78,7 @@ class CameraWindow(QtWidgets.QDialog):
|
|||
self.close()
|
||||
|
||||
|
||||
class ImagePlaneLoader(api.Loader):
|
||||
class ImagePlaneLoader(load.LoaderPlugin):
|
||||
"""Specific loader of plate for image planes on selected camera."""
|
||||
|
||||
families = ["image", "plate", "render"]
|
||||
|
|
@ -203,7 +207,7 @@ class ImagePlaneLoader(api.Loader):
|
|||
|
||||
assert image_plane_shape is not None, "Image plane not found."
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
image_plane_shape.imageName.set(path)
|
||||
cmds.setAttr(
|
||||
container["objectName"] + ".representation",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ from collections import defaultdict
|
|||
|
||||
from Qt import QtWidgets
|
||||
|
||||
from avalon import api, io
|
||||
from avalon import io
|
||||
from openpype.pipeline import get_representation_path
|
||||
import openpype.hosts.maya.api.plugin
|
||||
from openpype.hosts.maya.api import lib
|
||||
from openpype.widgets.message_window import ScrollMessageBox
|
||||
|
|
@ -77,7 +78,7 @@ class LookLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
})
|
||||
|
||||
# Load relationships
|
||||
shader_relation = api.get_representation_path(json_representation)
|
||||
shader_relation = get_representation_path(json_representation)
|
||||
with open(shader_relation, "r") as f:
|
||||
json_data = json.load(f)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from avalon import api
|
||||
from maya import mel
|
||||
from openpype.pipeline import load
|
||||
|
||||
|
||||
class MatchmoveLoader(api.Loader):
|
||||
class MatchmoveLoader(load.LoaderPlugin):
|
||||
"""
|
||||
This will run matchmove script to create track in scene.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ import clique
|
|||
|
||||
import maya.cmds as cmds
|
||||
|
||||
from avalon import api
|
||||
from openpype.api import get_project_settings
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
namespaced,
|
||||
maintained_selection,
|
||||
|
|
@ -15,7 +18,7 @@ from openpype.hosts.maya.api.lib import (
|
|||
from openpype.hosts.maya.api.pipeline import containerise
|
||||
|
||||
|
||||
class RedshiftProxyLoader(api.Loader):
|
||||
class RedshiftProxyLoader(load.LoaderPlugin):
|
||||
"""Load Redshift proxy"""
|
||||
|
||||
families = ["redshiftproxy"]
|
||||
|
|
@ -78,7 +81,7 @@ class RedshiftProxyLoader(api.Loader):
|
|||
rs_meshes = cmds.ls(members, type="RedshiftProxyMesh")
|
||||
assert rs_meshes, "Cannot find RedshiftProxyMesh in container"
|
||||
|
||||
filename = api.get_representation_path(representation)
|
||||
filename = get_representation_path(representation)
|
||||
|
||||
for rs_mesh in rs_meshes:
|
||||
cmds.setAttr("{}.fileName".format(rs_mesh),
|
||||
|
|
|
|||
|
|
@ -121,18 +121,10 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
if family == "rig":
|
||||
self._post_process_rig(name, namespace, context, options)
|
||||
else:
|
||||
|
||||
if "translate" in options:
|
||||
cmds.setAttr(group_name + ".t", *options["translate"])
|
||||
|
||||
return new_nodes
|
||||
|
||||
def load(self, context, name=None, namespace=None, options=None):
|
||||
container = super(ReferenceLoader, self).load(
|
||||
context, name, namespace, options)
|
||||
# clean containers if present to AVALON_CONTAINERS
|
||||
self._organize_containers(self[:], container[0])
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,13 @@ instance.
|
|||
"""
|
||||
|
||||
import json
|
||||
import six
|
||||
import sys
|
||||
import six
|
||||
|
||||
from avalon import api
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
from openpype.hosts.maya.api import lib
|
||||
from openpype.hosts.maya.api.pipeline import containerise
|
||||
|
||||
|
|
@ -18,7 +21,7 @@ from maya import cmds
|
|||
import maya.app.renderSetup.model.renderSetup as renderSetup
|
||||
|
||||
|
||||
class RenderSetupLoader(api.Loader):
|
||||
class RenderSetupLoader(load.LoaderPlugin):
|
||||
"""Load json preset for RenderSetup overwriting current one."""
|
||||
|
||||
families = ["rendersetup"]
|
||||
|
|
@ -87,7 +90,7 @@ class RenderSetupLoader(api.Loader):
|
|||
"Render setup setting will be overwritten by new version. All "
|
||||
"setting specified by user not included in loaded version "
|
||||
"will be lost.")
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
with open(path, "r") as file:
|
||||
try:
|
||||
renderSetup.instance().decode(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import os
|
||||
from avalon import api
|
||||
|
||||
from openpype.api import get_project_settings
|
||||
from openpype.pipeline import load
|
||||
|
||||
|
||||
class LoadVDBtoRedShift(api.Loader):
|
||||
class LoadVDBtoRedShift(load.LoaderPlugin):
|
||||
"""Load OpenVDB in a Redshift Volume Shape"""
|
||||
|
||||
families = ["vdbcache"]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import os
|
||||
from avalon import api
|
||||
|
||||
from openpype.api import get_project_settings
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
|
||||
from maya import cmds
|
||||
|
||||
|
|
@ -69,7 +73,7 @@ def _fix_duplicate_vvg_callbacks():
|
|||
matched.add(callback)
|
||||
|
||||
|
||||
class LoadVDBtoVRay(api.Loader):
|
||||
class LoadVDBtoVRay(load.LoaderPlugin):
|
||||
|
||||
families = ["vdbcache"]
|
||||
representations = ["vdb"]
|
||||
|
|
@ -252,7 +256,7 @@ class LoadVDBtoVRay(api.Loader):
|
|||
|
||||
def update(self, container, representation):
|
||||
|
||||
path = api.get_representation_path(representation)
|
||||
path = get_representation_path(representation)
|
||||
|
||||
# Find VRayVolumeGrid
|
||||
members = cmds.sets(container['objectName'], query=True)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,16 @@ loader will use them instead of native vray vrmesh format.
|
|||
"""
|
||||
import os
|
||||
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
import maya.cmds as cmds
|
||||
|
||||
from avalon import api, io
|
||||
from avalon import io
|
||||
from openpype.api import get_project_settings
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
maintained_selection,
|
||||
namespaced,
|
||||
|
|
@ -19,7 +25,7 @@ from openpype.hosts.maya.api.lib import (
|
|||
from openpype.hosts.maya.api.pipeline import containerise
|
||||
|
||||
|
||||
class VRayProxyLoader(api.Loader):
|
||||
class VRayProxyLoader(load.LoaderPlugin):
|
||||
"""Load VRay Proxy with Alembic or VrayMesh."""
|
||||
|
||||
families = ["vrayproxy", "model", "pointcache", "animation"]
|
||||
|
|
@ -100,7 +106,10 @@ class VRayProxyLoader(api.Loader):
|
|||
assert vraymeshes, "Cannot find VRayMesh in container"
|
||||
|
||||
# get all representations for this version
|
||||
filename = self._get_abc(representation["parent"]) or api.get_representation_path(representation) # noqa: E501
|
||||
filename = (
|
||||
self._get_abc(representation["parent"])
|
||||
or get_representation_path(representation)
|
||||
)
|
||||
|
||||
for vray_mesh in vraymeshes:
|
||||
cmds.setAttr("{}.fileName".format(vray_mesh),
|
||||
|
|
@ -179,13 +188,13 @@ class VRayProxyLoader(api.Loader):
|
|||
abc_rep = io.find_one(
|
||||
{
|
||||
"type": "representation",
|
||||
"parent": io.ObjectId(version_id),
|
||||
"parent": ObjectId(version_id),
|
||||
"name": "abc"
|
||||
})
|
||||
|
||||
if abc_rep:
|
||||
self.log.debug("Found, we'll link alembic to vray proxy.")
|
||||
file_name = api.get_representation_path(abc_rep)
|
||||
file_name = get_representation_path(abc_rep)
|
||||
self.log.debug("File: {}".format(self.fname))
|
||||
return file_name
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import maya.cmds as cmds # noqa
|
||||
from avalon import api
|
||||
from openpype.api import get_project_settings
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
maintained_selection,
|
||||
namespaced,
|
||||
|
|
@ -11,7 +14,7 @@ from openpype.hosts.maya.api.lib import (
|
|||
from openpype.hosts.maya.api.pipeline import containerise
|
||||
|
||||
|
||||
class VRaySceneLoader(api.Loader):
|
||||
class VRaySceneLoader(load.LoaderPlugin):
|
||||
"""Load Vray scene"""
|
||||
|
||||
families = ["vrayscene_layer"]
|
||||
|
|
@ -78,7 +81,7 @@ class VRaySceneLoader(api.Loader):
|
|||
vraymeshes = cmds.ls(members, type="VRayScene")
|
||||
assert vraymeshes, "Cannot find VRayScene in container"
|
||||
|
||||
filename = api.get_representation_path(representation)
|
||||
filename = get_representation_path(representation)
|
||||
|
||||
for vray_mesh in vraymeshes:
|
||||
cmds.setAttr("{}.FilePath".format(vray_mesh),
|
||||
|
|
|
|||
|
|
@ -7,13 +7,17 @@ from pprint import pprint
|
|||
|
||||
from maya import cmds
|
||||
|
||||
from avalon import api, io
|
||||
from avalon import io
|
||||
from openpype.api import get_project_settings
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_representation_path
|
||||
)
|
||||
from openpype.hosts.maya.api import lib
|
||||
from openpype.hosts.maya.api.pipeline import containerise
|
||||
|
||||
|
||||
class YetiCacheLoader(api.Loader):
|
||||
class YetiCacheLoader(load.LoaderPlugin):
|
||||
|
||||
families = ["yeticache", "yetiRig"]
|
||||
representations = ["fur"]
|
||||
|
|
@ -121,8 +125,8 @@ class YetiCacheLoader(api.Loader):
|
|||
"cannot find fursettings representation"
|
||||
)
|
||||
|
||||
settings_fname = api.get_representation_path(fur_settings)
|
||||
path = api.get_representation_path(representation)
|
||||
settings_fname = get_representation_path(fur_settings)
|
||||
path = get_representation_path(representation)
|
||||
# Get all node data
|
||||
with open(settings_fname, "r") as fp:
|
||||
settings = json.load(fp)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from maya import cmds
|
|||
|
||||
import openpype.api
|
||||
from openpype.hosts.maya.api.lib import maintained_selection
|
||||
from avalon.pipeline import AVALON_CONTAINER_ID
|
||||
from openpype.pipeline import AVALON_CONTAINER_ID
|
||||
|
||||
|
||||
class ExtractMayaSceneRaw(openpype.api.Extractor):
|
||||
|
|
@ -58,16 +58,11 @@ class ExtractMayaSceneRaw(openpype.api.Extractor):
|
|||
else:
|
||||
members = instance[:]
|
||||
|
||||
loaded_containers = None
|
||||
if set(self.add_for_families).intersection(
|
||||
set(instance.data.get("families")),
|
||||
set(instance.data.get("family").lower())):
|
||||
loaded_containers = self._add_loaded_containers(members)
|
||||
|
||||
selection = members
|
||||
if loaded_containers:
|
||||
self.log.info(loaded_containers)
|
||||
selection += loaded_containers
|
||||
if set(self.add_for_families).intersection(
|
||||
set(instance.data.get("families", []))) or \
|
||||
instance.data.get("family") in self.add_for_families:
|
||||
selection += self._get_loaded_containers(members)
|
||||
|
||||
# Perform extraction
|
||||
self.log.info("Performing extraction ...")
|
||||
|
|
@ -97,15 +92,15 @@ class ExtractMayaSceneRaw(openpype.api.Extractor):
|
|||
self.log.info("Extracted instance '%s' to: %s" % (instance.name, path))
|
||||
|
||||
@staticmethod
|
||||
def _add_loaded_containers(members):
|
||||
def _get_loaded_containers(members):
|
||||
# type: (list) -> list
|
||||
refs_to_include = [
|
||||
cmds.referenceQuery(ref, referenceNode=True)
|
||||
for ref in members
|
||||
if cmds.referenceQuery(ref, isNodeReferenced=True)
|
||||
]
|
||||
refs_to_include = {
|
||||
cmds.referenceQuery(node, referenceNode=True)
|
||||
for node in members
|
||||
if cmds.referenceQuery(node, isNodeReferenced=True)
|
||||
}
|
||||
|
||||
refs_to_include = set(refs_to_include)
|
||||
members_with_refs = refs_to_include.union(members)
|
||||
|
||||
obj_sets = cmds.ls("*.id", long=True, type="objectSet", recursive=True,
|
||||
objectsOnly=True)
|
||||
|
|
@ -121,7 +116,7 @@ class ExtractMayaSceneRaw(openpype.api.Extractor):
|
|||
continue
|
||||
|
||||
set_content = set(cmds.sets(obj_set, query=True))
|
||||
if set_content.intersection(refs_to_include):
|
||||
if set_content.intersection(members_with_refs):
|
||||
loaded_containers.append(obj_set)
|
||||
|
||||
return loaded_containers
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin):
|
|||
# if a deformer has been created on the shape
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Nodes found with non-related "
|
||||
"asset IDs: {0}".format(invalid))
|
||||
raise RuntimeError("Nodes found with mismatching "
|
||||
"IDs: {0}".format(invalid))
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
|
@ -65,7 +65,7 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin):
|
|||
invalid.append(node)
|
||||
continue
|
||||
|
||||
history_id = lib.get_id_from_history(node)
|
||||
history_id = lib.get_id_from_sibling(node)
|
||||
if history_id is not None and node_id != history_id:
|
||||
invalid.append(node)
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin):
|
|||
|
||||
for node in cls.get_invalid(instance):
|
||||
# Get the original id from history
|
||||
history_id = lib.get_id_from_history(node)
|
||||
history_id = lib.get_id_from_sibling(node)
|
||||
if not history_id:
|
||||
cls.log.error("Could not find ID in history for '%s'", node)
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class ValidateNodeIdsDeformedShape(pyblish.api.InstancePlugin):
|
|||
|
||||
invalid = []
|
||||
for shape in shapes:
|
||||
history_id = lib.get_id_from_history(shape)
|
||||
history_id = lib.get_id_from_sibling(shape)
|
||||
if history_id:
|
||||
current_id = lib.get_id(shape)
|
||||
if current_id != history_id:
|
||||
|
|
@ -61,7 +61,7 @@ class ValidateNodeIdsDeformedShape(pyblish.api.InstancePlugin):
|
|||
|
||||
for node in cls.get_invalid(instance):
|
||||
# Get the original id from history
|
||||
history_id = lib.get_id_from_history(node)
|
||||
history_id = lib.get_id_from_sibling(node)
|
||||
if not history_id:
|
||||
cls.log.error("Could not find ID in history for '%s'", node)
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
|
|||
openpype.hosts.maya.api.action.SelectInvalidAction,
|
||||
openpype.api.RepairAction
|
||||
]
|
||||
allow_history_only = False
|
||||
|
||||
def process(self, instance):
|
||||
"""Process all meshes"""
|
||||
|
|
@ -32,8 +33,8 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
|
|||
# if a deformer has been created on the shape
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Nodes found with non-related "
|
||||
"asset IDs: {0}".format(invalid))
|
||||
raise RuntimeError("Nodes found with mismatching "
|
||||
"IDs: {0}".format(invalid))
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
|
@ -51,10 +52,13 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
|
|||
noIntermediate=True)
|
||||
|
||||
for shape in shapes:
|
||||
history_id = lib.get_id_from_history(shape)
|
||||
if history_id:
|
||||
sibling_id = lib.get_id_from_sibling(
|
||||
shape,
|
||||
history_only=cls.allow_history_only
|
||||
)
|
||||
if sibling_id:
|
||||
current_id = lib.get_id(shape)
|
||||
if current_id != history_id:
|
||||
if current_id != sibling_id:
|
||||
invalid.append(shape)
|
||||
|
||||
return invalid
|
||||
|
|
@ -63,10 +67,13 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
|
|||
def repair(cls, instance):
|
||||
|
||||
for node in cls.get_invalid(instance):
|
||||
# Get the original id from history
|
||||
history_id = lib.get_id_from_history(node)
|
||||
if not history_id:
|
||||
cls.log.error("Could not find ID in history for '%s'", node)
|
||||
# Get the original id from sibling
|
||||
sibling_id = lib.get_id_from_sibling(
|
||||
node,
|
||||
history_only=cls.allow_history_only
|
||||
)
|
||||
if not sibling_id:
|
||||
cls.log.error("Could not find ID in siblings for '%s'", node)
|
||||
continue
|
||||
|
||||
lib.set_id(node, history_id, overwrite=True)
|
||||
lib.set_id(node, sibling_id, overwrite=True)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import logging
|
||||
import contextlib
|
||||
import nuke
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
from avalon import api, io
|
||||
|
||||
|
|
@ -70,10 +71,10 @@ def get_handles(asset):
|
|||
if "visualParent" in data:
|
||||
vp = data["visualParent"]
|
||||
if vp is not None:
|
||||
parent_asset = io.find_one({"_id": io.ObjectId(vp)})
|
||||
parent_asset = io.find_one({"_id": ObjectId(vp)})
|
||||
|
||||
if parent_asset is None:
|
||||
parent_asset = io.find_one({"_id": io.ObjectId(asset["parent"])})
|
||||
parent_asset = io.find_one({"_id": ObjectId(asset["parent"])})
|
||||
|
||||
if parent_asset is not None:
|
||||
return get_handles(parent_asset)
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ import contextlib
|
|||
from collections import OrderedDict
|
||||
|
||||
import clique
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
import nuke
|
||||
|
||||
from avalon import api, io, lib
|
||||
from avalon import api, io
|
||||
|
||||
from openpype.api import (
|
||||
Logger,
|
||||
|
|
@ -20,7 +21,6 @@ from openpype.api import (
|
|||
get_workdir_data,
|
||||
get_asset,
|
||||
get_current_project_settings,
|
||||
ApplicationManager
|
||||
)
|
||||
from openpype.tools.utils import host_tools
|
||||
from openpype.lib.path_tools import HostDirmap
|
||||
|
|
@ -570,7 +570,7 @@ def check_inventory_versions():
|
|||
# get representation from io
|
||||
representation = io.find_one({
|
||||
"type": "representation",
|
||||
"_id": io.ObjectId(avalon_knob_data["representation"])
|
||||
"_id": ObjectId(avalon_knob_data["representation"])
|
||||
})
|
||||
|
||||
# Failsafe for not finding the representation.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import nuke
|
|||
|
||||
import pyblish.api
|
||||
import avalon.api
|
||||
from avalon import pipeline
|
||||
|
||||
import openpype
|
||||
from openpype.api import (
|
||||
|
|
@ -15,7 +14,14 @@ from openpype.api import (
|
|||
get_current_project_settings
|
||||
)
|
||||
from openpype.lib import register_event_callback
|
||||
from openpype.pipeline import LegacyCreator
|
||||
from openpype.pipeline import (
|
||||
LegacyCreator,
|
||||
register_loader_plugin_path,
|
||||
register_inventory_action_path,
|
||||
deregister_loader_plugin_path,
|
||||
deregister_inventory_action_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.tools.utils import host_tools
|
||||
|
||||
from .command import viewer_update_and_undo_stop
|
||||
|
|
@ -99,9 +105,9 @@ def install():
|
|||
|
||||
log.info("Registering Nuke plug-ins..")
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
register_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.register_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
avalon.api.register_plugin_path(avalon.api.InventoryAction, INVENTORY_PATH)
|
||||
register_inventory_action_path(INVENTORY_PATH)
|
||||
|
||||
# Register Avalon event for workfiles loading.
|
||||
register_event_callback("workio.open_file", check_inventory_versions)
|
||||
|
|
@ -125,8 +131,9 @@ def uninstall():
|
|||
log.info("Deregistering Nuke plug-ins..")
|
||||
pyblish.deregister_host("nuke")
|
||||
pyblish.api.deregister_plugin_path(PUBLISH_PATH)
|
||||
avalon.api.deregister_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
deregister_loader_plugin_path(LOAD_PATH)
|
||||
avalon.api.deregister_plugin_path(LegacyCreator, CREATE_PATH)
|
||||
deregister_inventory_action_path(INVENTORY_PATH)
|
||||
|
||||
pyblish.api.deregister_callback(
|
||||
"instanceToggled", on_pyblish_instance_toggled)
|
||||
|
|
@ -326,7 +333,7 @@ def containerise(node,
|
|||
data = OrderedDict(
|
||||
[
|
||||
("schema", "openpype:container-2.0"),
|
||||
("id", pipeline.AVALON_CONTAINER_ID),
|
||||
("id", AVALON_CONTAINER_ID),
|
||||
("name", name),
|
||||
("namespace", namespace),
|
||||
("loader", str(loader)),
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue