mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 08:24:53 +01:00
TrayPublisher & StandalonePublisher: Specify version (#5142)
* modified simple creator plugin to be able handle version control * added 'allow_version_control' to simple creators * don't remove 'create_context' from pyblish context during publishing * implemented validator for existing version override * actually fill version on collected instances * version can be again changed from standalone publisher * added comment to collector * make sure the version is set always to int * removed unused import * disable validator if is disabled * fix filtered instances loop
This commit is contained in:
parent
7ecb03bb75
commit
3d41ee6591
10 changed files with 323 additions and 9 deletions
|
|
@ -222,7 +222,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin):
|
||||||
"label": subset,
|
"label": subset,
|
||||||
"name": subset,
|
"name": subset,
|
||||||
"family": in_data["family"],
|
"family": in_data["family"],
|
||||||
# "version": in_data.get("version", 1),
|
|
||||||
"frameStart": in_data.get("representations", [None])[0].get(
|
"frameStart": in_data.get("representations", [None])[0].get(
|
||||||
"frameStart", None
|
"frameStart", None
|
||||||
),
|
),
|
||||||
|
|
@ -232,6 +231,14 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin):
|
||||||
"families": instance_families
|
"families": instance_families
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
# Fill version only if 'use_next_available_version' is disabled
|
||||||
|
# and version is filled in instance data
|
||||||
|
version = in_data.get("version")
|
||||||
|
use_next_available_version = in_data.get(
|
||||||
|
"use_next_available_version", True)
|
||||||
|
if not use_next_available_version and version is not None:
|
||||||
|
instance.data["version"] = version
|
||||||
|
|
||||||
self.log.info("collected instance: {}".format(pformat(instance.data)))
|
self.log.info("collected instance: {}".format(pformat(instance.data)))
|
||||||
self.log.info("parsing data: {}".format(pformat(in_data)))
|
self.log.info("parsing data: {}".format(pformat(in_data)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,14 @@
|
||||||
from openpype.lib.attribute_definitions import FileDef
|
from openpype.client import (
|
||||||
|
get_assets,
|
||||||
|
get_subsets,
|
||||||
|
get_last_versions,
|
||||||
|
)
|
||||||
|
from openpype.lib.attribute_definitions import (
|
||||||
|
FileDef,
|
||||||
|
BoolDef,
|
||||||
|
NumberDef,
|
||||||
|
UISeparatorDef,
|
||||||
|
)
|
||||||
from openpype.lib.transcoding import IMAGE_EXTENSIONS, VIDEO_EXTENSIONS
|
from openpype.lib.transcoding import IMAGE_EXTENSIONS, VIDEO_EXTENSIONS
|
||||||
from openpype.pipeline.create import (
|
from openpype.pipeline.create import (
|
||||||
Creator,
|
Creator,
|
||||||
|
|
@ -94,6 +104,7 @@ class TrayPublishCreator(Creator):
|
||||||
class SettingsCreator(TrayPublishCreator):
|
class SettingsCreator(TrayPublishCreator):
|
||||||
create_allow_context_change = True
|
create_allow_context_change = True
|
||||||
create_allow_thumbnail = True
|
create_allow_thumbnail = True
|
||||||
|
allow_version_control = False
|
||||||
|
|
||||||
extensions = []
|
extensions = []
|
||||||
|
|
||||||
|
|
@ -101,8 +112,18 @@ class SettingsCreator(TrayPublishCreator):
|
||||||
# Pass precreate data to creator attributes
|
# Pass precreate data to creator attributes
|
||||||
thumbnail_path = pre_create_data.pop(PRE_CREATE_THUMBNAIL_KEY, None)
|
thumbnail_path = pre_create_data.pop(PRE_CREATE_THUMBNAIL_KEY, None)
|
||||||
|
|
||||||
|
# Fill 'version_to_use' if version control is enabled
|
||||||
|
if self.allow_version_control:
|
||||||
|
asset_name = data["asset"]
|
||||||
|
subset_docs_by_asset_id = self._prepare_next_versions(
|
||||||
|
[asset_name], [subset_name])
|
||||||
|
version = subset_docs_by_asset_id[asset_name].get(subset_name)
|
||||||
|
pre_create_data["version_to_use"] = version
|
||||||
|
data["_previous_last_version"] = version
|
||||||
|
|
||||||
data["creator_attributes"] = pre_create_data
|
data["creator_attributes"] = pre_create_data
|
||||||
data["settings_creator"] = True
|
data["settings_creator"] = True
|
||||||
|
|
||||||
# Create new instance
|
# Create new instance
|
||||||
new_instance = CreatedInstance(self.family, subset_name, data, self)
|
new_instance = CreatedInstance(self.family, subset_name, data, self)
|
||||||
|
|
||||||
|
|
@ -111,7 +132,158 @@ class SettingsCreator(TrayPublishCreator):
|
||||||
if thumbnail_path:
|
if thumbnail_path:
|
||||||
self.set_instance_thumbnail_path(new_instance.id, thumbnail_path)
|
self.set_instance_thumbnail_path(new_instance.id, thumbnail_path)
|
||||||
|
|
||||||
|
def _prepare_next_versions(self, asset_names, subset_names):
|
||||||
|
"""Prepare next versions for given asset and subset names.
|
||||||
|
|
||||||
|
Todos:
|
||||||
|
Expect combination of subset names by asset name to avoid
|
||||||
|
unnecessary server calls for unused subsets.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
asset_names (Iterable[str]): Asset names.
|
||||||
|
subset_names (Iterable[str]): Subset names.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict[str, dict[str, int]]: Last versions by asset
|
||||||
|
and subset names.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Prepare all versions for all combinations to '1'
|
||||||
|
subset_docs_by_asset_id = {
|
||||||
|
asset_name: {
|
||||||
|
subset_name: 1
|
||||||
|
for subset_name in subset_names
|
||||||
|
}
|
||||||
|
for asset_name in asset_names
|
||||||
|
}
|
||||||
|
if not asset_names or not subset_names:
|
||||||
|
return subset_docs_by_asset_id
|
||||||
|
|
||||||
|
asset_docs = get_assets(
|
||||||
|
self.project_name,
|
||||||
|
asset_names=asset_names,
|
||||||
|
fields=["_id", "name"]
|
||||||
|
)
|
||||||
|
asset_names_by_id = {
|
||||||
|
asset_doc["_id"]: asset_doc["name"]
|
||||||
|
for asset_doc in asset_docs
|
||||||
|
}
|
||||||
|
subset_docs = list(get_subsets(
|
||||||
|
self.project_name,
|
||||||
|
asset_ids=asset_names_by_id.keys(),
|
||||||
|
subset_names=subset_names,
|
||||||
|
fields=["_id", "name", "parent"]
|
||||||
|
))
|
||||||
|
|
||||||
|
subset_ids = {subset_doc["_id"] for subset_doc in subset_docs}
|
||||||
|
last_versions = get_last_versions(
|
||||||
|
self.project_name,
|
||||||
|
subset_ids,
|
||||||
|
fields=["name", "parent"])
|
||||||
|
|
||||||
|
for subset_doc in subset_docs:
|
||||||
|
asset_id = subset_doc["parent"]
|
||||||
|
asset_name = asset_names_by_id[asset_id]
|
||||||
|
subset_name = subset_doc["name"]
|
||||||
|
subset_id = subset_doc["_id"]
|
||||||
|
last_version = last_versions.get(subset_id)
|
||||||
|
version = 0
|
||||||
|
if last_version is not None:
|
||||||
|
version = last_version["name"]
|
||||||
|
subset_docs_by_asset_id[asset_name][subset_name] += version
|
||||||
|
return subset_docs_by_asset_id
|
||||||
|
|
||||||
|
def _fill_next_versions(self, instances_data):
|
||||||
|
"""Fill next version for instances.
|
||||||
|
|
||||||
|
Instances have also stored previous next version to be able to
|
||||||
|
recognize if user did enter different version. If version was
|
||||||
|
not changed by user, or user set it to '0' the next version will be
|
||||||
|
updated by current database state.
|
||||||
|
"""
|
||||||
|
|
||||||
|
filtered_instance_data = []
|
||||||
|
for instance in instances_data:
|
||||||
|
previous_last_version = instance.get("_previous_last_version")
|
||||||
|
creator_attributes = instance["creator_attributes"]
|
||||||
|
use_next_version = creator_attributes.get(
|
||||||
|
"use_next_version", True)
|
||||||
|
version = creator_attributes.get("version_to_use", 0)
|
||||||
|
if (
|
||||||
|
use_next_version
|
||||||
|
or version == 0
|
||||||
|
or version == previous_last_version
|
||||||
|
):
|
||||||
|
filtered_instance_data.append(instance)
|
||||||
|
|
||||||
|
asset_names = {
|
||||||
|
instance["asset"]
|
||||||
|
for instance in filtered_instance_data}
|
||||||
|
subset_names = {
|
||||||
|
instance["subset"]
|
||||||
|
for instance in filtered_instance_data}
|
||||||
|
subset_docs_by_asset_id = self._prepare_next_versions(
|
||||||
|
asset_names, subset_names
|
||||||
|
)
|
||||||
|
for instance in filtered_instance_data:
|
||||||
|
asset_name = instance["asset"]
|
||||||
|
subset_name = instance["subset"]
|
||||||
|
version = subset_docs_by_asset_id[asset_name][subset_name]
|
||||||
|
instance["creator_attributes"]["version_to_use"] = version
|
||||||
|
instance["_previous_last_version"] = version
|
||||||
|
|
||||||
|
def collect_instances(self):
|
||||||
|
"""Collect instances from host.
|
||||||
|
|
||||||
|
Overriden to be able to manage version control attributes. If version
|
||||||
|
control is disabled, the attributes will be removed from instances,
|
||||||
|
and next versions are filled if is version control enabled.
|
||||||
|
"""
|
||||||
|
|
||||||
|
instances_by_identifier = cache_and_get_instances(
|
||||||
|
self, SHARED_DATA_KEY, list_instances
|
||||||
|
)
|
||||||
|
instances = instances_by_identifier[self.identifier]
|
||||||
|
if not instances:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.allow_version_control:
|
||||||
|
self._fill_next_versions(instances)
|
||||||
|
|
||||||
|
for instance_data in instances:
|
||||||
|
# Make sure that there are not data related to version control
|
||||||
|
# if plugin does not support it
|
||||||
|
if not self.allow_version_control:
|
||||||
|
instance_data.pop("_previous_last_version", None)
|
||||||
|
creator_attributes = instance_data["creator_attributes"]
|
||||||
|
creator_attributes.pop("version_to_use", None)
|
||||||
|
creator_attributes.pop("use_next_version", None)
|
||||||
|
|
||||||
|
instance = CreatedInstance.from_existing(instance_data, self)
|
||||||
|
self._add_instance_to_context(instance)
|
||||||
|
|
||||||
def get_instance_attr_defs(self):
|
def get_instance_attr_defs(self):
|
||||||
|
defs = self.get_pre_create_attr_defs()
|
||||||
|
if self.allow_version_control:
|
||||||
|
defs += [
|
||||||
|
UISeparatorDef(),
|
||||||
|
BoolDef(
|
||||||
|
"use_next_version",
|
||||||
|
default=True,
|
||||||
|
label="Use next version",
|
||||||
|
),
|
||||||
|
NumberDef(
|
||||||
|
"version_to_use",
|
||||||
|
default=1,
|
||||||
|
minimum=0,
|
||||||
|
maximum=999,
|
||||||
|
label="Version to use",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
return defs
|
||||||
|
|
||||||
|
def get_pre_create_attr_defs(self):
|
||||||
|
# Use same attributes as for instance attributes
|
||||||
return [
|
return [
|
||||||
FileDef(
|
FileDef(
|
||||||
"representation_files",
|
"representation_files",
|
||||||
|
|
@ -132,10 +304,6 @@ class SettingsCreator(TrayPublishCreator):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_pre_create_attr_defs(self):
|
|
||||||
# Use same attributes as for instance attrobites
|
|
||||||
return self.get_instance_attr_defs()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_settings(cls, item_data):
|
def from_settings(cls, item_data):
|
||||||
identifier = item_data["identifier"]
|
identifier = item_data["identifier"]
|
||||||
|
|
@ -155,6 +323,8 @@ class SettingsCreator(TrayPublishCreator):
|
||||||
"extensions": item_data["extensions"],
|
"extensions": item_data["extensions"],
|
||||||
"allow_sequences": item_data["allow_sequences"],
|
"allow_sequences": item_data["allow_sequences"],
|
||||||
"allow_multiple_items": item_data["allow_multiple_items"],
|
"allow_multiple_items": item_data["allow_multiple_items"],
|
||||||
"default_variants": item_data["default_variants"]
|
"allow_version_control": item_data.get(
|
||||||
|
"allow_version_control", False),
|
||||||
|
"default_variants": item_data["default_variants"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ class CollectSettingsSimpleInstances(pyblish.api.InstancePlugin):
|
||||||
"Created temp staging directory for instance {}. {}"
|
"Created temp staging directory for instance {}. {}"
|
||||||
).format(instance_label, tmp_folder))
|
).format(instance_label, tmp_folder))
|
||||||
|
|
||||||
|
self._fill_version(instance, instance_label)
|
||||||
|
|
||||||
# Store filepaths for validation of their existence
|
# Store filepaths for validation of their existence
|
||||||
source_filepaths = []
|
source_filepaths = []
|
||||||
# Make sure there are no representations with same name
|
# Make sure there are no representations with same name
|
||||||
|
|
@ -93,6 +95,28 @@ class CollectSettingsSimpleInstances(pyblish.api.InstancePlugin):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _fill_version(self, instance, instance_label):
|
||||||
|
"""Fill instance version under which will be instance integrated.
|
||||||
|
|
||||||
|
Instance must have set 'use_next_version' to 'False'
|
||||||
|
and 'version_to_use' to version to use.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
instance (pyblish.api.Instance): Instance to fill version for.
|
||||||
|
instance_label (str): Label of instance to fill version for.
|
||||||
|
"""
|
||||||
|
|
||||||
|
creator_attributes = instance.data["creator_attributes"]
|
||||||
|
use_next_version = creator_attributes.get("use_next_version", True)
|
||||||
|
# If 'version_to_use' is '0' it means that next version should be used
|
||||||
|
version_to_use = creator_attributes.get("version_to_use", 0)
|
||||||
|
if use_next_version or not version_to_use:
|
||||||
|
return
|
||||||
|
instance.data["version"] = version_to_use
|
||||||
|
self.log.debug(
|
||||||
|
"Version for instance \"{}\" was set to \"{}\"".format(
|
||||||
|
instance_label, version_to_use))
|
||||||
|
|
||||||
def _create_main_representations(
|
def _create_main_representations(
|
||||||
self,
|
self,
|
||||||
instance,
|
instance,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<root>
|
||||||
|
<error id="main">
|
||||||
|
<title>Version already exists</title>
|
||||||
|
<description>
|
||||||
|
## Version already exists
|
||||||
|
|
||||||
|
Version {version} you have set on instance '{subset_name}' under '{asset_name}' already exists. This validation is enabled by default to prevent accidental override of existing versions.
|
||||||
|
|
||||||
|
### How to repair?
|
||||||
|
- Click on 'Repair' action -> this will change version to next available.
|
||||||
|
- Disable validation on the instance if you are sure you want to override the version.
|
||||||
|
- Reset publishing and manually change the version number.
|
||||||
|
</description>
|
||||||
|
</error>
|
||||||
|
</root>
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
import pyblish.api
|
||||||
|
|
||||||
|
from openpype.pipeline.publish import (
|
||||||
|
ValidateContentsOrder,
|
||||||
|
PublishXmlValidationError,
|
||||||
|
OptionalPyblishPluginMixin,
|
||||||
|
RepairAction,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateExistingVersion(
|
||||||
|
OptionalPyblishPluginMixin,
|
||||||
|
pyblish.api.InstancePlugin
|
||||||
|
):
|
||||||
|
label = "Validate Existing Version"
|
||||||
|
order = ValidateContentsOrder
|
||||||
|
|
||||||
|
hosts = ["traypublisher"]
|
||||||
|
|
||||||
|
actions = [RepairAction]
|
||||||
|
|
||||||
|
settings_category = "traypublisher"
|
||||||
|
optional = True
|
||||||
|
|
||||||
|
def process(self, instance):
|
||||||
|
if not self.is_active(instance.data):
|
||||||
|
return
|
||||||
|
|
||||||
|
version = instance.data.get("version")
|
||||||
|
if version is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
last_version = instance.data.get("latestVersion")
|
||||||
|
if last_version is None or last_version < version:
|
||||||
|
return
|
||||||
|
|
||||||
|
subset_name = instance.data["subset"]
|
||||||
|
msg = "Version {} already exists for subset {}.".format(
|
||||||
|
version, subset_name)
|
||||||
|
|
||||||
|
formatting_data = {
|
||||||
|
"subset_name": subset_name,
|
||||||
|
"asset_name": instance.data["asset"],
|
||||||
|
"version": version
|
||||||
|
}
|
||||||
|
raise PublishXmlValidationError(
|
||||||
|
self, msg, formatting_data=formatting_data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def repair(cls, instance):
|
||||||
|
create_context = instance.context.data["create_context"]
|
||||||
|
created_instance = create_context.get_instance_by_id(
|
||||||
|
instance.data["instance_id"])
|
||||||
|
creator_attributes = created_instance["creator_attributes"]
|
||||||
|
# Disable version override
|
||||||
|
creator_attributes["use_next_version"] = True
|
||||||
|
create_context.save_changes()
|
||||||
|
|
@ -1441,6 +1441,19 @@ class CreateContext:
|
||||||
"""Access to global publish attributes."""
|
"""Access to global publish attributes."""
|
||||||
return self._publish_attributes
|
return self._publish_attributes
|
||||||
|
|
||||||
|
def get_instance_by_id(self, instance_id):
|
||||||
|
"""Receive instance by id.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
instance_id (str): Instance id.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Union[CreatedInstance, None]: Instance or None if instance with
|
||||||
|
given id is not available.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._instances_by_id.get(instance_id)
|
||||||
|
|
||||||
def get_sorted_creators(self, identifiers=None):
|
def get_sorted_creators(self, identifiers=None):
|
||||||
"""Sorted creators by 'order' attribute.
|
"""Sorted creators by 'order' attribute.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class CollectFromCreateContext(pyblish.api.ContextPlugin):
|
||||||
order = pyblish.api.CollectorOrder - 0.5
|
order = pyblish.api.CollectorOrder - 0.5
|
||||||
|
|
||||||
def process(self, context):
|
def process(self, context):
|
||||||
create_context = context.data.pop("create_context", None)
|
create_context = context.data.get("create_context")
|
||||||
if not create_context:
|
if not create_context:
|
||||||
host = registered_host()
|
host = registered_host()
|
||||||
if isinstance(host, IPublishHost):
|
if isinstance(host, IPublishHost):
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
"detailed_description": "Workfiles are full scenes from any application that are directly edited by artists. They represent a state of work on a task at a given point and are usually not directly referenced into other scenes.",
|
"detailed_description": "Workfiles are full scenes from any application that are directly edited by artists. They represent a state of work on a task at a given point and are usually not directly referenced into other scenes.",
|
||||||
"allow_sequences": false,
|
"allow_sequences": false,
|
||||||
"allow_multiple_items": false,
|
"allow_multiple_items": false,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".ma",
|
".ma",
|
||||||
".mb",
|
".mb",
|
||||||
|
|
@ -57,6 +58,7 @@
|
||||||
"detailed_description": "Models should only contain geometry data, without any extras like cameras, locators or bones.\n\nKeep in mind that models published from tray publisher are not validated for correctness. ",
|
"detailed_description": "Models should only contain geometry data, without any extras like cameras, locators or bones.\n\nKeep in mind that models published from tray publisher are not validated for correctness. ",
|
||||||
"allow_sequences": false,
|
"allow_sequences": false,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".ma",
|
".ma",
|
||||||
".mb",
|
".mb",
|
||||||
|
|
@ -82,6 +84,7 @@
|
||||||
"detailed_description": "Alembic or bgeo cache of animated data",
|
"detailed_description": "Alembic or bgeo cache of animated data",
|
||||||
"allow_sequences": true,
|
"allow_sequences": true,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".abc",
|
".abc",
|
||||||
".bgeo",
|
".bgeo",
|
||||||
|
|
@ -105,6 +108,7 @@
|
||||||
"detailed_description": "Any type of image seqeuence coming from outside of the studio. Usually camera footage, but could also be animatics used for reference.",
|
"detailed_description": "Any type of image seqeuence coming from outside of the studio. Usually camera footage, but could also be animatics used for reference.",
|
||||||
"allow_sequences": true,
|
"allow_sequences": true,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".exr",
|
".exr",
|
||||||
".png",
|
".png",
|
||||||
|
|
@ -127,6 +131,7 @@
|
||||||
"detailed_description": "Sequence or single file renders",
|
"detailed_description": "Sequence or single file renders",
|
||||||
"allow_sequences": true,
|
"allow_sequences": true,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".exr",
|
".exr",
|
||||||
".png",
|
".png",
|
||||||
|
|
@ -150,6 +155,7 @@
|
||||||
"detailed_description": "Ideally this should be only camera itself with baked animation, however, it can technically also include helper geometry.",
|
"detailed_description": "Ideally this should be only camera itself with baked animation, however, it can technically also include helper geometry.",
|
||||||
"allow_sequences": false,
|
"allow_sequences": false,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".abc",
|
".abc",
|
||||||
".ma",
|
".ma",
|
||||||
|
|
@ -174,6 +180,7 @@
|
||||||
"detailed_description": "Any image data can be published as image family. References, textures, concept art, matte paints. This is a fallback 2d family for everything that doesn't fit more specific family.",
|
"detailed_description": "Any image data can be published as image family. References, textures, concept art, matte paints. This is a fallback 2d family for everything that doesn't fit more specific family.",
|
||||||
"allow_sequences": false,
|
"allow_sequences": false,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".exr",
|
".exr",
|
||||||
".jpg",
|
".jpg",
|
||||||
|
|
@ -197,6 +204,7 @@
|
||||||
"detailed_description": "Hierarchical data structure for the efficient storage and manipulation of sparse volumetric data discretized on three-dimensional grids",
|
"detailed_description": "Hierarchical data structure for the efficient storage and manipulation of sparse volumetric data discretized on three-dimensional grids",
|
||||||
"allow_sequences": true,
|
"allow_sequences": true,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".vdb"
|
".vdb"
|
||||||
]
|
]
|
||||||
|
|
@ -215,6 +223,7 @@
|
||||||
"detailed_description": "Script exported from matchmoving application to be later processed into a tracked camera with additional data",
|
"detailed_description": "Script exported from matchmoving application to be later processed into a tracked camera with additional data",
|
||||||
"allow_sequences": false,
|
"allow_sequences": false,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": []
|
"extensions": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -227,6 +236,7 @@
|
||||||
"detailed_description": "CG rigged character or prop. Rig should be clean of any extra data and directly loadable into it's respective application\t",
|
"detailed_description": "CG rigged character or prop. Rig should be clean of any extra data and directly loadable into it's respective application\t",
|
||||||
"allow_sequences": false,
|
"allow_sequences": false,
|
||||||
"allow_multiple_items": false,
|
"allow_multiple_items": false,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".ma",
|
".ma",
|
||||||
".blend",
|
".blend",
|
||||||
|
|
@ -244,6 +254,7 @@
|
||||||
"detailed_description": "Texture files with Unreal Engine naming conventions",
|
"detailed_description": "Texture files with Unreal Engine naming conventions",
|
||||||
"allow_sequences": false,
|
"allow_sequences": false,
|
||||||
"allow_multiple_items": true,
|
"allow_multiple_items": true,
|
||||||
|
"allow_version_control": false,
|
||||||
"extensions": []
|
"extensions": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -322,6 +333,11 @@
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"active": true
|
"active": true
|
||||||
|
},
|
||||||
|
"ValidateExistingVersion": {
|
||||||
|
"enabled": true,
|
||||||
|
"optional": true,
|
||||||
|
"active": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,12 @@
|
||||||
"label": "Allow multiple items",
|
"label": "Allow multiple items",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"key": "allow_version_control",
|
||||||
|
"label": "Allow version control",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "list",
|
"type": "list",
|
||||||
"key": "extensions",
|
"key": "extensions",
|
||||||
|
|
@ -346,6 +352,10 @@
|
||||||
{
|
{
|
||||||
"key": "ValidateFrameRange",
|
"key": "ValidateFrameRange",
|
||||||
"label": "Validate frame range"
|
"label": "Validate frame range"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "ValidateExistingVersion",
|
||||||
|
"label": "Validate Existing Version"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,8 @@ class FamilyWidget(QtWidgets.QWidget):
|
||||||
'family_preset_key': key,
|
'family_preset_key': key,
|
||||||
'family': family,
|
'family': family,
|
||||||
'subset': self.input_result.text(),
|
'subset': self.input_result.text(),
|
||||||
'version': self.version_spinbox.value()
|
'version': self.version_spinbox.value(),
|
||||||
|
'use_next_available_version': self.version_checkbox.isChecked(),
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue