diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py
index 7339f639b3..01f80267d8 100644
--- a/client/ayon_core/addon/base.py
+++ b/client/ayon_core/addon/base.py
@@ -51,7 +51,9 @@ IGNORED_MODULES_IN_AYON = set()
# - this is used to log the missing addon
MOVED_ADDON_MILESTONE_VERSIONS = {
"applications": VersionInfo(0, 2, 0),
+ "celaction": VersionInfo(0, 2, 0),
"clockify": VersionInfo(0, 2, 0),
+ "flame": VersionInfo(0, 2, 0),
"traypublisher": VersionInfo(0, 2, 0),
"tvpaint": VersionInfo(0, 2, 0),
"nuke": VersionInfo(0, 2, 0),
diff --git a/client/ayon_core/hosts/flame/__init__.py b/client/ayon_core/hosts/flame/__init__.py
deleted file mode 100644
index b45f107747..0000000000
--- a/client/ayon_core/hosts/flame/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from .addon import (
- HOST_DIR,
- FlameAddon,
-)
-
-
-__all__ = (
- "HOST_DIR",
- "FlameAddon",
-)
diff --git a/client/ayon_core/hosts/max/plugins/__init__.py b/client/ayon_core/hosts/max/plugins/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/client/ayon_core/hosts/resolve/RESOLVE_API_v18.5.1-build6.txt b/client/ayon_core/hosts/resolve/RESOLVE_API_v19.0B-build20.txt
similarity index 86%
rename from client/ayon_core/hosts/resolve/RESOLVE_API_v18.5.1-build6.txt
rename to client/ayon_core/hosts/resolve/RESOLVE_API_v19.0B-build20.txt
index 7d1d6edf61..a2f3fa6f73 100644
--- a/client/ayon_core/hosts/resolve/RESOLVE_API_v18.5.1-build6.txt
+++ b/client/ayon_core/hosts/resolve/RESOLVE_API_v19.0B-build20.txt
@@ -1,26 +1,23 @@
-Updated as of 26 May 2023
+Last Updated: 1 April 2024
----------------------------
In this package, you will find a brief introduction to the Scripting API for DaVinci Resolve Studio. Apart from this README.txt file, this package contains folders containing the basic import
modules for scripting access (DaVinciResolve.py) and some representative examples.
From v16.2.0 onwards, the nodeIndex parameters accepted by SetLUT() and SetCDL() are 1-based instead of 0-based, i.e. 1 <= nodeIndex <= total number of nodes.
-
Overview
--------
-As with Blackmagic Design Fusion scripts, user scripts written in Lua and Python programming languages are supported. By default, scripts can be invoked from the Console window in the Fusion page,
+As with Blackmagic Fusion scripts, user scripts written in Lua and Python programming languages are supported. By default, scripts can be invoked from the Console window in the Fusion page,
or via command line. This permission can be changed in Resolve Preferences, to be only from Console, or to be invoked from the local network. Please be aware of the security implications when
allowing scripting access from outside of the Resolve application.
-
Prerequisites
-------------
DaVinci Resolve scripting requires one of the following to be installed (for all users):
Lua 5.1
- Python 2.7 64-bit
Python >= 3.6 64-bit
-
+ Python 2.7 64-bit
Using a script
--------------
@@ -64,6 +61,7 @@ The interactive Console window allows for an easy way to execute simple scriptin
and Lua and evaluates and executes them immediately. For more information on how to use the Console, please refer to the DaVinci Resolve User Manual.
This example Python script creates a simple project:
+
#!/usr/bin/env python
import DaVinciResolveScript as dvr_script
resolve = dvr_script.scriptapp("Resolve")
@@ -80,9 +78,8 @@ Running DaVinci Resolve in headless mode
DaVinci Resolve can be launched in a headless mode without the user interface using the -nogui command line option. When DaVinci Resolve is launched using this option, the user interface is disabled.
However, the various scripting APIs will continue to work as expected.
-
-Basic Resolve API
------------------
+DaVinci Resolve API
+-------------------
Some commonly used API functions are described below (*). As with the resolve object, each object is inspectable for properties and functions.
Resolve
@@ -101,6 +98,12 @@ Resolve
SaveLayoutPreset(presetName) --> Bool # Saves current UI layout as a preset named 'presetName'.
ImportLayoutPreset(presetFilePath, presetName) --> Bool # Imports preset from path 'presetFilePath'. The optional argument 'presetName' specifies how the preset shall be named. If not specified, the preset is named based on the filename.
Quit() --> None # Quits the Resolve App.
+ ImportRenderPreset(presetPath) --> Bool # Import a preset from presetPath (string) and set it as current preset for rendering.
+ ExportRenderPreset(presetName, exportPath) --> Bool # Export a preset to a given path (string) if presetName(string) exists.
+ ImportBurnInPreset(presetPath) --> Bool # Import a data burn in preset from a given presetPath (string)
+ ExportBurnInPreset(presetName, exportPath) --> Bool # Export a data burn in preset to a given path (string) if presetName (string) exists.
+ GetKeyframeMode() --> keyframeMode # Returns the currently set keyframe mode (int). Refer to section 'Keyframe Mode information' below for details.
+ SetKeyframeMode(keyframeMode) --> Bool # Returns True when 'keyframeMode'(enum) is successfully set. Refer to section 'Keyframe Mode information' below for details.
ProjectManager
ArchiveProject(projectName,
@@ -131,6 +134,14 @@ ProjectManager
# 'DbType': 'Disk' or 'PostgreSQL' (string)
# 'DbName': database name (string)
# 'IpAddress': IP address of the PostgreSQL server (string, optional key - defaults to '127.0.0.1')
+ CreateCloudProject({cloudSettings}) --> Project # Creates and returns a cloud project.
+ # '{cloudSettings}': Check 'Cloud Projects Settings' subsection below for more information.
+ ImportCloudProject(filePath, {cloudSettings}) --> Bool # Returns True if import cloud project is successful; False otherwise
+ # 'filePath': String; filePath of file to import
+ # '{cloudSettings}': Check 'Cloud Projects Settings' subsection below for more information.
+ RestoreCloudProject(folderPath, {cloudSettings}) --> Bool # Returns True if restore cloud project is successful; False otherwise
+ # 'folderPath': String; path of folder to restore
+ # '{cloudSettings}': Check 'Cloud Projects Settings' subsection below for more information.
Project
GetMediaPool() --> MediaPool # Returns the Media Pool object.
@@ -175,6 +186,9 @@ Project
startOffsetInSamples, durationInSamples)
LoadBurnInPreset(presetName) --> Bool # Loads user defined data burn in preset for project when supplied presetName (string). Returns true if successful.
ExportCurrentFrameAsStill(filePath) --> Bool # Exports current frame as still to supplied filePath. filePath must end in valid export file format. Returns True if succssful, False otherwise.
+ GetColorGroupsList() --> [ColorGroups...] # Returns a list of all group objects in the timeline.
+ AddColorGroup(groupName) --> ColorGroup # Creates a new ColorGroup. groupName must be a unique string.
+ DeleteColorGroup(colorGroup) --> Bool # Deletes the given color group and sets clips to ungrouped.
MediaStorage
GetMountedVolumeList() --> [paths...] # Returns list of folder paths corresponding to mounted volumes displayed in Resolve’s Media Storage.
@@ -198,7 +212,7 @@ MediaPool
CreateTimelineFromClips(name, clip1, clip2,...) --> Timeline # Creates new timeline with specified name, and appends the specified MediaPoolItem objects.
CreateTimelineFromClips(name, [clips]) --> Timeline # Creates new timeline with specified name, and appends the specified MediaPoolItem objects.
CreateTimelineFromClips(name, [{clipInfo}]) --> Timeline # Creates new timeline with specified name, appending the list of clipInfos specified as a dict of "mediaPoolItem", "startFrame" (int), "endFrame" (int), "recordFrame" (int).
- ImportTimelineFromFile(filePath, {importOptions}) --> Timeline # Creates timeline based on parameters within given file (AAF/EDL/XML/FCPXML/DRT/ADL) and optional importOptions dict, with support for the keys:
+ ImportTimelineFromFile(filePath, {importOptions}) --> Timeline # Creates timeline based on parameters within given file (AAF/EDL/XML/FCPXML/DRT/ADL/OTIO) and optional importOptions dict, with support for the keys:
# "timelineName": string, specifies the name of the timeline to be created. Not valid for DRT import
# "importSourceClips": Bool, specifies whether source clips should be imported, True by default. Not valid for DRT import
# "sourceClipsPath": string, specifies a filesystem path to search for source clips if the media is inaccessible in their original path and if "importSourceClips" is True
@@ -225,6 +239,8 @@ MediaPool
ExportMetadata(fileName, [clips]) --> Bool # Exports metadata of specified clips to 'fileName' in CSV format.
# If no clips are specified, all clips from media pool will be used.
GetUniqueId() --> string # Returns a unique ID for the media pool
+ CreateStereoClip(LeftMediaPoolItem,
+ RightMediaPoolItem) --> MediaPoolItem # Takes in two existing media pool items and creates a new 3D stereoscopic media pool entry replacing the input media in the media pool.
Folder
GetClipList() --> [clips...] # Returns a list of clips (items) within the folder.
@@ -233,6 +249,8 @@ Folder
GetIsFolderStale() --> bool # Returns true if folder is stale in collaboration mode, false otherwise
GetUniqueId() --> string # Returns a unique ID for the media pool folder
Export(filePath) --> bool # Returns true if export of DRB folder to filePath is successful, false otherwise
+ TranscribeAudio() --> Bool # Transcribes audio of the MediaPoolItems within the folder and nested folders. Returns True if successful; False otherwise
+ ClearTranscription() --> Bool # Clears audio transcription of the MediaPoolItems within the folder and nested folders. Returns True if successful; False otherwise.
MediaPoolItem
GetName() --> string # Returns the clip name.
@@ -340,8 +358,12 @@ Timeline
GrabStill() --> galleryStill # Grabs still from the current video clip. Returns a GalleryStill object.
GrabAllStills(stillFrameSource) --> [galleryStill] # Grabs stills from all the clips of the timeline at 'stillFrameSource' (1 - First frame, 2 - Middle frame). Returns the list of GalleryStill objects.
GetUniqueId() --> string # Returns a unique ID for the timeline
- CreateSubtitlesFromAudio() --> Bool # Creates subtitles from audio for the timeline. Returns True on success, False otherwise.
+ CreateSubtitlesFromAudio({autoCaptionSettings}) --> Bool # Creates subtitles from audio for the timeline.
+ # Takes in optional dictionary {autoCaptionSettings}. Check 'Auto Caption Settings' subsection below for more information.
+ # Returns True on success, False otherwise.
DetectSceneCuts() --> Bool # Detects and makes scene cuts along the timeline. Returns True if successful, False otherwise.
+ ConvertTimelineToStereo() --> Bool # Converts timeline to stereo. Returns True if successful; False otherwise.
+ GetNodeGraph() --> Graph # Returns the timeline's node graph object.
TimelineItem
GetName() --> string # Returns the item name.
@@ -390,12 +412,7 @@ TimelineItem
GetStereoConvergenceValues() --> {keyframes...} # Returns a dict (offset -> value) of keyframe offsets and respective convergence values.
GetStereoLeftFloatingWindowParams() --> {keyframes...} # For the LEFT eye -> returns a dict (offset -> dict) of keyframe offsets and respective floating window params. Value at particular offset includes the left, right, top and bottom floating window values.
GetStereoRightFloatingWindowParams() --> {keyframes...} # For the RIGHT eye -> returns a dict (offset -> dict) of keyframe offsets and respective floating window params. Value at particular offset includes the left, right, top and bottom floating window values.
- GetNumNodes() --> int # Returns the number of nodes in the current graph for the timeline item
ApplyArriCdlLut() --> Bool # Applies ARRI CDL and LUT. Returns True if successful, False otherwise.
- SetLUT(nodeIndex, lutPath) --> Bool # Sets LUT on the node mapping the node index provided, 1 <= nodeIndex <= total number of nodes.
- # The lutPath can be an absolute path, or a relative path (based off custom LUT paths or the master LUT path).
- # The operation is successful for valid lut paths that Resolve has already discovered (see Project.RefreshLUTList).
- GetLUT(nodeIndex) --> String # Gets relative LUT path based on the node index provided, 1 <= nodeIndex <= total number of nodes.
SetCDL([CDL map]) --> Bool # Keys of map are: "NodeIndex", "Slope", "Offset", "Power", "Saturation", where 1 <= NodeIndex <= total number of nodes.
# Example python code - SetCDL({"NodeIndex" : "1", "Slope" : "0.5 0.4 0.2", "Offset" : "0.4 0.3 0.2", "Power" : "0.6 0.7 0.8", "Saturation" : "0.65"})
AddTake(mediaPoolItem, startFrame, endFrame) --> Bool # Adds mediaPoolItem as a new take. Initializes a take selector for the timeline item if needed. By default, the full clip extents is added. startFrame (int) and endFrame (int) are optional arguments used to specify the extents.
@@ -411,11 +428,17 @@ TimelineItem
UpdateSidecar() --> Bool # Updates sidecar file for BRAW clips or RMD file for R3D clips.
GetUniqueId() --> string # Returns a unique ID for the timeline item
LoadBurnInPreset(presetName) --> Bool # Loads user defined data burn in preset for clip when supplied presetName (string). Returns true if successful.
- GetNodeLabel(nodeIndex) --> string # Returns the label of the node at nodeIndex.
CreateMagicMask(mode) --> Bool # Returns True if magic mask was created successfully, False otherwise. mode can "F" (forward), "B" (backward), or "BI" (bidirection)
RegenerateMagicMask() --> Bool # Returns True if magic mask was regenerated successfully, False otherwise.
Stabilize() --> Bool # Returns True if stabilization was successful, False otherwise
SmartReframe() --> Bool # Performs Smart Reframe. Returns True if successful, False otherwise.
+ GetNodeGraph() --> Graph # Returns the clip's node graph object.
+ GetColorGroup() --> ColorGroup # Returns the clip's color group if one exists.
+ AssignToColorGroup(ColorGroup) --> Bool # Returns True if TiItem to successfully assigned to given ColorGroup. ColorGroup must be an existing group in the current project.
+ RemoveFromColorGroup() --> Bool # Returns True if the TiItem is successfully removed from the ColorGroup it is in.
+ ExportLUT(exportType, path) --> Bool # Exports LUTs from tiItem referring to value passed in 'exportType' (enum) for LUT size. Refer to. 'ExportLUT notes' section for possible values.
+ # Saves generated LUT in the provided 'path' (string). 'path' should include the intended file name.
+ # If an empty or incorrect extension is provided, the appropriate extension (.cube/.vlt) will be appended at the end of the path.
Gallery
GetAlbumName(galleryStillAlbum) --> string # Returns the name of the GalleryStillAlbum object 'galleryStillAlbum'.
@@ -428,17 +451,63 @@ GalleryStillAlbum
GetStills() --> [galleryStill] # Returns the list of GalleryStill objects in the album.
GetLabel(galleryStill) --> string # Returns the label of the galleryStill.
SetLabel(galleryStill, label) --> Bool # Sets the new 'label' to GalleryStill object 'galleryStill'.
- ExportStills([galleryStill], folderPath, filePrefix, format) --> Bool # Exports list of GalleryStill objects '[galleryStill]' to directory 'folderPath', with filename prefix 'filePrefix', using file format 'format' (supported formats: dpx, cin, tif, jpg, png, ppm, bmp, xpm).
+ ImportStills([filePaths]) --> Bool # Imports GalleryStill from each filePath in [filePaths] list. True if at least one still is imported successfully. False otherwise.
+ ExportStills([galleryStill], folderPath, filePrefix, format) --> Bool # Exports list of GalleryStill objects '[galleryStill]' to directory 'folderPath', with filename prefix 'filePrefix', using file format 'format' (supported formats: dpx, cin, tif, jpg, png, ppm, bmp, xpm, drx).
DeleteStills([galleryStill]) --> Bool # Deletes specified list of GalleryStill objects '[galleryStill]'.
GalleryStill # This class does not provide any API functions but the object type is used by functions in other classes.
+Graph
+ GetNumNodes() --> int # Returns the number of nodes in the graph
+ SetLUT(nodeIndex, lutPath) --> Bool # Sets LUT on the node mapping the node index provided, 1 <= nodeIndex <= self.GetNumNodes().
+ # The lutPath can be an absolute path, or a relative path (based off custom LUT paths or the master LUT path).
+ # The operation is successful for valid lut paths that Resolve has already discovered (see Project.RefreshLUTList).
+ GetLUT(nodeIndex) --> String # Gets relative LUT path based on the node index provided, 1 <= nodeIndex <= total number of nodes.
+ GetNodeLabel(nodeIndex) --> string # Returns the label of the node at nodeIndex.
+ GetToolsInNode(nodeIndex) --> [toolsList] # Returns toolsList (list of strings) of the tools used in the node indicated by given nodeIndex (int).
+
+ColorGroup
+ GetName() --> String # Returns the name (string) of the ColorGroup.
+ SetName(groupName) --> Bool # Renames ColorGroup to groupName (string).
+ GetClipsInTimeline(Timeline=CurrTimeline) --> [TimelineItem] # Returns a list of TimelineItem that are in colorGroup in the given Timeline. Timeline is Current Timeline by default.
+ GetPreClipNodeGraph() --> Graph # Returns the ColorGroup Pre-clip graph.
+ GetPostClipNodeGraph() --> Graph # Returns the ColorGroup Post-clip graph.
+
List and Dict Data Structures
-----------------------------
Beside primitive data types, Resolve's Python API mainly uses list and dict data structures. Lists are denoted by [ ... ] and dicts are denoted by { ... } above.
As Lua does not support list and dict data structures, the Lua API implements "list" as a table with indices, e.g. { [1] = listValue1, [2] = listValue2, ... }.
Similarly the Lua API implements "dict" as a table with the dictionary key as first element, e.g. { [dictKey1] = dictValue1, [dictKey2] = dictValue2, ... }.
+Keyframe Mode information
+-------------------------
+This section covers additional notes for the functions Resolve.GetKeyframeMode() and Resolve.SetKeyframeMode(keyframeMode).
+
+'keyframeMode' can be one of the following enums:
+ - resolve.KEYFRAME_MODE_ALL == 0
+ - resolve.KEYFRAME_MODE_COLOR == 1
+ - resolve.KEYFRAME_MODE_SIZING == 2
+
+Integer values returned by Resolve.GetKeyframeMode() will correspond to the enums above.
+
+Cloud Projects Settings
+--------------------------------------
+This section covers additional notes for the functions "ProjectManager:CreateCloudProject," "ProjectManager:ImportCloudProject," and "ProjectManager:RestoreCloudProject"
+
+All three functions take in a {cloudSettings} dict, that have the following keys:
+* resolve.CLOUD_SETTING_PROJECT_NAME: String, ["" by default]
+* resolve.CLOUD_SETTING_PROJECT_MEDIA_PATH: String, ["" by default]
+* resolve.CLOUD_SETTING_IS_COLLAB: Bool, [False by default]
+* resolve.CLOUD_SETTING_SYNC_MODE: syncMode (see below), [resolve.CLOUD_SYNC_PROXY_ONLY by default]
+* resolve.CLOUD_SETTING_IS_CAMERA_ACCESS: Bool [False by default]
+
+Where syncMode is one of the following values:
+* resolve.CLOUD_SYNC_NONE,
+* resolve.CLOUD_SYNC_PROXY_ONLY,
+* resolve.CLOUD_SYNC_PROXY_AND_ORIG
+
+All three "ProjectManager:CreateCloudProject," "ProjectManager:ImportCloudProject," and "ProjectManager:RestoreCloudProject" require resolve.PROJECT_MEDIA_PATH to be defined. "ProjectManager:CreateCloudProject" also requires resolve.PROJECT_NAME to be defined.
+
Looking up Project and Clip properties
--------------------------------------
This section covers additional notes for the functions "Project:GetSetting", "Project:SetSetting", "Timeline:GetSetting", "Timeline:SetSetting", "MediaPoolItem:GetClipProperty" and
@@ -478,6 +547,49 @@ Affects:
• x = MediaPoolItem:GetClipProperty('Super Scale') and MediaPoolItem:SetClipProperty('Super Scale', x)
• for '2x Enhanced' --> MediaPoolItem:SetClipProperty('Super Scale', 2, sharpnessValue, noiseReductionValue), where sharpnessValue is a float in the range [0.0, 1.0] and noiseReductionValue is a float in the range [0.0, 1.0]
+Auto Caption Settings
+----------------------
+This section covers the supported settings for the method Timeline.CreateSubtitlesFromAudio({autoCaptionSettings})
+
+The parameter setting is a dictionary containing the following keys:
+* resolve.SUBTITLE_LANGUAGE: languageID (see below), [resolve.AUTO_CAPTION_AUTO by default]
+* resolve.SUBTITLE_CAPTION_PRESET: presetType (see below), [resolve.AUTO_CAPTION_SUBTITLE_DEFAULT by default]
+* resolve.SUBTITLE_CHARS_PER_LINE: Number between 1 and 60 inclusive [42 by default]
+* resolve.SUBTITLE_LINE_BREAK: lineBreakType (see below), [resolve.AUTO_CAPTION_LINE_SINGLE by default]
+* resolve.SUBTITLE_GAP: Number between 0 and 10 inclusive [0 by default]
+
+Note that the default values for some keys may change based on values defined for other keys, as per the UI.
+For example, if the following dictionary is supplied,
+ CreateSubtitlesFromAudio( { resolve.SUBTITLE_LANGUAGE = resolve.AUTO_CAPTION_KOREAN,
+ resolve.SUBTITLE_CAPTION_PRESET = resolve.AUTO_CAPTION_NETFLIX } )
+the default value for resolve.SUBTITLE_CHARS_PER_LINE will be 16 instead of 42
+
+languageIDs:
+* resolve.AUTO_CAPTION_AUTO
+* resolve.AUTO_CAPTION_DANISH
+* resolve.AUTO_CAPTION_DUTCH
+* resolve.AUTO_CAPTION_ENGLISH
+* resolve.AUTO_CAPTION_FRENCH
+* resolve.AUTO_CAPTION_GERMAN
+* resolve.AUTO_CAPTION_ITALIAN
+* resolve.AUTO_CAPTION_JAPANESE
+* resolve.AUTO_CAPTION_KOREAN
+* resolve.AUTO_CAPTION_MANDARIN_SIMPLIFIED
+* resolve.AUTO_CAPTION_MANDARIN_TRADITIONAL
+* resolve.AUTO_CAPTION_NORWEGIAN
+* resolve.AUTO_CAPTION_PORTUGUESE
+* resolve.AUTO_CAPTION_RUSSIAN
+* resolve.AUTO_CAPTION_SPANISH
+* resolve.AUTO_CAPTION_SWEDISH
+
+presetTypes:
+* resolve.AUTO_CAPTION_SUBTITLE_DEFAULT
+* resolve.AUTO_CAPTION_TELETEXT
+* resolve.AUTO_CAPTION_NETFLIX
+
+lineBreakTypes:
+* resolve.AUTO_CAPTION_LINE_SINGLE
+* resolve.AUTO_CAPTION_LINE_DOUBLE
Looking up Render Settings
--------------------------
@@ -531,6 +643,8 @@ exportType can be one of the following constants:
- resolve.EXPORT_DOLBY_VISION_VER_4_0
- resolve.EXPORT_DOLBY_VISION_VER_5_1
- resolve.EXPORT_OTIO
+ - resolve.EXPORT_ALE
+ - resolve.EXPORT_ALE_CDL
exportSubtype can be one of the following enums:
- resolve.EXPORT_NONE
- resolve.EXPORT_AAF_NEW
@@ -627,7 +741,8 @@ The supported keys with their accepted values are:
- MOTION_EST_STANDARD_BETTER
- MOTION_EST_ENHANCED_FASTER
- MOTION_EST_ENHANCED_BETTER
- - MOTION_EST_SPEED_WRAP
+ - MOTION_EST_SPEED_WARP_BETTER
+ - MOTION_EST_SPEED_WARP_FASTER
"Scaling" : A value from the following constants
- SCALE_USE_PROJECT = 0
- SCALE_CROP
@@ -659,6 +774,16 @@ as a single argument.
Getting the values for the keys that uses constants will return the number which is in the constant
+ExportLUT notes
+---------------
+The following section covers additional notes for TimelineItem.ExportLUT(exportType, path).
+
+Supported values for 'exportType' (enum) are:
+ - resolve.EXPORT_LUT_17PTCUBE
+ - resolve.EXPORT_LUT_33PTCUBE
+ - resolve.EXPORT_LUT_65PTCUBE
+ - resolve.EXPORT_LUT_PANASONICVLUT
+
Deprecated Resolve API Functions
--------------------------------
The following API functions are deprecated.
@@ -693,7 +818,12 @@ TimelineItem
GetFusionCompNames() --> {names...} # Returns a dict of Fusion composition names associated with the timeline item.
GetFlags() --> {colors...} # Returns a dict of flag colors assigned to the item.
GetVersionNames(versionType) --> {names...} # Returns a dict of version names by provided versionType: 0 - local, 1 - remote.
-
+ GetNumNodes() --> int # Returns the number of nodes in the current graph for the timeline item
+ SetLUT(nodeIndex, lutPath) --> Bool # Sets LUT on the node mapping the node index provided, 1 <= nodeIndex <= total number of nodes.
+ # The lutPath can be an absolute path, or a relative path (based off custom LUT paths or the master LUT path).
+ # The operation is successful for valid lut paths that Resolve has already discovered (see Project.RefreshLUTList).
+ GetLUT(nodeIndex) --> String # Gets relative LUT path based on the node index provided, 1 <= nodeIndex <= total number of nodes.
+ GetNodeLabel(nodeIndex) --> string # Returns the label of the node at nodeIndex.
Unsupported Resolve API Functions
---------------------------------
diff --git a/client/ayon_core/hosts/resolve/plugins/load/load_editorial_package.py b/client/ayon_core/hosts/resolve/plugins/load/load_editorial_package.py
new file mode 100644
index 0000000000..33395534fa
--- /dev/null
+++ b/client/ayon_core/hosts/resolve/plugins/load/load_editorial_package.py
@@ -0,0 +1,52 @@
+from pathlib import Path
+
+from ayon_core.pipeline import (
+ load,
+ get_representation_path,
+)
+
+from ayon_core.hosts.resolve.api import lib
+
+
+class LoadEditorialPackage(load.LoaderPlugin):
+ """Load editorial package to timeline.
+
+ Loading timeline from OTIO file included media sources
+ and timeline structure.
+ """
+
+ product_types = {"editorial_pkg"}
+
+ representations = {"*"}
+ extensions = {"otio"}
+
+ label = "Load as Timeline"
+ order = -10
+ icon = "ei.align-left"
+ color = "orange"
+
+ def load(self, context, name, namespace, data):
+ files = get_representation_path(context["representation"])
+
+ search_folder_path = Path(files).parent / "resources"
+
+ project = lib.get_current_project()
+ media_pool = project.GetMediaPool()
+
+ # create versioned bin for editorial package
+ version_name = context["version"]["name"]
+ bin_name = f"{name}_{version_name}"
+ lib.create_bin(bin_name)
+
+ import_options = {
+ "timelineName": "Editorial Package Timeline",
+ "importSourceClips": True,
+ "sourceClipsPath": search_folder_path.as_posix(),
+ }
+
+ timeline = media_pool.ImportTimelineFromFile(files, import_options)
+ print("Timeline imported: ", timeline)
+
+ def update(self, container, context):
+ # TODO: implement update method in future
+ pass
diff --git a/client/ayon_core/modules/deadline/plugins/publish/submit_max_deadline.py b/client/ayon_core/modules/deadline/plugins/publish/submit_max_deadline.py
index ababb01285..4cb510f1cb 100644
--- a/client/ayon_core/modules/deadline/plugins/publish/submit_max_deadline.py
+++ b/client/ayon_core/modules/deadline/plugins/publish/submit_max_deadline.py
@@ -15,11 +15,11 @@ from ayon_core.pipeline.publish.lib import (
replace_with_published_scene_path
)
from ayon_core.pipeline.publish import KnownPublishError
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api.lib import (
get_current_renderer,
get_multipass_setting
)
-from ayon_core.hosts.max.api.lib_rendersettings import RenderSettings
+from ayon_max.api.lib_rendersettings import RenderSettings
from openpype_modules.deadline import abstract_submit_deadline
from openpype_modules.deadline.abstract_submit_deadline import DeadlineJobInfo
@@ -205,11 +205,11 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
def _use_published_name(self, data, project_settings):
# Not all hosts can import these modules.
- from ayon_core.hosts.max.api.lib import (
+ from ayon_max.api.lib import (
get_current_renderer,
get_multipass_setting
)
- from ayon_core.hosts.max.api.lib_rendersettings import RenderSettings
+ from ayon_max.api.lib_rendersettings import RenderSettings
instance = self._instance
job_info = copy.deepcopy(self.job_info)
diff --git a/client/ayon_core/plugins/publish/validate_version.py b/client/ayon_core/plugins/publish/validate_version.py
index 25a5757330..c2f7d5bf44 100644
--- a/client/ayon_core/plugins/publish/validate_version.py
+++ b/client/ayon_core/plugins/publish/validate_version.py
@@ -1,6 +1,10 @@
import pyblish.api
+
+from ayon_core.lib import filter_profiles
from ayon_core.pipeline.publish import (
- PublishValidationError, OptionalPyblishPluginMixin
+ PublishValidationError,
+ OptionalPyblishPluginMixin,
+ get_current_host_name,
)
@@ -13,12 +17,35 @@ class ValidateVersion(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin):
order = pyblish.api.ValidatorOrder
label = "Validate Version"
- hosts = ["nuke", "maya", "houdini", "blender",
- "photoshop", "aftereffects"]
optional = False
active = True
+ @classmethod
+ def apply_settings(cls, settings):
+ # Disable if no profile is found for the current host
+ profiles = (
+ settings
+ ["core"]
+ ["publish"]
+ ["ValidateVersion"]
+ ["plugin_state_profiles"]
+ )
+ profile = filter_profiles(
+ profiles, {"host_names": get_current_host_name()}
+ )
+ if not profile:
+ cls.enabled = False
+ return
+
+ # Apply settings from profile
+ for attr_name in {
+ "enabled",
+ "optional",
+ "active",
+ }:
+ setattr(cls, attr_name, profile[attr_name])
+
def process(self, instance):
if not self.is_active(instance.data):
return
diff --git a/client/ayon_core/tools/common_models/__init__.py b/client/ayon_core/tools/common_models/__init__.py
index 8895515b1a..f09edfeab2 100644
--- a/client/ayon_core/tools/common_models/__init__.py
+++ b/client/ayon_core/tools/common_models/__init__.py
@@ -14,6 +14,7 @@ from .hierarchy import (
)
from .thumbnails import ThumbnailsModel
from .selection import HierarchyExpectedSelection
+from .users import UsersModel
__all__ = (
@@ -32,4 +33,6 @@ __all__ = (
"ThumbnailsModel",
"HierarchyExpectedSelection",
+
+ "UsersModel",
)
diff --git a/client/ayon_core/tools/common_models/users.py b/client/ayon_core/tools/common_models/users.py
new file mode 100644
index 0000000000..f8beb31aa1
--- /dev/null
+++ b/client/ayon_core/tools/common_models/users.py
@@ -0,0 +1,84 @@
+import ayon_api
+
+from ayon_core.lib import CacheItem
+
+
+class UserItem:
+ def __init__(
+ self,
+ username,
+ full_name,
+ email,
+ avatar_url,
+ active,
+ ):
+ self.username = username
+ self.full_name = full_name
+ self.email = email
+ self.avatar_url = avatar_url
+ self.active = active
+
+ @classmethod
+ def from_entity_data(cls, user_data):
+ return cls(
+ user_data["name"],
+ user_data["attrib"]["fullName"],
+ user_data["attrib"]["email"],
+ user_data["attrib"]["avatarUrl"],
+ user_data["active"],
+ )
+
+
+class UsersModel:
+ def __init__(self, controller):
+ self._controller = controller
+ self._users_cache = CacheItem(default_factory=list)
+
+ def get_user_items(self):
+ """Get user items.
+
+ Returns:
+ List[UserItem]: List of user items.
+
+ """
+ self._invalidate_cache()
+ return self._users_cache.get_data()
+
+ def get_user_items_by_name(self):
+ """Get user items by name.
+
+ Implemented as most of cases using this model will need to find
+ user information by username.
+
+ Returns:
+ Dict[str, UserItem]: Dictionary of user items by name.
+
+ """
+ return {
+ user_item.username: user_item
+ for user_item in self.get_user_items()
+ }
+
+ def get_user_item_by_username(self, username):
+ """Get user item by username.
+
+ Args:
+ username (str): Username.
+
+ Returns:
+ Union[UserItem, None]: User item or None if not found.
+
+ """
+ self._invalidate_cache()
+ for user_item in self.get_user_items():
+ if user_item.username == username:
+ return user_item
+ return None
+
+ def _invalidate_cache(self):
+ if self._users_cache.is_valid:
+ return
+ self._users_cache.update_data([
+ UserItem.from_entity_data(user)
+ for user in ayon_api.get_users()
+ ])
diff --git a/client/ayon_core/tools/workfiles/abstract.py b/client/ayon_core/tools/workfiles/abstract.py
index c9eb9004e3..f345e20dca 100644
--- a/client/ayon_core/tools/workfiles/abstract.py
+++ b/client/ayon_core/tools/workfiles/abstract.py
@@ -13,8 +13,10 @@ class WorkfileInfo:
task_id (str): Task id.
filepath (str): Filepath.
filesize (int): File size.
- creation_time (int): Creation time (timestamp).
- modification_time (int): Modification time (timestamp).
+ creation_time (float): Creation time (timestamp).
+ modification_time (float): Modification time (timestamp).
+ created_by (Union[str, none]): User who created the file.
+ updated_by (Union[str, none]): User who last updated the file.
note (str): Note.
"""
@@ -26,6 +28,8 @@ class WorkfileInfo:
filesize,
creation_time,
modification_time,
+ created_by,
+ updated_by,
note,
):
self.folder_id = folder_id
@@ -34,6 +38,8 @@ class WorkfileInfo:
self.filesize = filesize
self.creation_time = creation_time
self.modification_time = modification_time
+ self.created_by = created_by
+ self.updated_by = updated_by
self.note = note
def to_data(self):
@@ -50,6 +56,8 @@ class WorkfileInfo:
"filesize": self.filesize,
"creation_time": self.creation_time,
"modification_time": self.modification_time,
+ "created_by": self.created_by,
+ "updated_by": self.updated_by,
"note": self.note,
}
@@ -212,6 +220,7 @@ class FileItem:
dirpath (str): Directory path of file.
filename (str): Filename.
modified (float): Modified timestamp.
+ created_by (Optional[str]): Username.
representation_id (Optional[str]): Representation id of published
workfile.
filepath (Optional[str]): Prepared filepath.
@@ -223,6 +232,8 @@ class FileItem:
dirpath,
filename,
modified,
+ created_by=None,
+ updated_by=None,
representation_id=None,
filepath=None,
exists=None
@@ -230,6 +241,8 @@ class FileItem:
self.filename = filename
self.dirpath = dirpath
self.modified = modified
+ self.created_by = created_by
+ self.updated_by = updated_by
self.representation_id = representation_id
self._filepath = filepath
self._exists = exists
@@ -269,6 +282,7 @@ class FileItem:
"filename": self.filename,
"dirpath": self.dirpath,
"modified": self.modified,
+ "created_by": self.created_by,
"representation_id": self.representation_id,
"filepath": self.filepath,
"exists": self.exists,
@@ -522,6 +536,16 @@ class AbstractWorkfilesFrontend(AbstractWorkfilesCommon):
pass
+ @abstractmethod
+ def get_user_items_by_name(self):
+ """Get user items available on AYON server.
+
+ Returns:
+ Dict[str, UserItem]: User items by username.
+
+ """
+ pass
+
# Host information
@abstractmethod
def get_workfile_extensions(self):
diff --git a/client/ayon_core/tools/workfiles/control.py b/client/ayon_core/tools/workfiles/control.py
index 3048e6be94..8fa9135bc0 100644
--- a/client/ayon_core/tools/workfiles/control.py
+++ b/client/ayon_core/tools/workfiles/control.py
@@ -19,6 +19,7 @@ from ayon_core.tools.common_models import (
HierarchyModel,
HierarchyExpectedSelection,
ProjectsModel,
+ UsersModel,
)
from .abstract import (
@@ -161,6 +162,7 @@ class BaseWorkfileController(
self._save_is_enabled = True
# Expected selected folder and task
+ self._users_model = self._create_users_model()
self._expected_selection = self._create_expected_selection_obj()
self._selection_model = self._create_selection_model()
self._projects_model = self._create_projects_model()
@@ -176,6 +178,12 @@ class BaseWorkfileController(
def is_host_valid(self):
return self._host_is_valid
+ def _create_users_model(self):
+ return UsersModel(self)
+
+ def _create_workfiles_model(self):
+ return WorkfilesModel(self)
+
def _create_expected_selection_obj(self):
return WorkfilesToolExpectedSelection(self)
@@ -188,9 +196,6 @@ class BaseWorkfileController(
def _create_hierarchy_model(self):
return HierarchyModel(self)
- def _create_workfiles_model(self):
- return WorkfilesModel(self)
-
@property
def event_system(self):
"""Inner event system for workfiles tool controller.
@@ -272,6 +277,9 @@ class BaseWorkfileController(
{"enabled": enabled}
)
+ def get_user_items_by_name(self):
+ return self._users_model.get_user_items_by_name()
+
# Host information
def get_workfile_extensions(self):
host = self._host
diff --git a/client/ayon_core/tools/workfiles/models/workfiles.py b/client/ayon_core/tools/workfiles/models/workfiles.py
index 5f59b99b22..c93bbb6637 100644
--- a/client/ayon_core/tools/workfiles/models/workfiles.py
+++ b/client/ayon_core/tools/workfiles/models/workfiles.py
@@ -6,6 +6,7 @@ import arrow
import ayon_api
from ayon_api.operations import OperationsSession
+from ayon_core.lib import get_ayon_username
from ayon_core.pipeline.template_data import (
get_template_data,
get_task_template_data,
@@ -23,6 +24,8 @@ from ayon_core.tools.workfiles.abstract import (
WorkfileInfo,
)
+_NOT_SET = object()
+
class CommentMatcher(object):
"""Use anatomy and work file data to parse comments from filenames.
@@ -188,10 +191,17 @@ class WorkareaModel:
if ext not in self._extensions:
continue
- modified = os.path.getmtime(filepath)
- items.append(
- FileItem(workdir, filename, modified)
+ workfile_info = self._controller.get_workfile_info(
+ folder_id, task_id, filepath
)
+ modified = os.path.getmtime(filepath)
+ items.append(FileItem(
+ workdir,
+ filename,
+ modified,
+ workfile_info.created_by,
+ workfile_info.updated_by,
+ ))
return items
def _get_template_key(self, fill_data):
@@ -439,6 +449,7 @@ class WorkfileEntitiesModel:
self._controller = controller
self._cache = {}
self._items = {}
+ self._current_username = _NOT_SET
def _get_workfile_info_identifier(
self, folder_id, task_id, rootless_path
@@ -459,8 +470,12 @@ class WorkfileEntitiesModel:
self, folder_id, task_id, workfile_info, filepath
):
note = ""
+ created_by = None
+ updated_by = None
if workfile_info:
note = workfile_info["attrib"].get("description") or ""
+ created_by = workfile_info.get("createdBy")
+ updated_by = workfile_info.get("updatedBy")
filestat = os.stat(filepath)
return WorkfileInfo(
@@ -470,6 +485,8 @@ class WorkfileEntitiesModel:
filesize=filestat.st_size,
creation_time=filestat.st_ctime,
modification_time=filestat.st_mtime,
+ created_by=created_by,
+ updated_by=updated_by,
note=note
)
@@ -481,7 +498,7 @@ class WorkfileEntitiesModel:
for workfile_info in ayon_api.get_workfiles_info(
self._controller.get_current_project_name(),
task_ids=[task_id],
- fields=["id", "path", "attrib"],
+ fields=["id", "path", "attrib", "createdBy", "updatedBy"],
):
workfile_identifier = self._get_workfile_info_identifier(
folder_id, task_id, workfile_info["path"]
@@ -525,18 +542,32 @@ class WorkfileEntitiesModel:
self._items.pop(identifier, None)
return
- if note is None:
- return
-
old_note = workfile_info.get("attrib", {}).get("note")
new_workfile_info = copy.deepcopy(workfile_info)
- attrib = new_workfile_info.setdefault("attrib", {})
- attrib["description"] = note
+ update_data = {}
+ if note is not None and old_note != note:
+ update_data["attrib"] = {"description": note}
+ attrib = new_workfile_info.setdefault("attrib", {})
+ attrib["description"] = note
+
+ username = self._get_current_username()
+ # Automatically fix 'createdBy' and 'updatedBy' fields
+ # NOTE both fields were not automatically filled by server
+ # until 1.1.3 release.
+ if workfile_info.get("createdBy") is None:
+ update_data["createdBy"] = username
+ new_workfile_info["createdBy"] = username
+
+ if workfile_info.get("updatedBy") != username:
+ update_data["updatedBy"] = username
+ new_workfile_info["updatedBy"] = username
+
+ if not update_data:
+ return
+
self._cache[identifier] = new_workfile_info
self._items.pop(identifier, None)
- if old_note == note:
- return
project_name = self._controller.get_current_project_name()
@@ -545,7 +576,7 @@ class WorkfileEntitiesModel:
project_name,
"workfile",
workfile_info["id"],
- {"attrib": {"description": note}},
+ update_data,
)
session.commit()
@@ -554,13 +585,18 @@ class WorkfileEntitiesModel:
project_name = self._controller.get_current_project_name()
+ username = self._get_current_username()
workfile_info = {
"path": rootless_path,
"taskId": task_id,
"attrib": {
"extension": extension,
"description": note
- }
+ },
+ # TODO remove 'createdBy' and 'updatedBy' fields when server is
+ # or above 1.1.3 .
+ "createdBy": username,
+ "updatedBy": username,
}
session = OperationsSession()
@@ -568,6 +604,11 @@ class WorkfileEntitiesModel:
session.commit()
return workfile_info
+ def _get_current_username(self):
+ if self._current_username is _NOT_SET:
+ self._current_username = get_ayon_username()
+ return self._current_username
+
class PublishWorkfilesModel:
"""Model for handling of published workfiles.
@@ -599,7 +640,7 @@ class PublishWorkfilesModel:
return self._cached_repre_extensions
def _file_item_from_representation(
- self, repre_entity, project_anatomy, task_name=None
+ self, repre_entity, project_anatomy, author, task_name=None
):
if task_name is not None:
task_info = repre_entity["context"].get("task")
@@ -634,6 +675,8 @@ class PublishWorkfilesModel:
dirpath,
filename,
created_at.float_timestamp,
+ author,
+ None,
repre_entity["id"]
)
@@ -643,9 +686,9 @@ class PublishWorkfilesModel:
# Get subset docs of folder
product_entities = ayon_api.get_products(
project_name,
- folder_ids=[folder_id],
- product_types=["workfile"],
- fields=["id", "name"]
+ folder_ids={folder_id},
+ product_types={"workfile"},
+ fields={"id", "name"}
)
output = []
@@ -657,25 +700,33 @@ class PublishWorkfilesModel:
version_entities = ayon_api.get_versions(
project_name,
product_ids=product_ids,
- fields=["id", "productId"]
+ fields={"id", "author"}
)
- version_ids = {version["id"] for version in version_entities}
- if not version_ids:
+ versions_by_id = {
+ version["id"]: version
+ for version in version_entities
+ }
+ if not versions_by_id:
return output
# Query representations of filtered versions and add filter for
# extension
repre_entities = ayon_api.get_representations(
project_name,
- version_ids=version_ids
+ version_ids=set(versions_by_id)
)
project_anatomy = self._controller.project_anatomy
# Filter queried representations by task name if task is set
file_items = []
for repre_entity in repre_entities:
+ version_id = repre_entity["versionId"]
+ version_entity = versions_by_id[version_id]
file_item = self._file_item_from_representation(
- repre_entity, project_anatomy, task_name
+ repre_entity,
+ project_anatomy,
+ version_entity["author"],
+ task_name,
)
if file_item is not None:
file_items.append(file_item)
diff --git a/client/ayon_core/tools/workfiles/widgets/files_widget_published.py b/client/ayon_core/tools/workfiles/widgets/files_widget_published.py
index bf36d790e9..2ce8569a9b 100644
--- a/client/ayon_core/tools/workfiles/widgets/files_widget_published.py
+++ b/client/ayon_core/tools/workfiles/widgets/files_widget_published.py
@@ -13,7 +13,8 @@ from .utils import BaseOverlayFrame
REPRE_ID_ROLE = QtCore.Qt.UserRole + 1
FILEPATH_ROLE = QtCore.Qt.UserRole + 2
-DATE_MODIFIED_ROLE = QtCore.Qt.UserRole + 3
+AUTHOR_ROLE = QtCore.Qt.UserRole + 3
+DATE_MODIFIED_ROLE = QtCore.Qt.UserRole + 4
class PublishedFilesModel(QtGui.QStandardItemModel):
@@ -23,13 +24,19 @@ class PublishedFilesModel(QtGui.QStandardItemModel):
controller (AbstractWorkfilesFrontend): The control object.
"""
+ columns = [
+ "Name",
+ "Author",
+ "Date Modified",
+ ]
+ date_modified_col = columns.index("Date Modified")
+
def __init__(self, controller):
super(PublishedFilesModel, self).__init__()
- self.setColumnCount(2)
-
- self.setHeaderData(0, QtCore.Qt.Horizontal, "Name")
- self.setHeaderData(1, QtCore.Qt.Horizontal, "Date Modified")
+ self.setColumnCount(len(self.columns))
+ for idx, label in enumerate(self.columns):
+ self.setHeaderData(idx, QtCore.Qt.Horizontal, label)
controller.register_event_callback(
"selection.task.changed",
@@ -185,6 +192,8 @@ class PublishedFilesModel(QtGui.QStandardItemModel):
self._remove_empty_item()
self._remove_missing_context_item()
+ user_items_by_name = self._controller.get_user_items_by_name()
+
items_to_remove = set(self._items_by_id.keys())
new_items = []
for file_item in file_items:
@@ -205,8 +214,15 @@ class PublishedFilesModel(QtGui.QStandardItemModel):
else:
flags = QtCore.Qt.NoItemFlags
+ author = file_item.created_by
+ user_item = user_items_by_name.get(author)
+ if user_item is not None and user_item.full_name:
+ author = user_item.full_name
+
item.setFlags(flags)
+
item.setData(file_item.filepath, FILEPATH_ROLE)
+ item.setData(author, AUTHOR_ROLE)
item.setData(file_item.modified, DATE_MODIFIED_ROLE)
self._items_by_id[repre_id] = item
@@ -225,22 +241,30 @@ class PublishedFilesModel(QtGui.QStandardItemModel):
# Use flags of first column for all columns
if index.column() != 0:
index = self.index(index.row(), 0, index.parent())
- return super(PublishedFilesModel, self).flags(index)
+ return super().flags(index)
def data(self, index, role=None):
if role is None:
role = QtCore.Qt.DisplayRole
# Handle roles for first column
- if index.column() == 1:
- if role == QtCore.Qt.DecorationRole:
- return None
+ col = index.column()
+ if col != 1:
+ return super().data(index, role)
- if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
+ if role == QtCore.Qt.DecorationRole:
+ return None
+
+ if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
+ if col == 1:
+ role = AUTHOR_ROLE
+ elif col == 2:
role = DATE_MODIFIED_ROLE
- index = self.index(index.row(), 0, index.parent())
+ else:
+ return None
+ index = self.index(index.row(), 0, index.parent())
- return super(PublishedFilesModel, self).data(index, role)
+ return super().data(index, role)
class SelectContextOverlay(BaseOverlayFrame):
@@ -295,7 +319,7 @@ class PublishedFilesWidget(QtWidgets.QWidget):
view.setModel(proxy_model)
time_delegate = PrettyTimeDelegate()
- view.setItemDelegateForColumn(1, time_delegate)
+ view.setItemDelegateForColumn(model.date_modified_col, time_delegate)
# Default to a wider first filename column it is what we mostly care
# about and the date modified is relatively small anyway.
diff --git a/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py b/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py
index fe6abee951..5c102dcdd4 100644
--- a/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py
+++ b/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py
@@ -10,7 +10,8 @@ from ayon_core.tools.utils.delegates import PrettyTimeDelegate
FILENAME_ROLE = QtCore.Qt.UserRole + 1
FILEPATH_ROLE = QtCore.Qt.UserRole + 2
-DATE_MODIFIED_ROLE = QtCore.Qt.UserRole + 3
+AUTHOR_ROLE = QtCore.Qt.UserRole + 3
+DATE_MODIFIED_ROLE = QtCore.Qt.UserRole + 4
class WorkAreaFilesModel(QtGui.QStandardItemModel):
@@ -21,14 +22,20 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel):
"""
refreshed = QtCore.Signal()
+ columns = [
+ "Name",
+ "Author",
+ "Date Modified",
+ ]
+ date_modified_col = columns.index("Date Modified")
def __init__(self, controller):
super(WorkAreaFilesModel, self).__init__()
- self.setColumnCount(2)
+ self.setColumnCount(len(self.columns))
- self.setHeaderData(0, QtCore.Qt.Horizontal, "Name")
- self.setHeaderData(1, QtCore.Qt.Horizontal, "Date Modified")
+ for idx, label in enumerate(self.columns):
+ self.setHeaderData(idx, QtCore.Qt.Horizontal, label)
controller.register_event_callback(
"selection.folder.changed",
@@ -186,6 +193,7 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel):
return
self._remove_empty_item()
self._remove_missing_context_item()
+ user_items_by_name = self._controller.get_user_items_by_name()
items_to_remove = set(self._items_by_filename.keys())
new_items = []
@@ -205,7 +213,13 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel):
item.setData(file_item.filename, QtCore.Qt.DisplayRole)
item.setData(file_item.filename, FILENAME_ROLE)
+ updated_by = file_item.updated_by
+ user_item = user_items_by_name.get(updated_by)
+ if user_item is not None and user_item.full_name:
+ updated_by = user_item.full_name
+
item.setData(file_item.filepath, FILEPATH_ROLE)
+ item.setData(updated_by, AUTHOR_ROLE)
item.setData(file_item.modified, DATE_MODIFIED_ROLE)
self._items_by_filename[file_item.filename] = item
@@ -224,22 +238,30 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel):
# Use flags of first column for all columns
if index.column() != 0:
index = self.index(index.row(), 0, index.parent())
- return super(WorkAreaFilesModel, self).flags(index)
+ return super().flags(index)
def data(self, index, role=None):
if role is None:
role = QtCore.Qt.DisplayRole
# Handle roles for first column
- if index.column() == 1:
- if role == QtCore.Qt.DecorationRole:
- return None
+ col = index.column()
+ if col == 0:
+ return super().data(index, role)
- if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
+ if role == QtCore.Qt.DecorationRole:
+ return None
+
+ if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
+ if col == 1:
+ role = AUTHOR_ROLE
+ elif col == 2:
role = DATE_MODIFIED_ROLE
- index = self.index(index.row(), 0, index.parent())
+ else:
+ return None
+ index = self.index(index.row(), 0, index.parent())
- return super(WorkAreaFilesModel, self).data(index, role)
+ return super().data(index, role)
def set_published_mode(self, published_mode):
if self._published_mode == published_mode:
@@ -279,7 +301,7 @@ class WorkAreaFilesWidget(QtWidgets.QWidget):
view.setModel(proxy_model)
time_delegate = PrettyTimeDelegate()
- view.setItemDelegateForColumn(1, time_delegate)
+ view.setItemDelegateForColumn(model.date_modified_col, time_delegate)
# Default to a wider first filename column it is what we mostly care
# about and the date modified is relatively small anyway.
diff --git a/client/ayon_core/tools/workfiles/widgets/side_panel.py b/client/ayon_core/tools/workfiles/widgets/side_panel.py
index 5085f4701e..53fdf0e0ac 100644
--- a/client/ayon_core/tools/workfiles/widgets/side_panel.py
+++ b/client/ayon_core/tools/workfiles/widgets/side_panel.py
@@ -147,13 +147,38 @@ class SidePanelWidget(QtWidgets.QWidget):
workfile_info.creation_time)
modification_time = datetime.datetime.fromtimestamp(
workfile_info.modification_time)
+
+ user_items_by_name = self._controller.get_user_items_by_name()
+
+ def convert_username(username):
+ user_item = user_items_by_name.get(username)
+ if user_item is not None and user_item.full_name:
+ return user_item.full_name
+ return username
+
+ created_lines = [
+ creation_time.strftime(datetime_format)
+ ]
+ if workfile_info.created_by:
+ created_lines.insert(
+ 0, convert_username(workfile_info.created_by)
+ )
+
+ modified_lines = [
+ modification_time.strftime(datetime_format)
+ ]
+ if workfile_info.updated_by:
+ modified_lines.insert(
+ 0, convert_username(workfile_info.updated_by)
+ )
+
lines = (
"Size:",
size_value,
"Created:",
- creation_time.strftime(datetime_format),
+ "
".join(created_lines),
"Modified:",
- modification_time.strftime(datetime_format)
+ "
".join(modified_lines),
)
self._orig_note = note
self._note_input.setPlainText(note)
diff --git a/client/ayon_core/tools/workfiles/widgets/window.py b/client/ayon_core/tools/workfiles/widgets/window.py
index 1cfae7ec90..8bcff66f50 100644
--- a/client/ayon_core/tools/workfiles/widgets/window.py
+++ b/client/ayon_core/tools/workfiles/widgets/window.py
@@ -107,7 +107,7 @@ class WorkfilesToolWindow(QtWidgets.QWidget):
split_widget.addWidget(tasks_widget)
split_widget.addWidget(col_3_widget)
split_widget.addWidget(side_panel)
- split_widget.setSizes([255, 160, 455, 175])
+ split_widget.setSizes([255, 175, 550, 190])
body_layout.addWidget(split_widget)
@@ -169,7 +169,7 @@ class WorkfilesToolWindow(QtWidgets.QWidget):
# Force focus on the open button by default, required for Houdini.
self._files_widget.setFocus()
- self.resize(1200, 600)
+ self.resize(1260, 600)
def _create_col_1_widget(self, controller, parent):
col_widget = QtWidgets.QWidget(parent)
diff --git a/server/__init__.py b/server/__init__.py
index 79f505ccd5..d60f50f471 100644
--- a/server/__init__.py
+++ b/server/__init__.py
@@ -2,7 +2,11 @@ from typing import Any
from ayon_server.addons import BaseServerAddon
-from .settings import CoreSettings, DEFAULT_VALUES
+from .settings import (
+ CoreSettings,
+ DEFAULT_VALUES,
+ convert_settings_overrides,
+)
class CoreAddon(BaseServerAddon):
@@ -17,47 +21,8 @@ class CoreAddon(BaseServerAddon):
source_version: str,
overrides: dict[str, Any],
) -> dict[str, Any]:
- self._convert_imagio_configs_0_3_1(overrides)
+ convert_settings_overrides(source_version, overrides)
# Use super conversion
return await super().convert_settings_overrides(
source_version, overrides
)
-
- def _convert_imagio_configs_0_3_1(self, overrides):
- """Imageio config settings did change to profiles since 0.3.1. ."""
- imageio_overrides = overrides.get("imageio") or {}
- if (
- "ocio_config" not in imageio_overrides
- or "filepath" not in imageio_overrides["ocio_config"]
- ):
- return
-
- ocio_config = imageio_overrides.pop("ocio_config")
-
- filepath = ocio_config["filepath"]
- if not filepath:
- return
- first_filepath = filepath[0]
- ocio_config_profiles = imageio_overrides.setdefault(
- "ocio_config_profiles", []
- )
- base_value = {
- "type": "builtin_path",
- "product_name": "",
- "host_names": [],
- "task_names": [],
- "task_types": [],
- "custom_path": "",
- "builtin_path": "{BUILTIN_OCIO_ROOT}/aces_1.2/config.ocio"
- }
- if first_filepath in (
- "{BUILTIN_OCIO_ROOT}/aces_1.2/config.ocio",
- "{BUILTIN_OCIO_ROOT}/nuke-default/config.ocio",
- ):
- base_value["type"] = "builtin_path"
- base_value["builtin_path"] = first_filepath
- else:
- base_value["type"] = "custom_path"
- base_value["custom_path"] = first_filepath
-
- ocio_config_profiles.append(base_value)
diff --git a/server/settings/__init__.py b/server/settings/__init__.py
index 527a2bdc0c..4bb21a9644 100644
--- a/server/settings/__init__.py
+++ b/server/settings/__init__.py
@@ -1,7 +1,10 @@
from .main import CoreSettings, DEFAULT_VALUES
+from .conversion import convert_settings_overrides
__all__ = (
"CoreSettings",
"DEFAULT_VALUES",
+
+ "convert_settings_overrides",
)
diff --git a/server/settings/conversion.py b/server/settings/conversion.py
new file mode 100644
index 0000000000..f513738603
--- /dev/null
+++ b/server/settings/conversion.py
@@ -0,0 +1,86 @@
+import copy
+from typing import Any
+
+from .publish_plugins import DEFAULT_PUBLISH_VALUES
+
+
+def _convert_imageio_configs_0_3_1(overrides):
+ """Imageio config settings did change to profiles since 0.3.1. ."""
+ imageio_overrides = overrides.get("imageio") or {}
+ if (
+ "ocio_config" not in imageio_overrides
+ or "filepath" not in imageio_overrides["ocio_config"]
+ ):
+ return
+
+ ocio_config = imageio_overrides.pop("ocio_config")
+
+ filepath = ocio_config["filepath"]
+ if not filepath:
+ return
+ first_filepath = filepath[0]
+ ocio_config_profiles = imageio_overrides.setdefault(
+ "ocio_config_profiles", []
+ )
+ base_value = {
+ "type": "builtin_path",
+ "product_name": "",
+ "host_names": [],
+ "task_names": [],
+ "task_types": [],
+ "custom_path": "",
+ "builtin_path": "{BUILTIN_OCIO_ROOT}/aces_1.2/config.ocio"
+ }
+ if first_filepath in (
+ "{BUILTIN_OCIO_ROOT}/aces_1.2/config.ocio",
+ "{BUILTIN_OCIO_ROOT}/nuke-default/config.ocio",
+ ):
+ base_value["type"] = "builtin_path"
+ base_value["builtin_path"] = first_filepath
+ else:
+ base_value["type"] = "custom_path"
+ base_value["custom_path"] = first_filepath
+
+ ocio_config_profiles.append(base_value)
+
+
+def _convert_validate_version_0_3_3(publish_overrides):
+ """ValidateVersion plugin changed in 0.3.3."""
+ if "ValidateVersion" not in publish_overrides:
+ return
+
+ validate_version = publish_overrides["ValidateVersion"]
+ # Already new settings
+ if "plugin_state_profiles" in validate_version:
+ return
+
+ # Use new default profile as base
+ profile = copy.deepcopy(
+ DEFAULT_PUBLISH_VALUES["ValidateVersion"]["plugin_state_profiles"][0]
+ )
+ # Copy values from old overrides to new overrides
+ for key in {
+ "enabled",
+ "optional",
+ "active",
+ }:
+ if key not in validate_version:
+ continue
+ profile[key] = validate_version.pop(key)
+
+ validate_version["plugin_state_profiles"] = [profile]
+
+
+def _conver_publish_plugins(overrides):
+ if "publish" not in overrides:
+ return
+ _convert_validate_version_0_3_3(overrides["publish"])
+
+
+def convert_settings_overrides(
+ source_version: str,
+ overrides: dict[str, Any],
+) -> dict[str, Any]:
+ _convert_imageio_configs_0_3_1(overrides)
+ _conver_publish_plugins(overrides)
+ return overrides
diff --git a/server/settings/publish_plugins.py b/server/settings/publish_plugins.py
index 61e73ce912..2640a3db37 100644
--- a/server/settings/publish_plugins.py
+++ b/server/settings/publish_plugins.py
@@ -59,7 +59,7 @@ class CollectFramesFixDefModel(BaseSettingsModel):
)
-class ValidateOutdatedContainersProfile(BaseSettingsModel):
+class PluginStateByHostModelProfile(BaseSettingsModel):
_layout = "expanded"
# Filtering
host_names: list[str] = SettingsField(
@@ -72,17 +72,12 @@ class ValidateOutdatedContainersProfile(BaseSettingsModel):
active: bool = SettingsField(True, title="Active")
-class ValidateOutdatedContainersModel(BaseSettingsModel):
- """Validate if Publishing intent was selected.
-
- It is possible to disable validation for specific publishing context
- with profiles.
- """
-
+class PluginStateByHostModel(BaseSettingsModel):
_isGroup = True
- plugin_state_profiles: list[ValidateOutdatedContainersProfile] = SettingsField(
+ plugin_state_profiles: list[PluginStateByHostModelProfile] = SettingsField(
default_factory=list,
title="Plugin enable state profiles",
+ description="Change plugin state based on host name."
)
@@ -563,7 +558,7 @@ class ExtractBurninProfile(BaseSettingsModel):
_layout = "expanded"
product_types: list[str] = SettingsField(
default_factory=list,
- title="Produt types"
+ title="Product types"
)
hosts: list[str] = SettingsField(
default_factory=list,
@@ -793,12 +788,16 @@ class PublishPuginsModel(BaseSettingsModel):
default_factory=ValidateBaseModel,
title="Validate Editorial Asset Name"
)
- ValidateVersion: ValidateBaseModel = SettingsField(
- default_factory=ValidateBaseModel,
- title="Validate Version"
+ ValidateVersion: PluginStateByHostModel = SettingsField(
+ default_factory=PluginStateByHostModel,
+ title="Validate Version",
+ description=(
+ "Validate that product version to integrate"
+ " is newer than latest version in AYON."
+ )
)
- ValidateOutdatedContainers: ValidateOutdatedContainersModel = SettingsField(
- default_factory=ValidateOutdatedContainersModel,
+ ValidateOutdatedContainers: PluginStateByHostModel = SettingsField(
+ default_factory=PluginStateByHostModel,
title="Validate Containers"
)
ValidateIntent: ValidateIntentModel = SettingsField(
@@ -882,9 +881,21 @@ DEFAULT_PUBLISH_VALUES = {
"active": True
},
"ValidateVersion": {
- "enabled": True,
- "optional": False,
- "active": True
+ "plugin_state_profiles": [
+ {
+ "host_names": [
+ "aftereffects",
+ "blender",
+ "houdini",
+ "maya",
+ "nuke",
+ "photoshop",
+ ],
+ "enabled": True,
+ "optional": False,
+ "active": True
+ }
+ ]
},
"ValidateOutdatedContainers": {
"plugin_state_profiles": [
diff --git a/client/ayon_core/hosts/celaction/__init__.py b/server_addon/celaction/client/ayon_celaction/__init__.py
similarity index 71%
rename from client/ayon_core/hosts/celaction/__init__.py
rename to server_addon/celaction/client/ayon_celaction/__init__.py
index 8983d48d7d..0df0224125 100644
--- a/client/ayon_core/hosts/celaction/__init__.py
+++ b/server_addon/celaction/client/ayon_celaction/__init__.py
@@ -1,3 +1,4 @@
+from .version import __version__
from .addon import (
CELACTION_ROOT_DIR,
CelactionAddon,
@@ -5,6 +6,8 @@ from .addon import (
__all__ = (
+ "__version__",
+
"CELACTION_ROOT_DIR",
"CelactionAddon",
)
diff --git a/client/ayon_core/hosts/celaction/addon.py b/server_addon/celaction/client/ayon_celaction/addon.py
similarity index 92%
rename from client/ayon_core/hosts/celaction/addon.py
rename to server_addon/celaction/client/ayon_celaction/addon.py
index d00401a2e0..ad04a54088 100644
--- a/client/ayon_core/hosts/celaction/addon.py
+++ b/server_addon/celaction/client/ayon_celaction/addon.py
@@ -1,11 +1,14 @@
import os
from ayon_core.addon import AYONAddon, IHostAddon
+from .version import __version__
+
CELACTION_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
class CelactionAddon(AYONAddon, IHostAddon):
name = "celaction"
+ version = __version__
host_name = "celaction"
def get_launch_hook_paths(self, app):
diff --git a/client/ayon_core/hosts/celaction/hooks/pre_celaction_setup.py b/server_addon/celaction/client/ayon_celaction/hooks/pre_celaction_setup.py
similarity index 96%
rename from client/ayon_core/hosts/celaction/hooks/pre_celaction_setup.py
rename to server_addon/celaction/client/ayon_celaction/hooks/pre_celaction_setup.py
index 8350c7b7c8..52622d43b8 100644
--- a/client/ayon_core/hosts/celaction/hooks/pre_celaction_setup.py
+++ b/server_addon/celaction/client/ayon_celaction/hooks/pre_celaction_setup.py
@@ -4,13 +4,11 @@ import winreg
import subprocess
from ayon_core.lib import get_ayon_launcher_args
from ayon_applications import PreLaunchHook, LaunchTypes
-from ayon_core.hosts.celaction import CELACTION_ROOT_DIR
+from ayon_celaction import CELACTION_ROOT_DIR
class CelactionPrelaunchHook(PreLaunchHook):
- """
- Bootstrap celacion with pype
- """
+ """Bootstrap celacion with AYON"""
app_groups = {"celaction"}
platforms = {"windows"}
launch_types = {LaunchTypes.local}
@@ -39,7 +37,7 @@ class CelactionPrelaunchHook(PreLaunchHook):
CELACTION_ROOT_DIR, "scripts", "publish_cli.py"
)
subprocess_args = get_ayon_launcher_args("run", path_to_cli)
- openpype_executable = subprocess_args.pop(0)
+ executable = subprocess_args.pop(0)
workfile_settings = self.get_workfile_settings()
winreg.SetValueEx(
@@ -47,7 +45,7 @@ class CelactionPrelaunchHook(PreLaunchHook):
"SubmitAppTitle",
0,
winreg.REG_SZ,
- openpype_executable
+ executable
)
# add required arguments for workfile path
diff --git a/client/ayon_core/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py b/server_addon/celaction/client/ayon_celaction/plugins/publish/collect_celaction_cli_kwargs.py
similarity index 100%
rename from client/ayon_core/hosts/celaction/plugins/publish/collect_celaction_cli_kwargs.py
rename to server_addon/celaction/client/ayon_celaction/plugins/publish/collect_celaction_cli_kwargs.py
diff --git a/client/ayon_core/hosts/celaction/plugins/publish/collect_celaction_instances.py b/server_addon/celaction/client/ayon_celaction/plugins/publish/collect_celaction_instances.py
similarity index 100%
rename from client/ayon_core/hosts/celaction/plugins/publish/collect_celaction_instances.py
rename to server_addon/celaction/client/ayon_celaction/plugins/publish/collect_celaction_instances.py
diff --git a/client/ayon_core/hosts/celaction/plugins/publish/collect_render_path.py b/server_addon/celaction/client/ayon_celaction/plugins/publish/collect_render_path.py
similarity index 98%
rename from client/ayon_core/hosts/celaction/plugins/publish/collect_render_path.py
rename to server_addon/celaction/client/ayon_celaction/plugins/publish/collect_render_path.py
index 1bb4d54831..3bcd1c69b3 100644
--- a/client/ayon_core/hosts/celaction/plugins/publish/collect_render_path.py
+++ b/server_addon/celaction/client/ayon_celaction/plugins/publish/collect_render_path.py
@@ -1,6 +1,6 @@
import os
-import pyblish.api
import copy
+import pyblish.api
class CollectRenderPath(pyblish.api.InstancePlugin):
@@ -10,6 +10,8 @@ class CollectRenderPath(pyblish.api.InstancePlugin):
order = pyblish.api.CollectorOrder + 0.495
families = ["render.farm"]
+ settings_category = "celaction"
+
# Presets
output_extension = "png"
anatomy_template_key_render_files = None
diff --git a/client/ayon_core/hosts/celaction/plugins/publish/integrate_version_up.py b/server_addon/celaction/client/ayon_celaction/plugins/publish/integrate_version_up.py
similarity index 100%
rename from client/ayon_core/hosts/celaction/plugins/publish/integrate_version_up.py
rename to server_addon/celaction/client/ayon_celaction/plugins/publish/integrate_version_up.py
diff --git a/client/ayon_core/hosts/celaction/resources/celaction_template_scene.scn b/server_addon/celaction/client/ayon_celaction/resources/celaction_template_scene.scn
similarity index 100%
rename from client/ayon_core/hosts/celaction/resources/celaction_template_scene.scn
rename to server_addon/celaction/client/ayon_celaction/resources/celaction_template_scene.scn
diff --git a/client/ayon_core/hosts/celaction/plugins/__init__.py b/server_addon/celaction/client/ayon_celaction/scripts/__init__.py
similarity index 100%
rename from client/ayon_core/hosts/celaction/plugins/__init__.py
rename to server_addon/celaction/client/ayon_celaction/scripts/__init__.py
diff --git a/client/ayon_core/hosts/celaction/scripts/publish_cli.py b/server_addon/celaction/client/ayon_celaction/scripts/publish_cli.py
similarity index 77%
rename from client/ayon_core/hosts/celaction/scripts/publish_cli.py
rename to server_addon/celaction/client/ayon_celaction/scripts/publish_cli.py
index 92019b8702..4e54aa253a 100644
--- a/client/ayon_core/hosts/celaction/scripts/publish_cli.py
+++ b/server_addon/celaction/client/ayon_celaction/scripts/publish_cli.py
@@ -4,7 +4,7 @@ import sys
import pyblish.api
import pyblish.util
-import ayon_core.hosts.celaction
+from ayon_celaction import CELACTION_ROOT_DIR
from ayon_core.lib import Logger
from ayon_core.tools.utils import host_tools
from ayon_core.pipeline import install_ayon_plugins
@@ -13,13 +13,12 @@ from ayon_core.pipeline import install_ayon_plugins
log = Logger.get_logger("celaction")
PUBLISH_HOST = "celaction"
-HOST_DIR = os.path.dirname(os.path.abspath(ayon_core.hosts.celaction.__file__))
-PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
+PLUGINS_DIR = os.path.join(CELACTION_ROOT_DIR, "plugins")
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
def main():
- # Registers pype's Global pyblish plugins
+ # Registers global pyblish plugins
install_ayon_plugins()
if os.path.exists(PUBLISH_PATH):
diff --git a/server_addon/celaction/client/ayon_celaction/version.py b/server_addon/celaction/client/ayon_celaction/version.py
new file mode 100644
index 0000000000..ceed47c3a0
--- /dev/null
+++ b/server_addon/celaction/client/ayon_celaction/version.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+"""Package declaring AYON addon 'celaction' version."""
+__version__ = "0.2.0"
diff --git a/server_addon/celaction/package.py b/server_addon/celaction/package.py
index 2b11a8630f..8b9069d019 100644
--- a/server_addon/celaction/package.py
+++ b/server_addon/celaction/package.py
@@ -1,3 +1,12 @@
name = "celaction"
title = "CelAction"
-version = "0.1.0"
+version = "0.2.0"
+
+client_dir = "ayon_celaction"
+
+ayon_required_addons = {
+ "core": ">0.3.2",
+}
+ayon_compatible_addons = {
+ "applications": ">=0.2.0",
+}
diff --git a/server_addon/flame/client/ayon_flame/__init__.py b/server_addon/flame/client/ayon_flame/__init__.py
new file mode 100644
index 0000000000..d2d89bdb01
--- /dev/null
+++ b/server_addon/flame/client/ayon_flame/__init__.py
@@ -0,0 +1,13 @@
+from .version import __version__
+from .addon import (
+ FLAME_ADDON_ROOT,
+ FlameAddon,
+)
+
+
+__all__ = (
+ "__version__",
+
+ "FLAME_ADDON_ROOT",
+ "FlameAddon",
+)
diff --git a/client/ayon_core/hosts/flame/addon.py b/server_addon/flame/client/ayon_flame/addon.py
similarity index 74%
rename from client/ayon_core/hosts/flame/addon.py
rename to server_addon/flame/client/ayon_flame/addon.py
index f5560cde7a..5a96a9332e 100644
--- a/client/ayon_core/hosts/flame/addon.py
+++ b/server_addon/flame/client/ayon_flame/addon.py
@@ -1,16 +1,19 @@
import os
from ayon_core.addon import AYONAddon, IHostAddon
-HOST_DIR = os.path.dirname(os.path.abspath(__file__))
+from .version import __version__
+
+FLAME_ADDON_ROOT = os.path.dirname(os.path.abspath(__file__))
class FlameAddon(AYONAddon, IHostAddon):
name = "flame"
+ version = __version__
host_name = "flame"
def add_implementation_envs(self, env, _app):
# Add requirements to DL_PYTHON_HOOK_PATH
- env["DL_PYTHON_HOOK_PATH"] = os.path.join(HOST_DIR, "startup")
+ env["DL_PYTHON_HOOK_PATH"] = os.path.join(FLAME_ADDON_ROOT, "startup")
env.pop("QT_AUTO_SCREEN_SCALE_FACTOR", None)
# Set default values if are not already set via settings
@@ -25,7 +28,7 @@ class FlameAddon(AYONAddon, IHostAddon):
if app.host_name != self.host_name:
return []
return [
- os.path.join(HOST_DIR, "hooks")
+ os.path.join(FLAME_ADDON_ROOT, "hooks")
]
def get_workfile_extensions(self):
diff --git a/client/ayon_core/hosts/flame/api/__init__.py b/server_addon/flame/client/ayon_flame/api/__init__.py
similarity index 100%
rename from client/ayon_core/hosts/flame/api/__init__.py
rename to server_addon/flame/client/ayon_flame/api/__init__.py
diff --git a/client/ayon_core/hosts/flame/api/batch_utils.py b/server_addon/flame/client/ayon_flame/api/batch_utils.py
similarity index 100%
rename from client/ayon_core/hosts/flame/api/batch_utils.py
rename to server_addon/flame/client/ayon_flame/api/batch_utils.py
diff --git a/client/ayon_core/hosts/flame/api/constants.py b/server_addon/flame/client/ayon_flame/api/constants.py
similarity index 100%
rename from client/ayon_core/hosts/flame/api/constants.py
rename to server_addon/flame/client/ayon_flame/api/constants.py
diff --git a/client/ayon_core/hosts/flame/api/lib.py b/server_addon/flame/client/ayon_flame/api/lib.py
similarity index 100%
rename from client/ayon_core/hosts/flame/api/lib.py
rename to server_addon/flame/client/ayon_flame/api/lib.py
diff --git a/client/ayon_core/hosts/flame/api/menu.py b/server_addon/flame/client/ayon_flame/api/menu.py
similarity index 99%
rename from client/ayon_core/hosts/flame/api/menu.py
rename to server_addon/flame/client/ayon_flame/api/menu.py
index 7e880483f5..83d75d18d3 100644
--- a/client/ayon_core/hosts/flame/api/menu.py
+++ b/server_addon/flame/client/ayon_flame/api/menu.py
@@ -28,7 +28,7 @@ default_flame_export_presets = {
def callback_selection(selection, function):
- import ayon_core.hosts.flame.api as opfapi
+ import ayon_flame.api as opfapi
opfapi.CTX.selection = selection
print("Hook Selection: \n\t{}".format(
pformat({
diff --git a/client/ayon_core/hosts/flame/api/pipeline.py b/server_addon/flame/client/ayon_flame/api/pipeline.py
similarity index 95%
rename from client/ayon_core/hosts/flame/api/pipeline.py
rename to server_addon/flame/client/ayon_flame/api/pipeline.py
index 4578d7bb4b..121b925920 100644
--- a/client/ayon_core/hosts/flame/api/pipeline.py
+++ b/server_addon/flame/client/ayon_flame/api/pipeline.py
@@ -13,6 +13,7 @@ from ayon_core.pipeline import (
deregister_creator_plugin_path,
AVALON_CONTAINER_ID,
)
+from ayon_flame import FLAME_ADDON_ROOT
from .lib import (
set_segment_data_marker,
set_publish_attribute,
@@ -20,10 +21,8 @@ from .lib import (
get_current_sequence,
reset_segment_selection
)
-from .. import HOST_DIR
-API_DIR = os.path.join(HOST_DIR, "api")
-PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
+PLUGINS_DIR = os.path.join(FLAME_ADDON_ROOT, "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")
@@ -113,10 +112,6 @@ def on_pyblish_instance_toggled(instance, old_value, new_value):
log.info("instance toggle: {}, old_value: {}, new_value:{} ".format(
instance, old_value, new_value))
- # from ayon_core.hosts.resolve import (
- # set_publish_attribute
- # )
-
# # Whether instances should be passthrough based on new value
# timeline_item = instance.data["item"]
# set_publish_attribute(timeline_item, new_value)
diff --git a/client/ayon_core/hosts/flame/api/plugin.py b/server_addon/flame/client/ayon_flame/api/plugin.py
similarity index 100%
rename from client/ayon_core/hosts/flame/api/plugin.py
rename to server_addon/flame/client/ayon_flame/api/plugin.py
diff --git a/client/ayon_core/hosts/flame/api/render_utils.py b/server_addon/flame/client/ayon_flame/api/render_utils.py
similarity index 100%
rename from client/ayon_core/hosts/flame/api/render_utils.py
rename to server_addon/flame/client/ayon_flame/api/render_utils.py
diff --git a/client/ayon_core/hosts/flame/api/scripts/wiretap_com.py b/server_addon/flame/client/ayon_flame/api/scripts/wiretap_com.py
similarity index 100%
rename from client/ayon_core/hosts/flame/api/scripts/wiretap_com.py
rename to server_addon/flame/client/ayon_flame/api/scripts/wiretap_com.py
diff --git a/client/ayon_core/hosts/flame/api/utils.py b/server_addon/flame/client/ayon_flame/api/utils.py
similarity index 98%
rename from client/ayon_core/hosts/flame/api/utils.py
rename to server_addon/flame/client/ayon_flame/api/utils.py
index b76dd92ada..03a694c25c 100644
--- a/client/ayon_core/hosts/flame/api/utils.py
+++ b/server_addon/flame/client/ayon_flame/api/utils.py
@@ -5,6 +5,8 @@ Flame utils for syncing scripts
import os
import shutil
from ayon_core.lib import Logger
+from ayon_flame import FLAME_ADDON_ROOT
+
log = Logger.get_logger(__name__)
@@ -16,7 +18,6 @@ def _sync_utility_scripts(env=None):
`/opt/Autodesk/shared/python`. This will be always synchronizing those
folders.
"""
- from .. import HOST_DIR
env = env or os.environ
@@ -26,7 +27,7 @@ def _sync_utility_scripts(env=None):
flame_shared_dir = "/opt/Autodesk/shared/python"
fsd_paths = [os.path.join(
- HOST_DIR,
+ FLAME_ADDON_ROOT,
"api",
"utility_scripts"
)]
diff --git a/client/ayon_core/hosts/flame/api/workio.py b/server_addon/flame/client/ayon_flame/api/workio.py
similarity index 100%
rename from client/ayon_core/hosts/flame/api/workio.py
rename to server_addon/flame/client/ayon_flame/api/workio.py
diff --git a/client/ayon_core/hosts/flame/hooks/pre_flame_setup.py b/server_addon/flame/client/ayon_flame/hooks/pre_flame_setup.py
similarity index 98%
rename from client/ayon_core/hosts/flame/hooks/pre_flame_setup.py
rename to server_addon/flame/client/ayon_flame/hooks/pre_flame_setup.py
index 77a9435205..e9e9aca3f4 100644
--- a/client/ayon_core/hosts/flame/hooks/pre_flame_setup.py
+++ b/server_addon/flame/client/ayon_flame/hooks/pre_flame_setup.py
@@ -10,7 +10,7 @@ from ayon_core.lib import (
run_subprocess,
)
from ayon_applications import PreLaunchHook, LaunchTypes
-from ayon_core.hosts import flame as opflame
+from ayon_flame import FLAME_ADDON_ROOT
class FlamePrelaunch(PreLaunchHook):
@@ -23,7 +23,8 @@ class FlamePrelaunch(PreLaunchHook):
permissions = 0o777
wtc_script_path = os.path.join(
- opflame.HOST_DIR, "api", "scripts", "wiretap_com.py")
+ FLAME_ADDON_ROOT, "api", "scripts", "wiretap_com.py"
+ )
launch_types = {LaunchTypes.local}
def __init__(self, *args, **kwargs):
diff --git a/client/ayon_core/hosts/celaction/scripts/__init__.py b/server_addon/flame/client/ayon_flame/otio/__init__.py
similarity index 100%
rename from client/ayon_core/hosts/celaction/scripts/__init__.py
rename to server_addon/flame/client/ayon_flame/otio/__init__.py
diff --git a/client/ayon_core/hosts/flame/otio/flame_export.py b/server_addon/flame/client/ayon_flame/otio/flame_export.py
similarity index 99%
rename from client/ayon_core/hosts/flame/otio/flame_export.py
rename to server_addon/flame/client/ayon_flame/otio/flame_export.py
index cb038f9e9a..bebe9be1c1 100644
--- a/client/ayon_core/hosts/flame/otio/flame_export.py
+++ b/server_addon/flame/client/ayon_flame/otio/flame_export.py
@@ -275,7 +275,7 @@ def create_otio_reference(clip_data, fps=None):
def create_otio_clip(clip_data):
- from ayon_core.hosts.flame.api import MediaInfoFile, TimeEffectMetadata
+ from ayon_flame.api import MediaInfoFile, TimeEffectMetadata
segment = clip_data["PySegment"]
diff --git a/client/ayon_core/hosts/flame/otio/utils.py b/server_addon/flame/client/ayon_flame/otio/utils.py
similarity index 100%
rename from client/ayon_core/hosts/flame/otio/utils.py
rename to server_addon/flame/client/ayon_flame/otio/utils.py
diff --git a/client/ayon_core/hosts/flame/plugins/create/create_shot_clip.py b/server_addon/flame/client/ayon_flame/plugins/create/create_shot_clip.py
similarity index 99%
rename from client/ayon_core/hosts/flame/plugins/create/create_shot_clip.py
rename to server_addon/flame/client/ayon_flame/plugins/create/create_shot_clip.py
index 56f5319f21..120c8c559d 100644
--- a/client/ayon_core/hosts/flame/plugins/create/create_shot_clip.py
+++ b/server_addon/flame/client/ayon_flame/plugins/create/create_shot_clip.py
@@ -1,5 +1,5 @@
from copy import deepcopy
-import ayon_core.hosts.flame.api as opfapi
+import ayon_flame.api as opfapi
class CreateShotClip(opfapi.Creator):
diff --git a/client/ayon_core/hosts/flame/plugins/load/load_clip.py b/server_addon/flame/client/ayon_flame/plugins/load/load_clip.py
similarity index 99%
rename from client/ayon_core/hosts/flame/plugins/load/load_clip.py
rename to server_addon/flame/client/ayon_flame/plugins/load/load_clip.py
index 40ab9c038b..c8ec7b36c9 100644
--- a/client/ayon_core/hosts/flame/plugins/load/load_clip.py
+++ b/server_addon/flame/client/ayon_flame/plugins/load/load_clip.py
@@ -2,7 +2,7 @@ from copy import deepcopy
import os
import flame
from pprint import pformat
-import ayon_core.hosts.flame.api as opfapi
+import ayon_flame.api as opfapi
from ayon_core.lib import StringTemplate
from ayon_core.lib.transcoding import (
VIDEO_EXTENSIONS,
diff --git a/client/ayon_core/hosts/flame/plugins/load/load_clip_batch.py b/server_addon/flame/client/ayon_flame/plugins/load/load_clip_batch.py
similarity index 99%
rename from client/ayon_core/hosts/flame/plugins/load/load_clip_batch.py
rename to server_addon/flame/client/ayon_flame/plugins/load/load_clip_batch.py
index 1b23a8b465..0d7a125af7 100644
--- a/client/ayon_core/hosts/flame/plugins/load/load_clip_batch.py
+++ b/server_addon/flame/client/ayon_flame/plugins/load/load_clip_batch.py
@@ -2,7 +2,7 @@ from copy import deepcopy
import os
import flame
from pprint import pformat
-import ayon_core.hosts.flame.api as opfapi
+import ayon_flame.api as opfapi
from ayon_core.lib import StringTemplate
from ayon_core.lib.transcoding import (
VIDEO_EXTENSIONS,
diff --git a/client/ayon_core/hosts/flame/plugins/publish/collect_test_selection.py b/server_addon/flame/client/ayon_flame/plugins/publish/collect_test_selection.py
similarity index 94%
rename from client/ayon_core/hosts/flame/plugins/publish/collect_test_selection.py
rename to server_addon/flame/client/ayon_flame/plugins/publish/collect_test_selection.py
index 7442e7df48..dac2c862e6 100644
--- a/client/ayon_core/hosts/flame/plugins/publish/collect_test_selection.py
+++ b/server_addon/flame/client/ayon_flame/plugins/publish/collect_test_selection.py
@@ -1,8 +1,8 @@
import os
import pyblish.api
import tempfile
-import ayon_core.hosts.flame.api as opfapi
-from ayon_core.hosts.flame.otio import flame_export as otio_export
+import ayon_flame.api as opfapi
+from ayon_flame.otio import flame_export as otio_export
import opentimelineio as otio
from pprint import pformat
reload(otio_export) # noqa
diff --git a/client/ayon_core/hosts/flame/plugins/publish/collect_timeline_instances.py b/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py
similarity index 99%
rename from client/ayon_core/hosts/flame/plugins/publish/collect_timeline_instances.py
rename to server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py
index ca5475824d..35591f1a0d 100644
--- a/client/ayon_core/hosts/flame/plugins/publish/collect_timeline_instances.py
+++ b/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_instances.py
@@ -1,8 +1,8 @@
import re
from types import NoneType
import pyblish
-import ayon_core.hosts.flame.api as opfapi
-from ayon_core.hosts.flame.otio import flame_export
+import ayon_flame.api as opfapi
+from ayon_flame.otio import flame_export
from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID
from ayon_core.pipeline.editorial import (
is_overlapping_otio_ranges,
@@ -24,6 +24,8 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin):
label = "Collect timeline Instances"
hosts = ["flame"]
+ settings_category = "flame"
+
audio_track_items = []
# settings
diff --git a/client/ayon_core/hosts/flame/plugins/publish/collect_timeline_otio.py b/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_otio.py
similarity index 95%
rename from client/ayon_core/hosts/flame/plugins/publish/collect_timeline_otio.py
rename to server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_otio.py
index 7609ea7879..139ac5b875 100644
--- a/client/ayon_core/hosts/flame/plugins/publish/collect_timeline_otio.py
+++ b/server_addon/flame/client/ayon_flame/plugins/publish/collect_timeline_otio.py
@@ -1,7 +1,7 @@
import pyblish.api
-import ayon_core.hosts.flame.api as opfapi
-from ayon_core.hosts.flame.otio import flame_export
+import ayon_flame.api as opfapi
+from ayon_flame.otio import flame_export
from ayon_core.pipeline.create import get_product_name
diff --git a/client/ayon_core/hosts/flame/plugins/publish/extract_otio_file.py b/server_addon/flame/client/ayon_flame/plugins/publish/extract_otio_file.py
similarity index 100%
rename from client/ayon_core/hosts/flame/plugins/publish/extract_otio_file.py
rename to server_addon/flame/client/ayon_flame/plugins/publish/extract_otio_file.py
diff --git a/client/ayon_core/hosts/flame/plugins/publish/extract_subset_resources.py b/server_addon/flame/client/ayon_flame/plugins/publish/extract_subset_resources.py
similarity index 99%
rename from client/ayon_core/hosts/flame/plugins/publish/extract_subset_resources.py
rename to server_addon/flame/client/ayon_flame/plugins/publish/extract_subset_resources.py
index cae08cd76b..66c6181ffb 100644
--- a/client/ayon_core/hosts/flame/plugins/publish/extract_subset_resources.py
+++ b/server_addon/flame/client/ayon_flame/plugins/publish/extract_subset_resources.py
@@ -5,8 +5,8 @@ from copy import deepcopy
import pyblish.api
from ayon_core.pipeline import publish
-from ayon_core.hosts.flame import api as opfapi
-from ayon_core.hosts.flame.api import MediaInfoFile
+from ayon_flame import api as opfapi
+from ayon_flame.api import MediaInfoFile
from ayon_core.pipeline.editorial import (
get_media_range_with_retimes
)
@@ -24,6 +24,8 @@ class ExtractProductResources(publish.Extractor):
families = ["clip"]
hosts = ["flame"]
+ settings_category = "flame"
+
# plugin defaults
keep_original_representation = False
diff --git a/client/ayon_core/hosts/flame/plugins/publish/integrate_batch_group.py b/server_addon/flame/client/ayon_flame/plugins/publish/integrate_batch_group.py
similarity index 99%
rename from client/ayon_core/hosts/flame/plugins/publish/integrate_batch_group.py
rename to server_addon/flame/client/ayon_flame/plugins/publish/integrate_batch_group.py
index d8669f836d..f77c9e9116 100644
--- a/client/ayon_core/hosts/flame/plugins/publish/integrate_batch_group.py
+++ b/server_addon/flame/client/ayon_flame/plugins/publish/integrate_batch_group.py
@@ -3,7 +3,7 @@ import copy
from collections import OrderedDict
from pprint import pformat
import pyblish
-import ayon_core.hosts.flame.api as opfapi
+import ayon_flame.api as opfapi
import ayon_core.pipeline as op_pipeline
from ayon_core.pipeline.workfile import get_workdir
@@ -16,6 +16,8 @@ class IntegrateBatchGroup(pyblish.api.InstancePlugin):
hosts = ["flame"]
families = ["clip"]
+ settings_category = "flame"
+
# settings
default_loader = "LoadClip"
diff --git a/client/ayon_core/hosts/flame/startup/openpype_babypublisher/export_preset/openpype_seg_thumbnails_jpg.xml b/server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/export_preset/openpype_seg_thumbnails_jpg.xml
similarity index 100%
rename from client/ayon_core/hosts/flame/startup/openpype_babypublisher/export_preset/openpype_seg_thumbnails_jpg.xml
rename to server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/export_preset/openpype_seg_thumbnails_jpg.xml
diff --git a/client/ayon_core/hosts/flame/startup/openpype_babypublisher/export_preset/openpype_seg_video_h264.xml b/server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/export_preset/openpype_seg_video_h264.xml
similarity index 100%
rename from client/ayon_core/hosts/flame/startup/openpype_babypublisher/export_preset/openpype_seg_video_h264.xml
rename to server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/export_preset/openpype_seg_video_h264.xml
diff --git a/client/ayon_core/hosts/flame/otio/__init__.py b/server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/__init__.py
similarity index 100%
rename from client/ayon_core/hosts/flame/otio/__init__.py
rename to server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/__init__.py
diff --git a/client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/app_utils.py b/server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/app_utils.py
similarity index 100%
rename from client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/app_utils.py
rename to server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/app_utils.py
diff --git a/client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/ftrack_lib.py b/server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/ftrack_lib.py
similarity index 100%
rename from client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/ftrack_lib.py
rename to server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/ftrack_lib.py
diff --git a/client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/panel_app.py b/server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/panel_app.py
similarity index 100%
rename from client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/panel_app.py
rename to server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/panel_app.py
diff --git a/client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/uiwidgets.py b/server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/uiwidgets.py
similarity index 100%
rename from client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/uiwidgets.py
rename to server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/modules/uiwidgets.py
diff --git a/client/ayon_core/hosts/flame/startup/openpype_babypublisher/openpype_babypublisher.py b/server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/openpype_babypublisher.py
similarity index 100%
rename from client/ayon_core/hosts/flame/startup/openpype_babypublisher/openpype_babypublisher.py
rename to server_addon/flame/client/ayon_flame/startup/openpype_babypublisher/openpype_babypublisher.py
diff --git a/client/ayon_core/hosts/flame/startup/openpype_in_flame.py b/server_addon/flame/client/ayon_flame/startup/openpype_in_flame.py
similarity index 99%
rename from client/ayon_core/hosts/flame/startup/openpype_in_flame.py
rename to server_addon/flame/client/ayon_flame/startup/openpype_in_flame.py
index b9cbf9700b..8f319a88eb 100644
--- a/client/ayon_core/hosts/flame/startup/openpype_in_flame.py
+++ b/server_addon/flame/client/ayon_flame/startup/openpype_in_flame.py
@@ -4,7 +4,7 @@ from qtpy import QtWidgets
from pprint import pformat
import atexit
-import ayon_core.hosts.flame.api as opfapi
+import ayon_flame.api as opfapi
from ayon_core.pipeline import (
install_host,
registered_host,
diff --git a/server_addon/flame/client/ayon_flame/version.py b/server_addon/flame/client/ayon_flame/version.py
new file mode 100644
index 0000000000..0004797e59
--- /dev/null
+++ b/server_addon/flame/client/ayon_flame/version.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+"""Package declaring AYON addon 'flame' version."""
+__version__ = "0.2.0"
diff --git a/server_addon/flame/package.py b/server_addon/flame/package.py
index 8c077ed91d..f228e61f8e 100644
--- a/server_addon/flame/package.py
+++ b/server_addon/flame/package.py
@@ -1,3 +1,10 @@
name = "flame"
title = "Flame"
-version = "0.1.0"
+version = "0.2.0"
+
+client_dir = "ayon_flame"
+
+ayon_required_addons = {
+ "core": ">0.3.2",
+}
+ayon_compatible_addons = {}
diff --git a/client/ayon_core/hosts/max/__init__.py b/server_addon/max/client/ayon_max/__init__.py
similarity index 100%
rename from client/ayon_core/hosts/max/__init__.py
rename to server_addon/max/client/ayon_max/__init__.py
diff --git a/client/ayon_core/hosts/max/addon.py b/server_addon/max/client/ayon_max/addon.py
similarity index 100%
rename from client/ayon_core/hosts/max/addon.py
rename to server_addon/max/client/ayon_max/addon.py
diff --git a/client/ayon_core/hosts/max/api/__init__.py b/server_addon/max/client/ayon_max/api/__init__.py
similarity index 100%
rename from client/ayon_core/hosts/max/api/__init__.py
rename to server_addon/max/client/ayon_max/api/__init__.py
diff --git a/client/ayon_core/hosts/max/api/action.py b/server_addon/max/client/ayon_max/api/action.py
similarity index 100%
rename from client/ayon_core/hosts/max/api/action.py
rename to server_addon/max/client/ayon_max/api/action.py
diff --git a/client/ayon_core/hosts/max/api/colorspace.py b/server_addon/max/client/ayon_max/api/colorspace.py
similarity index 100%
rename from client/ayon_core/hosts/max/api/colorspace.py
rename to server_addon/max/client/ayon_max/api/colorspace.py
diff --git a/client/ayon_core/hosts/max/api/lib.py b/server_addon/max/client/ayon_max/api/lib.py
similarity index 99%
rename from client/ayon_core/hosts/max/api/lib.py
rename to server_addon/max/client/ayon_max/api/lib.py
index f20f754248..eb22dbafd2 100644
--- a/client/ayon_core/hosts/max/api/lib.py
+++ b/server_addon/max/client/ayon_max/api/lib.py
@@ -20,7 +20,7 @@ from pymxs import runtime as rt
JSON_PREFIX = "JSON::"
-log = logging.getLogger("ayon_core.hosts.max")
+log = logging.getLogger("ayon_max")
def get_main_window():
diff --git a/client/ayon_core/hosts/max/api/lib_renderproducts.py b/server_addon/max/client/ayon_max/api/lib_renderproducts.py
similarity index 99%
rename from client/ayon_core/hosts/max/api/lib_renderproducts.py
rename to server_addon/max/client/ayon_max/api/lib_renderproducts.py
index 710ed0031a..82a6a0c20c 100644
--- a/client/ayon_core/hosts/max/api/lib_renderproducts.py
+++ b/server_addon/max/client/ayon_max/api/lib_renderproducts.py
@@ -6,7 +6,7 @@ import os
from pymxs import runtime as rt
-from ayon_core.hosts.max.api.lib import get_current_renderer
+from ayon_max.api.lib import get_current_renderer
from ayon_core.pipeline import get_current_project_name
from ayon_core.settings import get_project_settings
diff --git a/client/ayon_core/hosts/max/api/lib_rendersettings.py b/server_addon/max/client/ayon_max/api/lib_rendersettings.py
similarity index 99%
rename from client/ayon_core/hosts/max/api/lib_rendersettings.py
rename to server_addon/max/client/ayon_max/api/lib_rendersettings.py
index 35b6d064c1..4b65e1397e 100644
--- a/client/ayon_core/hosts/max/api/lib_rendersettings.py
+++ b/server_addon/max/client/ayon_max/api/lib_rendersettings.py
@@ -5,7 +5,7 @@ from ayon_core.settings import get_project_settings
from ayon_core.pipeline import get_current_project_name
from ayon_core.pipeline.context_tools import get_current_folder_entity
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api.lib import (
set_render_frame_range,
get_current_renderer,
get_default_render_folder
diff --git a/client/ayon_core/hosts/max/api/menu.py b/server_addon/max/client/ayon_max/api/menu.py
similarity index 99%
rename from client/ayon_core/hosts/max/api/menu.py
rename to server_addon/max/client/ayon_max/api/menu.py
index c6ceeb3a43..25dd39fd84 100644
--- a/client/ayon_core/hosts/max/api/menu.py
+++ b/server_addon/max/client/ayon_max/api/menu.py
@@ -5,7 +5,7 @@ from qtpy import QtWidgets, QtCore
from pymxs import runtime as rt
from ayon_core.tools.utils import host_tools
-from ayon_core.hosts.max.api import lib
+from ayon_max.api import lib
class AYONMenu(object):
diff --git a/client/ayon_core/hosts/max/api/pipeline.py b/server_addon/max/client/ayon_max/api/pipeline.py
similarity index 97%
rename from client/ayon_core/hosts/max/api/pipeline.py
rename to server_addon/max/client/ayon_max/api/pipeline.py
index d9cfc3407f..5f5e896e86 100644
--- a/client/ayon_core/hosts/max/api/pipeline.py
+++ b/server_addon/max/client/ayon_max/api/pipeline.py
@@ -14,14 +14,14 @@ from ayon_core.pipeline import (
AVALON_CONTAINER_ID,
AYON_CONTAINER_ID,
)
-from ayon_core.hosts.max.api.menu import AYONMenu
-from ayon_core.hosts.max.api import lib
-from ayon_core.hosts.max.api.plugin import MS_CUSTOM_ATTRIB
-from ayon_core.hosts.max import MAX_HOST_DIR
+from ayon_max.api.menu import AYONMenu
+from ayon_max.api import lib
+from ayon_max.api.plugin import MS_CUSTOM_ATTRIB
+from ayon_max import MAX_HOST_DIR
from pymxs import runtime as rt # noqa
-log = logging.getLogger("ayon_core.hosts.max")
+log = logging.getLogger("ayon_max")
PLUGINS_DIR = os.path.join(MAX_HOST_DIR, "plugins")
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
diff --git a/client/ayon_core/hosts/max/api/plugin.py b/server_addon/max/client/ayon_max/api/plugin.py
similarity index 100%
rename from client/ayon_core/hosts/max/api/plugin.py
rename to server_addon/max/client/ayon_max/api/plugin.py
diff --git a/client/ayon_core/hosts/max/api/preview_animation.py b/server_addon/max/client/ayon_max/api/preview_animation.py
similarity index 99%
rename from client/ayon_core/hosts/max/api/preview_animation.py
rename to server_addon/max/client/ayon_max/api/preview_animation.py
index 399d3b6222..acda5360a1 100644
--- a/client/ayon_core/hosts/max/api/preview_animation.py
+++ b/server_addon/max/client/ayon_max/api/preview_animation.py
@@ -3,7 +3,7 @@ import contextlib
from pymxs import runtime as rt
from .lib import get_max_version, render_resolution
-log = logging.getLogger("ayon_core.hosts.max")
+log = logging.getLogger("ayon_max")
@contextlib.contextmanager
diff --git a/client/ayon_core/hosts/max/hooks/force_startup_script.py b/server_addon/max/client/ayon_max/hooks/force_startup_script.py
similarity index 94%
rename from client/ayon_core/hosts/max/hooks/force_startup_script.py
rename to server_addon/max/client/ayon_max/hooks/force_startup_script.py
index 417f0049ab..1699ea300a 100644
--- a/client/ayon_core/hosts/max/hooks/force_startup_script.py
+++ b/server_addon/max/client/ayon_max/hooks/force_startup_script.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""Pre-launch to force 3ds max startup script."""
import os
-from ayon_core.hosts.max import MAX_HOST_DIR
+from ayon_max import MAX_HOST_DIR
from ayon_applications import PreLaunchHook, LaunchTypes
diff --git a/client/ayon_core/hosts/max/hooks/inject_python.py b/server_addon/max/client/ayon_max/hooks/inject_python.py
similarity index 100%
rename from client/ayon_core/hosts/max/hooks/inject_python.py
rename to server_addon/max/client/ayon_max/hooks/inject_python.py
diff --git a/client/ayon_core/hosts/max/hooks/set_paths.py b/server_addon/max/client/ayon_max/hooks/set_paths.py
similarity index 100%
rename from client/ayon_core/hosts/max/hooks/set_paths.py
rename to server_addon/max/client/ayon_max/hooks/set_paths.py
diff --git a/client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/__init__.py b/server_addon/max/client/ayon_max/plugins/__init__.py
similarity index 100%
rename from client/ayon_core/hosts/flame/startup/openpype_babypublisher/modules/__init__.py
rename to server_addon/max/client/ayon_max/plugins/__init__.py
diff --git a/client/ayon_core/hosts/max/plugins/create/create_camera.py b/server_addon/max/client/ayon_max/plugins/create/create_camera.py
similarity index 80%
rename from client/ayon_core/hosts/max/plugins/create/create_camera.py
rename to server_addon/max/client/ayon_max/plugins/create/create_camera.py
index 42f8cb716d..451e178afc 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_camera.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_camera.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating camera."""
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
class CreateCamera(plugin.MaxCreator):
@@ -9,3 +9,5 @@ class CreateCamera(plugin.MaxCreator):
label = "Camera"
product_type = "camera"
icon = "gear"
+
+ settings_category = "max"
diff --git a/client/ayon_core/hosts/max/plugins/create/create_maxScene.py b/server_addon/max/client/ayon_max/plugins/create/create_maxScene.py
similarity index 81%
rename from client/ayon_core/hosts/max/plugins/create/create_maxScene.py
rename to server_addon/max/client/ayon_max/plugins/create/create_maxScene.py
index 0e5768b267..ee58ef663d 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_maxScene.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_maxScene.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating raw max scene."""
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
class CreateMaxScene(plugin.MaxCreator):
@@ -9,3 +9,5 @@ class CreateMaxScene(plugin.MaxCreator):
label = "Max Scene"
product_type = "maxScene"
icon = "gear"
+
+ settings_category = "max"
diff --git a/client/ayon_core/hosts/max/plugins/create/create_model.py b/server_addon/max/client/ayon_max/plugins/create/create_model.py
similarity index 79%
rename from client/ayon_core/hosts/max/plugins/create/create_model.py
rename to server_addon/max/client/ayon_max/plugins/create/create_model.py
index 297c92067e..f48182ecd7 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_model.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_model.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for model."""
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
class CreateModel(plugin.MaxCreator):
@@ -9,3 +9,5 @@ class CreateModel(plugin.MaxCreator):
label = "Model"
product_type = "model"
icon = "gear"
+
+ settings_category = "max"
diff --git a/client/ayon_core/hosts/max/plugins/create/create_pointcache.py b/server_addon/max/client/ayon_max/plugins/create/create_pointcache.py
similarity index 82%
rename from client/ayon_core/hosts/max/plugins/create/create_pointcache.py
rename to server_addon/max/client/ayon_max/plugins/create/create_pointcache.py
index eb0686a0c0..6d7aabe12c 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_pointcache.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_pointcache.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating pointcache alembics."""
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
class CreatePointCache(plugin.MaxCreator):
@@ -9,3 +9,5 @@ class CreatePointCache(plugin.MaxCreator):
label = "Point Cache"
product_type = "pointcache"
icon = "gear"
+
+ settings_category = "max"
diff --git a/client/ayon_core/hosts/max/plugins/create/create_pointcloud.py b/server_addon/max/client/ayon_max/plugins/create/create_pointcloud.py
similarity index 82%
rename from client/ayon_core/hosts/max/plugins/create/create_pointcloud.py
rename to server_addon/max/client/ayon_max/plugins/create/create_pointcloud.py
index 9a58f4e624..52014d77b2 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_pointcloud.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_pointcloud.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating point cloud."""
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
class CreatePointCloud(plugin.MaxCreator):
@@ -9,3 +9,5 @@ class CreatePointCloud(plugin.MaxCreator):
label = "Point Cloud"
product_type = "pointcloud"
icon = "gear"
+
+ settings_category = "max"
diff --git a/client/ayon_core/hosts/max/plugins/create/create_redshift_proxy.py b/server_addon/max/client/ayon_max/plugins/create/create_redshift_proxy.py
similarity index 80%
rename from client/ayon_core/hosts/max/plugins/create/create_redshift_proxy.py
rename to server_addon/max/client/ayon_max/plugins/create/create_redshift_proxy.py
index 17f5349dc1..bcc96c7efe 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_redshift_proxy.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_redshift_proxy.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating camera."""
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
class CreateRedshiftProxy(plugin.MaxCreator):
@@ -8,3 +8,5 @@ class CreateRedshiftProxy(plugin.MaxCreator):
label = "Redshift Proxy"
product_type = "redshiftproxy"
icon = "gear"
+
+ settings_category = "max"
diff --git a/client/ayon_core/hosts/max/plugins/create/create_render.py b/server_addon/max/client/ayon_max/plugins/create/create_render.py
similarity index 93%
rename from client/ayon_core/hosts/max/plugins/create/create_render.py
rename to server_addon/max/client/ayon_max/plugins/create/create_render.py
index 60fe628a5e..d1e236f3ef 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_render.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_render.py
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating camera."""
import os
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
from ayon_core.lib import BoolDef
-from ayon_core.hosts.max.api.lib_rendersettings import RenderSettings
+from ayon_max.api.lib_rendersettings import RenderSettings
class CreateRender(plugin.MaxCreator):
@@ -13,6 +13,8 @@ class CreateRender(plugin.MaxCreator):
product_type = "maxrender"
icon = "gear"
+ settings_category = "max"
+
def create(self, product_name, instance_data, pre_create_data):
from pymxs import runtime as rt
file = rt.maxFileName
diff --git a/client/ayon_core/hosts/max/plugins/create/create_review.py b/server_addon/max/client/ayon_max/plugins/create/create_review.py
similarity index 98%
rename from client/ayon_core/hosts/max/plugins/create/create_review.py
rename to server_addon/max/client/ayon_max/plugins/create/create_review.py
index 0a0ffd2e46..a49490519a 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_review.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_review.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating review in Max."""
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
from ayon_core.lib import BoolDef, EnumDef, NumberDef
@@ -12,6 +12,8 @@ class CreateReview(plugin.MaxCreator):
product_type = "review"
icon = "video-camera"
+ settings_category = "max"
+
review_width = 1920
review_height = 1080
percentSize = 100
diff --git a/client/ayon_core/hosts/max/plugins/create/create_tycache.py b/server_addon/max/client/ayon_max/plugins/create/create_tycache.py
similarity index 80%
rename from client/ayon_core/hosts/max/plugins/create/create_tycache.py
rename to server_addon/max/client/ayon_max/plugins/create/create_tycache.py
index 2b3893bf13..cbdd94e272 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_tycache.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_tycache.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating TyCache."""
-from ayon_core.hosts.max.api import plugin
+from ayon_max.api import plugin
class CreateTyCache(plugin.MaxCreator):
@@ -9,3 +9,5 @@ class CreateTyCache(plugin.MaxCreator):
label = "TyCache"
product_type = "tycache"
icon = "gear"
+
+ settings_category = "max"
diff --git a/client/ayon_core/hosts/max/plugins/create/create_workfile.py b/server_addon/max/client/ayon_max/plugins/create/create_workfile.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/create/create_workfile.py
rename to server_addon/max/client/ayon_max/plugins/create/create_workfile.py
index 901da6254c..35c41f0fcc 100644
--- a/client/ayon_core/hosts/max/plugins/create/create_workfile.py
+++ b/server_addon/max/client/ayon_max/plugins/create/create_workfile.py
@@ -3,8 +3,8 @@
import ayon_api
from ayon_core.pipeline import CreatedInstance, AutoCreator
-from ayon_core.hosts.max.api import plugin
-from ayon_core.hosts.max.api.lib import read, imprint
+from ayon_max.api import plugin
+from ayon_max.api.lib import read, imprint
from pymxs import runtime as rt
@@ -17,6 +17,8 @@ class CreateWorkfile(plugin.MaxCreatorBase, AutoCreator):
default_variant = "Main"
+ settings_category = "max"
+
def create(self):
variant = self.default_variant
current_instance = next(
diff --git a/client/ayon_core/hosts/max/plugins/load/load_camera_fbx.py b/server_addon/max/client/ayon_max/plugins/load/load_camera_fbx.py
similarity index 96%
rename from client/ayon_core/hosts/max/plugins/load/load_camera_fbx.py
rename to server_addon/max/client/ayon_max/plugins/load/load_camera_fbx.py
index 6f1e9988c5..81ea15d52a 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_camera_fbx.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_camera_fbx.py
@@ -1,12 +1,12 @@
import os
-from ayon_core.hosts.max.api import lib
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib
+from ayon_max.api.lib import (
unique_namespace,
get_namespace,
object_transform_set
)
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise,
get_previous_loaded_object,
update_custom_attribute_data,
diff --git a/client/ayon_core/hosts/max/plugins/load/load_max_scene.py b/server_addon/max/client/ayon_max/plugins/load/load_max_scene.py
similarity index 98%
rename from client/ayon_core/hosts/max/plugins/load/load_max_scene.py
rename to server_addon/max/client/ayon_max/plugins/load/load_max_scene.py
index 97b8c6cd52..7fca69b193 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_max_scene.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_max_scene.py
@@ -1,14 +1,14 @@
import os
from qtpy import QtWidgets, QtCore
from ayon_core.lib.attribute_definitions import EnumDef
-from ayon_core.hosts.max.api import lib
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib
+from ayon_max.api.lib import (
unique_namespace,
get_namespace,
object_transform_set,
is_headless
)
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise, get_previous_loaded_object,
update_custom_attribute_data,
remove_container_data
diff --git a/client/ayon_core/hosts/max/plugins/load/load_model.py b/server_addon/max/client/ayon_max/plugins/load/load_model.py
similarity index 96%
rename from client/ayon_core/hosts/max/plugins/load/load_model.py
rename to server_addon/max/client/ayon_max/plugins/load/load_model.py
index 1070fce2bd..2a6bc45c18 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_model.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_model.py
@@ -1,12 +1,12 @@
import os
from ayon_core.pipeline import load, get_representation_path
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise,
get_previous_loaded_object,
remove_container_data
)
-from ayon_core.hosts.max.api import lib
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib
+from ayon_max.api.lib import (
maintained_selection, unique_namespace
)
diff --git a/client/ayon_core/hosts/max/plugins/load/load_model_fbx.py b/server_addon/max/client/ayon_max/plugins/load/load_model_fbx.py
similarity index 94%
rename from client/ayon_core/hosts/max/plugins/load/load_model_fbx.py
rename to server_addon/max/client/ayon_max/plugins/load/load_model_fbx.py
index 6f5de20ae0..2775e1b453 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_model_fbx.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_model_fbx.py
@@ -1,17 +1,17 @@
import os
from ayon_core.pipeline import load, get_representation_path
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise, get_previous_loaded_object,
update_custom_attribute_data,
remove_container_data
)
-from ayon_core.hosts.max.api import lib
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib
+from ayon_max.api.lib import (
unique_namespace,
get_namespace,
object_transform_set
)
-from ayon_core.hosts.max.api.lib import maintained_selection
+from ayon_max.api.lib import maintained_selection
class FbxModelLoader(load.LoaderPlugin):
diff --git a/client/ayon_core/hosts/max/plugins/load/load_model_obj.py b/server_addon/max/client/ayon_max/plugins/load/load_model_obj.py
similarity index 95%
rename from client/ayon_core/hosts/max/plugins/load/load_model_obj.py
rename to server_addon/max/client/ayon_max/plugins/load/load_model_obj.py
index a9119259df..d38aadb5bc 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_model_obj.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_model_obj.py
@@ -1,13 +1,13 @@
import os
-from ayon_core.hosts.max.api import lib
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib
+from ayon_max.api.lib import (
unique_namespace,
get_namespace,
maintained_selection,
object_transform_set
)
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise,
get_previous_loaded_object,
update_custom_attribute_data,
diff --git a/client/ayon_core/hosts/max/plugins/load/load_model_usd.py b/server_addon/max/client/ayon_max/plugins/load/load_model_usd.py
similarity index 95%
rename from client/ayon_core/hosts/max/plugins/load/load_model_usd.py
rename to server_addon/max/client/ayon_max/plugins/load/load_model_usd.py
index 2ed5d64a18..f4dd41d5db 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_model_usd.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_model_usd.py
@@ -2,15 +2,15 @@ import os
from pymxs import runtime as rt
from ayon_core.pipeline.load import LoadError
-from ayon_core.hosts.max.api import lib
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib
+from ayon_max.api.lib import (
unique_namespace,
get_namespace,
object_transform_set,
get_plugins
)
-from ayon_core.hosts.max.api.lib import maintained_selection
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.lib import maintained_selection
+from ayon_max.api.pipeline import (
containerise,
get_previous_loaded_object,
update_custom_attribute_data,
diff --git a/client/ayon_core/hosts/max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py
similarity index 95%
rename from client/ayon_core/hosts/max/plugins/load/load_pointcache.py
rename to server_addon/max/client/ayon_max/plugins/load/load_pointcache.py
index 0743b3bb34..d7def3d0ba 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_pointcache.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py
@@ -6,9 +6,9 @@ Because of limited api, alembics can be only loaded, but not easily updated.
"""
import os
from ayon_core.pipeline import load, get_representation_path
-from ayon_core.hosts.max.api import lib, maintained_selection
-from ayon_core.hosts.max.api.lib import unique_namespace
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api import lib, maintained_selection
+from ayon_max.api.lib import unique_namespace
+from ayon_max.api.pipeline import (
containerise,
get_previous_loaded_object,
remove_container_data
diff --git a/client/ayon_core/hosts/max/plugins/load/load_pointcache_ornatrix.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache_ornatrix.py
similarity index 96%
rename from client/ayon_core/hosts/max/plugins/load/load_pointcache_ornatrix.py
rename to server_addon/max/client/ayon_max/plugins/load/load_pointcache_ornatrix.py
index 47690f84e9..bc997951c1 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_pointcache_ornatrix.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache_ornatrix.py
@@ -1,20 +1,20 @@
import os
from ayon_core.pipeline import load, get_representation_path
from ayon_core.pipeline.load import LoadError
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise,
get_previous_loaded_object,
update_custom_attribute_data,
remove_container_data
)
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api.lib import (
unique_namespace,
get_namespace,
object_transform_set,
get_plugins
)
-from ayon_core.hosts.max.api import lib
+from ayon_max.api import lib
from pymxs import runtime as rt
diff --git a/client/ayon_core/hosts/max/plugins/load/load_pointcloud.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcloud.py
similarity index 92%
rename from client/ayon_core/hosts/max/plugins/load/load_pointcloud.py
rename to server_addon/max/client/ayon_max/plugins/load/load_pointcloud.py
index 0e79882fc5..0fb506d5bd 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_pointcloud.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcloud.py
@@ -1,11 +1,11 @@
import os
-from ayon_core.hosts.max.api import lib, maintained_selection
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib, maintained_selection
+from ayon_max.api.lib import (
unique_namespace,
)
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise,
get_previous_loaded_object,
update_custom_attribute_data,
diff --git a/client/ayon_core/hosts/max/plugins/load/load_redshift_proxy.py b/server_addon/max/client/ayon_max/plugins/load/load_redshift_proxy.py
similarity index 94%
rename from client/ayon_core/hosts/max/plugins/load/load_redshift_proxy.py
rename to server_addon/max/client/ayon_max/plugins/load/load_redshift_proxy.py
index 22d42390d9..3fd84b7538 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_redshift_proxy.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_redshift_proxy.py
@@ -6,14 +6,14 @@ from ayon_core.pipeline import (
get_representation_path
)
from ayon_core.pipeline.load import LoadError
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise,
update_custom_attribute_data,
get_previous_loaded_object,
remove_container_data
)
-from ayon_core.hosts.max.api import lib
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib
+from ayon_max.api.lib import (
unique_namespace,
get_plugins
)
diff --git a/client/ayon_core/hosts/max/plugins/load/load_tycache.py b/server_addon/max/client/ayon_max/plugins/load/load_tycache.py
similarity index 92%
rename from client/ayon_core/hosts/max/plugins/load/load_tycache.py
rename to server_addon/max/client/ayon_max/plugins/load/load_tycache.py
index 7a5296d933..e087d5599a 100644
--- a/client/ayon_core/hosts/max/plugins/load/load_tycache.py
+++ b/server_addon/max/client/ayon_max/plugins/load/load_tycache.py
@@ -1,10 +1,10 @@
import os
-from ayon_core.hosts.max.api import lib, maintained_selection
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api import lib, maintained_selection
+from ayon_max.api.lib import (
unique_namespace,
)
-from ayon_core.hosts.max.api.pipeline import (
+from ayon_max.api.pipeline import (
containerise,
get_previous_loaded_object,
update_custom_attribute_data,
diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_current_file.py b/server_addon/max/client/ayon_max/plugins/publish/collect_current_file.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/collect_current_file.py
rename to server_addon/max/client/ayon_max/plugins/publish/collect_current_file.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_frame_range.py b/server_addon/max/client/ayon_max/plugins/publish/collect_frame_range.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/collect_frame_range.py
rename to server_addon/max/client/ayon_max/plugins/publish/collect_frame_range.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_members.py b/server_addon/max/client/ayon_max/plugins/publish/collect_members.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/collect_members.py
rename to server_addon/max/client/ayon_max/plugins/publish/collect_members.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_render.py b/server_addon/max/client/ayon_max/plugins/publish/collect_render.py
similarity index 94%
rename from client/ayon_core/hosts/max/plugins/publish/collect_render.py
rename to server_addon/max/client/ayon_max/plugins/publish/collect_render.py
index 4ad9dfb3a3..a5e8d65df2 100644
--- a/client/ayon_core/hosts/max/plugins/publish/collect_render.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/collect_render.py
@@ -5,10 +5,10 @@ import pyblish.api
from pymxs import runtime as rt
from ayon_core.pipeline.publish import KnownPublishError
-from ayon_core.hosts.max.api import colorspace
-from ayon_core.hosts.max.api.lib import get_max_version, get_current_renderer
-from ayon_core.hosts.max.api.lib_rendersettings import RenderSettings
-from ayon_core.hosts.max.api.lib_renderproducts import RenderProducts
+from ayon_max.api import colorspace
+from ayon_max.api.lib import get_max_version, get_current_renderer
+from ayon_max.api.lib_rendersettings import RenderSettings
+from ayon_max.api.lib_renderproducts import RenderProducts
class CollectRender(pyblish.api.InstancePlugin):
diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_review.py b/server_addon/max/client/ayon_max/plugins/publish/collect_review.py
similarity index 99%
rename from client/ayon_core/hosts/max/plugins/publish/collect_review.py
rename to server_addon/max/client/ayon_max/plugins/publish/collect_review.py
index d746e2b2db..321aa7439c 100644
--- a/client/ayon_core/hosts/max/plugins/publish/collect_review.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/collect_review.py
@@ -4,7 +4,7 @@ import pyblish.api
from pymxs import runtime as rt
from ayon_core.lib import BoolDef
-from ayon_core.hosts.max.api.lib import get_max_version
+from ayon_max.api.lib import get_max_version
from ayon_core.pipeline.publish import (
AYONPyblishPluginMixin,
KnownPublishError
diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_tycache_attributes.py b/server_addon/max/client/ayon_max/plugins/publish/collect_tycache_attributes.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/collect_tycache_attributes.py
rename to server_addon/max/client/ayon_max/plugins/publish/collect_tycache_attributes.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_workfile.py b/server_addon/max/client/ayon_max/plugins/publish/collect_workfile.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/collect_workfile.py
rename to server_addon/max/client/ayon_max/plugins/publish/collect_workfile.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_alembic.py b/server_addon/max/client/ayon_max/plugins/publish/extract_alembic.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/extract_alembic.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_alembic.py
index 67cec23ecc..b0999e5a78 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_alembic.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_alembic.py
@@ -41,8 +41,8 @@ import os
import pyblish.api
from ayon_core.pipeline import publish, OptionalPyblishPluginMixin
from pymxs import runtime as rt
-from ayon_core.hosts.max.api import maintained_selection
-from ayon_core.hosts.max.api.lib import suspended_refresh
+from ayon_max.api import maintained_selection
+from ayon_max.api.lib import suspended_refresh
from ayon_core.lib import BoolDef
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_fbx.py b/server_addon/max/client/ayon_max/plugins/publish/extract_fbx.py
similarity index 95%
rename from client/ayon_core/hosts/max/plugins/publish/extract_fbx.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_fbx.py
index 3d80588c47..bdfc1d0d78 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_fbx.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_fbx.py
@@ -2,8 +2,8 @@ import os
import pyblish.api
from ayon_core.pipeline import publish, OptionalPyblishPluginMixin
from pymxs import runtime as rt
-from ayon_core.hosts.max.api import maintained_selection
-from ayon_core.hosts.max.api.lib import convert_unit_scale
+from ayon_max.api import maintained_selection
+from ayon_max.api.lib import convert_unit_scale
class ExtractModelFbx(publish.Extractor, OptionalPyblishPluginMixin):
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_max_scene_raw.py b/server_addon/max/client/ayon_max/plugins/publish/extract_max_scene_raw.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/extract_max_scene_raw.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_max_scene_raw.py
index f5c703564c..ecde6d2ce9 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_max_scene_raw.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_max_scene_raw.py
@@ -15,6 +15,8 @@ class ExtractMaxSceneRaw(publish.Extractor, OptionalPyblishPluginMixin):
families = ["camera", "maxScene", "model"]
optional = True
+ settings_category = "max"
+
def process(self, instance):
if not self.is_active(instance.data):
return
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_model_obj.py b/server_addon/max/client/ayon_max/plugins/publish/extract_model_obj.py
similarity index 93%
rename from client/ayon_core/hosts/max/plugins/publish/extract_model_obj.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_model_obj.py
index 03bdde7d5d..6556bd7809 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_model_obj.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_model_obj.py
@@ -2,8 +2,8 @@ import os
import pyblish.api
from ayon_core.pipeline import publish, OptionalPyblishPluginMixin
from pymxs import runtime as rt
-from ayon_core.hosts.max.api import maintained_selection
-from ayon_core.hosts.max.api.lib import suspended_refresh
+from ayon_max.api import maintained_selection
+from ayon_max.api.lib import suspended_refresh
from ayon_core.pipeline.publish import KnownPublishError
@@ -18,6 +18,8 @@ class ExtractModelObj(publish.Extractor, OptionalPyblishPluginMixin):
families = ["model"]
optional = True
+ settings_category = "max"
+
def process(self, instance):
if not self.is_active(instance.data):
return
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_model_usd.py b/server_addon/max/client/ayon_max/plugins/publish/extract_model_usd.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/extract_model_usd.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_model_usd.py
index 64791e4c7d..a48126c6e5 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_model_usd.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_model_usd.py
@@ -3,7 +3,7 @@ import os
import pyblish.api
from pymxs import runtime as rt
-from ayon_core.hosts.max.api import maintained_selection
+from ayon_max.api import maintained_selection
from ayon_core.pipeline import OptionalPyblishPluginMixin, publish
@@ -17,6 +17,8 @@ class ExtractModelUSD(publish.Extractor,
families = ["model"]
optional = True
+ settings_category = "max"
+
def process(self, instance):
if not self.is_active(instance.data):
return
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_pointcloud.py b/server_addon/max/client/ayon_max/plugins/publish/extract_pointcloud.py
similarity index 99%
rename from client/ayon_core/hosts/max/plugins/publish/extract_pointcloud.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_pointcloud.py
index 67dde7f0a6..f763325eb9 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_pointcloud.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_pointcloud.py
@@ -3,7 +3,7 @@ import os
import pyblish.api
from pymxs import runtime as rt
-from ayon_core.hosts.max.api import maintained_selection
+from ayon_max.api import maintained_selection
from ayon_core.pipeline import publish
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_redshift_proxy.py b/server_addon/max/client/ayon_max/plugins/publish/extract_redshift_proxy.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/extract_redshift_proxy.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_redshift_proxy.py
index 6a647670bc..dfb3527be1 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_redshift_proxy.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_redshift_proxy.py
@@ -2,7 +2,7 @@ import os
import pyblish.api
from ayon_core.pipeline import publish
from pymxs import runtime as rt
-from ayon_core.hosts.max.api import maintained_selection
+from ayon_max.api import maintained_selection
class ExtractRedshiftProxy(publish.Extractor):
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_review_animation.py b/server_addon/max/client/ayon_max/plugins/publish/extract_review_animation.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/extract_review_animation.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_review_animation.py
index 12f1fbb63b..b6397d404e 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_review_animation.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_review_animation.py
@@ -1,7 +1,7 @@
import os
import pyblish.api
from ayon_core.pipeline import publish
-from ayon_core.hosts.max.api.preview_animation import (
+from ayon_max.api.preview_animation import (
render_preview_animation
)
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_thumbnail.py b/server_addon/max/client/ayon_max/plugins/publish/extract_thumbnail.py
similarity index 95%
rename from client/ayon_core/hosts/max/plugins/publish/extract_thumbnail.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_thumbnail.py
index 5764ce98c4..183e381be2 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_thumbnail.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_thumbnail.py
@@ -1,7 +1,7 @@
import os
import pyblish.api
from ayon_core.pipeline import publish
-from ayon_core.hosts.max.api.preview_animation import render_preview_animation
+from ayon_max.api.preview_animation import render_preview_animation
class ExtractThumbnail(publish.Extractor):
diff --git a/client/ayon_core/hosts/max/plugins/publish/extract_tycache.py b/server_addon/max/client/ayon_max/plugins/publish/extract_tycache.py
similarity index 98%
rename from client/ayon_core/hosts/max/plugins/publish/extract_tycache.py
rename to server_addon/max/client/ayon_max/plugins/publish/extract_tycache.py
index 50bb06a765..576abe32a2 100644
--- a/client/ayon_core/hosts/max/plugins/publish/extract_tycache.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/extract_tycache.py
@@ -3,7 +3,7 @@ import os
import pyblish.api
from pymxs import runtime as rt
-from ayon_core.hosts.max.api import maintained_selection
+from ayon_max.api import maintained_selection
from ayon_core.pipeline import publish
diff --git a/client/ayon_core/hosts/max/plugins/publish/help/validate_model_name.xml b/server_addon/max/client/ayon_max/plugins/publish/help/validate_model_name.xml
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/help/validate_model_name.xml
rename to server_addon/max/client/ayon_max/plugins/publish/help/validate_model_name.xml
diff --git a/client/ayon_core/hosts/max/plugins/publish/increment_workfile_version.py b/server_addon/max/client/ayon_max/plugins/publish/increment_workfile_version.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/increment_workfile_version.py
rename to server_addon/max/client/ayon_max/plugins/publish/increment_workfile_version.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/save_scene.py b/server_addon/max/client/ayon_max/plugins/publish/save_scene.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/save_scene.py
rename to server_addon/max/client/ayon_max/plugins/publish/save_scene.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/save_scenes_for_cameras.py b/server_addon/max/client/ayon_max/plugins/publish/save_scenes_for_cameras.py
similarity index 96%
rename from client/ayon_core/hosts/max/plugins/publish/save_scenes_for_cameras.py
rename to server_addon/max/client/ayon_max/plugins/publish/save_scenes_for_cameras.py
index 817db1b28f..a211210550 100644
--- a/client/ayon_core/hosts/max/plugins/publish/save_scenes_for_cameras.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/save_scenes_for_cameras.py
@@ -5,8 +5,8 @@ import tempfile
from pymxs import runtime as rt
from ayon_core.lib import run_subprocess
-from ayon_core.hosts.max.api.lib_rendersettings import RenderSettings
-from ayon_core.hosts.max.api.lib_renderproducts import RenderProducts
+from ayon_max.api.lib_rendersettings import RenderSettings
+from ayon_max.api.lib_renderproducts import RenderProducts
class SaveScenesForCamera(pyblish.api.InstancePlugin):
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_attributes.py b/server_addon/max/client/ayon_max/plugins/publish/validate_attributes.py
similarity index 99%
rename from client/ayon_core/hosts/max/plugins/publish/validate_attributes.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_attributes.py
index 354539871f..a489533b2c 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_attributes.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_attributes.py
@@ -61,6 +61,8 @@ class ValidateAttributes(OptionalPyblishPluginMixin,
actions = [RepairContextAction]
optional = True
+ settings_category = "max"
+
@classmethod
def get_invalid(cls, context):
attributes = json.loads(
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_camera_attributes.py b/server_addon/max/client/ayon_max/plugins/publish/validate_camera_attributes.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/validate_camera_attributes.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_camera_attributes.py
index 9398cba2b7..63a2ef39a7 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_camera_attributes.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_camera_attributes.py
@@ -6,7 +6,7 @@ from ayon_core.pipeline.publish import (
OptionalPyblishPluginMixin,
PublishValidationError
)
-from ayon_core.hosts.max.api.action import SelectInvalidAction
+from ayon_max.api.action import SelectInvalidAction
class ValidateCameraAttributes(OptionalPyblishPluginMixin,
@@ -23,6 +23,8 @@ class ValidateCameraAttributes(OptionalPyblishPluginMixin,
actions = [SelectInvalidAction, RepairAction]
optional = True
+ settings_category = "max"
+
DEFAULTS = ["fov", "nearrange", "farrange",
"nearclip", "farclip"]
CAM_TYPE = ["Freecamera", "Targetcamera",
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_camera_contents.py b/server_addon/max/client/ayon_max/plugins/publish/validate_camera_contents.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/validate_camera_contents.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_camera_contents.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_extended_viewport.py b/server_addon/max/client/ayon_max/plugins/publish/validate_extended_viewport.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/validate_extended_viewport.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_extended_viewport.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_frame_range.py b/server_addon/max/client/ayon_max/plugins/publish/validate_frame_range.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/validate_frame_range.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_frame_range.py
index 11b55232d5..9a9f22dd3e 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_frame_range.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_frame_range.py
@@ -10,7 +10,7 @@ from ayon_core.pipeline.publish import (
PublishValidationError,
KnownPublishError
)
-from ayon_core.hosts.max.api.lib import get_frame_range, set_timeline
+from ayon_max.api.lib import get_frame_range, set_timeline
class ValidateFrameRange(pyblish.api.InstancePlugin,
@@ -36,6 +36,8 @@ class ValidateFrameRange(pyblish.api.InstancePlugin,
optional = True
actions = [RepairAction]
+ settings_category = "max"
+
def process(self, instance):
if not self.is_active(instance.data):
self.log.debug("Skipping Validate Frame Range...")
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_instance_has_members.py b/server_addon/max/client/ayon_max/plugins/publish/validate_instance_has_members.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/validate_instance_has_members.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_instance_has_members.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_instance_in_context.py b/server_addon/max/client/ayon_max/plugins/publish/validate_instance_in_context.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/validate_instance_in_context.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_instance_in_context.py
index 5107665235..d5bdfe4eb0 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_instance_in_context.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_instance_in_context.py
@@ -7,7 +7,7 @@ from ayon_core.pipeline.publish import (
PublishValidationError,
OptionalPyblishPluginMixin
)
-from ayon_core.hosts.max.api.action import SelectInvalidAction
+from ayon_max.api.action import SelectInvalidAction
from pymxs import runtime as rt
@@ -27,6 +27,8 @@ class ValidateInstanceInContext(pyblish.api.InstancePlugin,
hosts = ["max"]
actions = [SelectInvalidAction, RepairAction]
+ settings_category = "max"
+
def process(self, instance):
if not self.is_active(instance.data):
return
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_loaded_plugin.py b/server_addon/max/client/ayon_max/plugins/publish/validate_loaded_plugin.py
similarity index 98%
rename from client/ayon_core/hosts/max/plugins/publish/validate_loaded_plugin.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_loaded_plugin.py
index e278041b6b..1fddc7998d 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_loaded_plugin.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_loaded_plugin.py
@@ -9,7 +9,7 @@ from ayon_core.pipeline.publish import (
OptionalPyblishPluginMixin,
PublishValidationError
)
-from ayon_core.hosts.max.api.lib import get_plugins
+from ayon_max.api.lib import get_plugins
class ValidateLoadedPlugin(OptionalPyblishPluginMixin,
@@ -25,6 +25,8 @@ class ValidateLoadedPlugin(OptionalPyblishPluginMixin,
optional = True
actions = [RepairAction]
+ settings_category = "max"
+
family_plugins_mapping = []
@classmethod
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_mesh_has_uv.py b/server_addon/max/client/ayon_max/plugins/publish/validate_mesh_has_uv.py
similarity index 95%
rename from client/ayon_core/hosts/max/plugins/publish/validate_mesh_has_uv.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_mesh_has_uv.py
index ccd91da2be..31143a60c0 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_mesh_has_uv.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_mesh_has_uv.py
@@ -1,6 +1,6 @@
import pyblish.api
-from ayon_core.hosts.max.api.action import SelectInvalidAction
+from ayon_max.api.action import SelectInvalidAction
from ayon_core.pipeline.publish import (
ValidateMeshOrder,
OptionalPyblishPluginMixin,
@@ -30,6 +30,8 @@ class ValidateMeshHasUVs(pyblish.api.InstancePlugin,
actions = [SelectInvalidAction]
optional = True
+ settings_category = "max"
+
@classmethod
def get_invalid(cls, instance):
meshes = [member for member in instance.data["members"]
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_model_contents.py b/server_addon/max/client/ayon_max/plugins/publish/validate_model_contents.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/validate_model_contents.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_model_contents.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py b/server_addon/max/client/ayon_max/plugins/publish/validate_model_name.py
similarity index 97%
rename from client/ayon_core/hosts/max/plugins/publish/validate_model_name.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_model_name.py
index eb86e2e5bd..d691b739b7 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_model_name.py
@@ -4,7 +4,7 @@ import re
import pyblish.api
-from ayon_core.hosts.max.api.action import SelectInvalidAction
+from ayon_max.api.action import SelectInvalidAction
from ayon_core.pipeline.publish import (
OptionalPyblishPluginMixin,
@@ -39,6 +39,9 @@ class ValidateModelName(pyblish.api.InstancePlugin,
families = ["model"]
label = "Validate Model Name"
actions = [SelectInvalidAction]
+
+ settings_category = "max"
+
# defined by settings
regex = r"(.*)_(?P.*)_(GEO)"
# cache
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py b/server_addon/max/client/ayon_max/plugins/publish/validate_no_animation.py
similarity index 95%
rename from client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_no_animation.py
index 4b2a18d606..26384954ca 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_no_animation.py
@@ -5,7 +5,7 @@ from ayon_core.pipeline import (
PublishValidationError,
OptionalPyblishPluginMixin
)
-from ayon_core.hosts.max.api.action import SelectInvalidAction
+from ayon_max.api.action import SelectInvalidAction
def get_invalid_keys(obj):
@@ -39,6 +39,8 @@ class ValidateNoAnimation(pyblish.api.InstancePlugin,
label = "Validate No Animation"
actions = [SelectInvalidAction]
+ settings_category = "max"
+
def process(self, instance):
if not self.is_active(instance.data):
return
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_pointcloud.py b/server_addon/max/client/ayon_max/plugins/publish/validate_pointcloud.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/validate_pointcloud.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_pointcloud.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_renderable_camera.py b/server_addon/max/client/ayon_max/plugins/publish/validate_renderable_camera.py
similarity index 95%
rename from client/ayon_core/hosts/max/plugins/publish/validate_renderable_camera.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_renderable_camera.py
index ffd6b183fe..dc05771e1b 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_renderable_camera.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_renderable_camera.py
@@ -4,7 +4,7 @@ from ayon_core.pipeline import (
PublishValidationError,
OptionalPyblishPluginMixin)
from ayon_core.pipeline.publish import RepairAction
-from ayon_core.hosts.max.api.lib import get_current_renderer
+from ayon_max.api.lib import get_current_renderer
from pymxs import runtime as rt
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py b/server_addon/max/client/ayon_max/plugins/publish/validate_renderer_redshift_proxy.py
similarity index 96%
rename from client/ayon_core/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_renderer_redshift_proxy.py
index de3a806c85..66c69bc100 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_renderer_redshift_proxy.py
@@ -3,7 +3,7 @@ import pyblish.api
from ayon_core.pipeline import PublishValidationError
from pymxs import runtime as rt
from ayon_core.pipeline.publish import RepairAction
-from ayon_core.hosts.max.api.lib import get_current_renderer
+from ayon_max.api.lib import get_current_renderer
class ValidateRendererRedshiftProxy(pyblish.api.InstancePlugin):
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_renderpasses.py b/server_addon/max/client/ayon_max/plugins/publish/validate_renderpasses.py
similarity index 98%
rename from client/ayon_core/hosts/max/plugins/publish/validate_renderpasses.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_renderpasses.py
index 394d3119c4..d0d47c6340 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_renderpasses.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_renderpasses.py
@@ -7,7 +7,7 @@ from ayon_core.pipeline.publish import (
PublishValidationError,
OptionalPyblishPluginMixin
)
-from ayon_core.hosts.max.api.lib_rendersettings import RenderSettings
+from ayon_max.api.lib_rendersettings import RenderSettings
class ValidateRenderPasses(OptionalPyblishPluginMixin,
@@ -21,6 +21,8 @@ class ValidateRenderPasses(OptionalPyblishPluginMixin,
label = "Validate Render Passes"
actions = [RepairAction]
+ settings_category = "max"
+
def process(self, instance):
invalid = self.get_invalid(instance)
if invalid:
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_resolution_setting.py b/server_addon/max/client/ayon_max/plugins/publish/validate_resolution_setting.py
similarity index 98%
rename from client/ayon_core/hosts/max/plugins/publish/validate_resolution_setting.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_resolution_setting.py
index 5f6cd0a21d..9f7ec17dd9 100644
--- a/client/ayon_core/hosts/max/plugins/publish/validate_resolution_setting.py
+++ b/server_addon/max/client/ayon_max/plugins/publish/validate_resolution_setting.py
@@ -7,7 +7,7 @@ from ayon_core.pipeline.publish import (
RepairAction,
PublishValidationError
)
-from ayon_core.hosts.max.api.lib import (
+from ayon_max.api.lib import (
reset_scene_resolution,
imprint
)
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_scene_saved.py b/server_addon/max/client/ayon_max/plugins/publish/validate_scene_saved.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/validate_scene_saved.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_scene_saved.py
diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_tyflow_data.py b/server_addon/max/client/ayon_max/plugins/publish/validate_tyflow_data.py
similarity index 100%
rename from client/ayon_core/hosts/max/plugins/publish/validate_tyflow_data.py
rename to server_addon/max/client/ayon_max/plugins/publish/validate_tyflow_data.py
diff --git a/client/ayon_core/hosts/max/startup/startup.ms b/server_addon/max/client/ayon_max/startup/startup.ms
similarity index 100%
rename from client/ayon_core/hosts/max/startup/startup.ms
rename to server_addon/max/client/ayon_max/startup/startup.ms
diff --git a/client/ayon_core/hosts/max/startup/startup.py b/server_addon/max/client/ayon_max/startup/startup.py
similarity index 88%
rename from client/ayon_core/hosts/max/startup/startup.py
rename to server_addon/max/client/ayon_max/startup/startup.py
index 49a861bad0..1462cc93b7 100644
--- a/client/ayon_core/hosts/max/startup/startup.py
+++ b/server_addon/max/client/ayon_max/startup/startup.py
@@ -1,15 +1,13 @@
# -*- coding: utf-8 -*-
import os
import sys
-
+from ayon_max.api import MaxHost
+from ayon_core.pipeline import install_host
# this might happen in some 3dsmax version where PYTHONPATH isn't added
# to sys.path automatically
for path in os.environ["PYTHONPATH"].split(os.pathsep):
if path and path not in sys.path:
sys.path.append(path)
-from ayon_core.hosts.max.api import MaxHost
-from ayon_core.pipeline import install_host
-
host = MaxHost()
install_host(host)
diff --git a/server_addon/max/package.py b/server_addon/max/package.py
index fb1f1b3050..ddd4e3b33e 100644
--- a/server_addon/max/package.py
+++ b/server_addon/max/package.py
@@ -1,3 +1,9 @@
name = "max"
title = "Max"
-version = "0.1.7"
+version = "0.2.0"
+client_dir = "ayon_max"
+
+ayon_required_addons = {
+ "core": ">0.3.2",
+}
+ayon_compatible_addons = {}
diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial_package.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial_package.py
index 5f0a84be4a..bc003c0601 100644
--- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial_package.py
+++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/create/create_editorial_package.py
@@ -16,13 +16,13 @@ class EditorialPackageCreator(TrayPublishCreator):
"""Creates instance for OTIO file from published folder.
Folder contains OTIO file and exported .mov files. Process should publish
- whole folder as single `editorial_pckg` product type and (possibly) convert
+ whole folder as single `editorial_pkg` product type and (possibly) convert
.mov files into different format and copy them into `publish` `resources`
subfolder.
"""
- identifier = "editorial_pckg"
+ identifier = "editorial_pkg"
label = "Editorial package"
- product_type = "editorial_pckg"
+ product_type = "editorial_pkg"
description = "Publish folder with OTIO file and resources"
# Position batch creator after simple creators
@@ -89,8 +89,8 @@ class EditorialPackageCreator(TrayPublishCreator):
def get_detail_description(self):
return """# Publish folder with OTIO file and video clips
- Folder contains OTIO file and exported .mov files. Process should
- publish whole folder as single `editorial_pckg` product type and
- (possibly) convert .mov files into different format and copy them into
+ Folder contains OTIO file and exported .mov files. Process should
+ publish whole folder as single `editorial_pkg` product type and
+ (possibly) convert .mov files into different format and copy them into
`publish` `resources` subfolder.
"""
diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_editorial_package.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_editorial_package.py
index cb1277546c..fb7d5cd5a1 100644
--- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_editorial_package.py
+++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/collect_editorial_package.py
@@ -1,10 +1,10 @@
-"""Produces instance.data["editorial_pckg"] data used during integration.
+"""Produces instance.data["editorial_pkg"] data used during integration.
Requires:
instance.data["creator_attributes"]["path"] - from creator
Provides:
- instance -> editorial_pckg (dict):
+ instance -> editorial_pkg (dict):
folder_path (str)
otio_path (str) - from dragged folder
resource_paths (list)
@@ -24,7 +24,7 @@ class CollectEditorialPackage(pyblish.api.InstancePlugin):
order = pyblish.api.CollectorOrder - 0.1
hosts = ["traypublisher"]
- families = ["editorial_pckg"]
+ families = ["editorial_pkg"]
def process(self, instance):
folder_path = instance.data["creator_attributes"]["folder_path"]
@@ -34,14 +34,14 @@ class CollectEditorialPackage(pyblish.api.InstancePlugin):
))
return
- instance.data["editorial_pckg"] = {}
- instance.data["editorial_pckg"]["folder_path"] = folder_path
+ instance.data["editorial_pkg"] = {}
+ instance.data["editorial_pkg"]["folder_path"] = folder_path
otio_path, resource_paths = (
self._get_otio_and_resource_paths(folder_path))
- instance.data["editorial_pckg"]["otio_path"] = otio_path
- instance.data["editorial_pckg"]["resource_paths"] = resource_paths
+ instance.data["editorial_pkg"]["otio_path"] = otio_path
+ instance.data["editorial_pkg"]["resource_paths"] = resource_paths
def _get_otio_and_resource_paths(self, folder_path):
otio_path = None
diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/extract_editorial_pckg.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/extract_editorial_pckg.py
index 6dd4e84704..3e391b5f6e 100644
--- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/extract_editorial_pckg.py
+++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/extract_editorial_pckg.py
@@ -20,27 +20,27 @@ class ExtractEditorialPckgConversion(publish.Extractor):
label = "Extract Editorial Package"
order = pyblish.api.ExtractorOrder - 0.45
hosts = ["traypublisher"]
- families = ["editorial_pckg"]
+ families = ["editorial_pkg"]
def process(self, instance):
- editorial_pckg_data = instance.data.get("editorial_pckg")
+ editorial_pkg_data = instance.data.get("editorial_pkg")
- otio_path = editorial_pckg_data["otio_path"]
+ otio_path = editorial_pkg_data["otio_path"]
otio_basename = os.path.basename(otio_path)
staging_dir = self.staging_dir(instance)
- editorial_pckg_repre = {
- 'name': "editorial_pckg",
+ editorial_pkg_repre = {
+ 'name': "editorial_pkg",
'ext': "otio",
'files': otio_basename,
"stagingDir": staging_dir,
}
otio_staging_path = os.path.join(staging_dir, otio_basename)
- instance.data["representations"].append(editorial_pckg_repre)
+ instance.data["representations"].append(editorial_pkg_repre)
publish_resource_folder = self._get_publish_resource_folder(instance)
- resource_paths = editorial_pckg_data["resource_paths"]
+ resource_paths = editorial_pkg_data["resource_paths"]
transfers = self._get_transfers(resource_paths,
publish_resource_folder)
@@ -61,13 +61,13 @@ class ExtractEditorialPckgConversion(publish.Extractor):
source_to_rootless = self._get_resource_path_mapping(instance,
transfers)
- otio_data = editorial_pckg_data["otio_data"]
+ otio_data = editorial_pkg_data["otio_data"]
otio_data = self._replace_target_urls(otio_data, source_to_rootless)
opentimelineio.adapters.write_to_file(otio_data, otio_staging_path)
self.log.info("Added Editorial Package representation: {}".format(
- editorial_pckg_repre))
+ editorial_pkg_repre))
def _get_publish_resource_folder(self, instance):
"""Calculates publish folder and create it."""
diff --git a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_editorial_package.py b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_editorial_package.py
index c63c4a6a73..02793516e2 100644
--- a/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_editorial_package.py
+++ b/server_addon/traypublisher/client/ayon_traypublisher/plugins/publish/validate_editorial_package.py
@@ -1,5 +1,7 @@
import os
import opentimelineio
+from opentimelineio.exceptions import UnsupportedSchemaError
+
import pyblish.api
from ayon_core.pipeline import PublishValidationError
@@ -17,26 +19,35 @@ class ValidateEditorialPackage(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder - 0.49
hosts = ["traypublisher"]
- families = ["editorial_pckg"]
+ families = ["editorial_pkg"]
def process(self, instance):
- editorial_pckg_data = instance.data.get("editorial_pckg")
- if not editorial_pckg_data:
+ editorial_pkg_data = instance.data.get("editorial_pkg")
+ if not editorial_pkg_data:
raise PublishValidationError("Editorial package not collected")
- folder_path = editorial_pckg_data["folder_path"]
+ folder_path = editorial_pkg_data["folder_path"]
- otio_path = editorial_pckg_data["otio_path"]
+ otio_path = editorial_pkg_data["otio_path"]
if not otio_path:
raise PublishValidationError(
f"Folder {folder_path} missing otio file")
- resource_paths = editorial_pckg_data["resource_paths"]
+ resource_paths = editorial_pkg_data["resource_paths"]
resource_file_names = {os.path.basename(path)
for path in resource_paths}
- otio_data = opentimelineio.adapters.read_from_file(otio_path)
+ try:
+ otio_data = opentimelineio.adapters.read_from_file(otio_path)
+ except UnsupportedSchemaError as e:
+ raise PublishValidationError(
+ f"Unsupported schema in otio file '{otio_path}'."
+ "Version of your OpenTimelineIO library is too old."
+ "Please update it to the latest version."
+ f"Current version is '{opentimelineio.__version__}', "
+ "but required is at least 0.16.0."
+ ) from e
target_urls = self._get_all_target_urls(otio_data)
missing_files = set()
@@ -50,7 +61,7 @@ class ValidateEditorialPackage(pyblish.api.InstancePlugin):
f"Otio file contains missing files `{missing_files}`.\n\n"
f"Please add them to `{folder_path}` and republish.")
- instance.data["editorial_pckg"]["otio_data"] = otio_data
+ instance.data["editorial_pkg"]["otio_data"] = otio_data
def _get_all_target_urls(self, otio_data):
target_urls = []
diff --git a/server_addon/traypublisher/package.py b/server_addon/traypublisher/package.py
index ea04835b45..c9b94c2b72 100644
--- a/server_addon/traypublisher/package.py
+++ b/server_addon/traypublisher/package.py
@@ -1,6 +1,6 @@
name = "traypublisher"
title = "TrayPublisher"
-version = "0.2.0"
+version = "0.2.1"
client_dir = "ayon_traypublisher"