Merge branch 'develop' into enhancement/add_missing_repair_action_validate_resolution_setting_3dsmax

This commit is contained in:
Libor Batek 2023-12-12 10:56:54 +01:00 committed by GitHub
commit e4d33ea766
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 306 additions and 53 deletions

View file

@ -35,6 +35,7 @@ body:
label: Version
description: What version are you running? Look to OpenPype Tray
options:
- 3.17.7-nightly.7
- 3.17.7-nightly.6
- 3.17.7-nightly.5
- 3.17.7-nightly.4
@ -134,7 +135,6 @@ body:
- 3.15.3-nightly.3
- 3.15.3-nightly.2
- 3.15.3-nightly.1
- 3.15.2
validations:
required: true
- type: dropdown

View file

@ -606,7 +606,7 @@ def convert_v4_version_to_v3(version):
output_data[dst_key] = version[src_key]
if "createdAt" in version:
created_at = arrow.get(version["createdAt"])
created_at = arrow.get(version["createdAt"]).to("local")
output_data["time"] = created_at.strftime("%Y%m%dT%H%M%SZ")
output["data"] = output_data

View file

@ -60,8 +60,9 @@ class ExtractLocalRender(publish.Extractor):
first_repre = not representations
if instance.data["review"] and first_repre:
repre_data["tags"] = ["review"]
thumbnail_path = os.path.join(staging_dir, files[0])
instance.data["thumbnailSource"] = thumbnail_path
# TODO return back when Extract from source same as regular
# thumbnail_path = os.path.join(staging_dir, files[0])
# instance.data["thumbnailSource"] = thumbnail_path
representations.append(repre_data)

View file

@ -198,8 +198,8 @@ def _render_preview_animation_max_pre_2024(
res_width, res_height, filename=filepath
)
dib = rt.gw.getViewportDib()
dib_width = rt.renderWidth
dib_height = rt.renderHeight
dib_width = float(dib.width)
dib_height = float(dib.height)
# aspect ratio
viewportRatio = dib_width / dib_height
renderRatio = float(res_width / res_height)

View file

@ -583,18 +583,9 @@ def prompt_new_file_with_mesh(mesh_filepath):
file_dialog.setDirectory(os.path.dirname(mesh_filepath))
url = QtCore.QUrl.fromLocalFile(os.path.basename(mesh_filepath))
file_dialog.selectUrl(url)
# Give the explorer window time to refresh to the folder and select
# the file
while not file_dialog.selectedFiles():
app.processEvents(QtCore.QEventLoop.ExcludeUserInputEvents, 1000)
print(f"Selected: {file_dialog.selectedFiles()}")
# Set it again now we know the path is refreshed - without this
# accepting the dialog will often not trigger the correct filepath
file_dialog.setDirectory(os.path.dirname(mesh_filepath))
url = QtCore.QUrl.fromLocalFile(os.path.basename(mesh_filepath))
file_dialog.selectUrl(url)
# TODO: find a way to improve the process event to
# load more complicated mesh
app.processEvents(QtCore.QEventLoop.ExcludeUserInputEvents, 3000)
file_dialog.done(file_dialog.Accepted)
app.processEvents(QtCore.QEventLoop.AllEvents)
@ -628,7 +619,12 @@ def prompt_new_file_with_mesh(mesh_filepath):
mesh_filename_label = mesh_filename.findChild(QtWidgets.QLabel)
if not mesh_filename_label.text():
dialog.close()
raise RuntimeError(f"Failed to set mesh path: {mesh_filepath}")
substance_painter.logging.warning(
"Failed to set mesh path with the prompt dialog:"
f"{mesh_filepath}\n\n"
"Creating new project directly with the mesh path instead.")
else:
dialog.done(dialog.Accepted)
new_action = _get_new_project_action()
if not new_action:

View file

@ -44,14 +44,22 @@ class SubstanceLoadProjectMesh(load.LoaderPlugin):
# Get user inputs
import_cameras = data.get("import_cameras", True)
preserve_strokes = data.get("preserve_strokes", True)
sp_settings = substance_painter.project.Settings(
import_cameras=import_cameras
)
if not substance_painter.project.is_open():
# Allow to 'initialize' a new project
path = self.filepath_from_context(context)
# TODO: improve the prompt dialog function to not
# only works for simple polygon scene
result = prompt_new_file_with_mesh(mesh_filepath=path)
if not result:
self.log.info("User cancelled new project prompt.")
return
self.log.info("User cancelled new project prompt."
"Creating new project directly from"
" Substance Painter API Instead.")
settings = substance_painter.project.create(
mesh_file_path=path, settings=sp_settings
)
else:
# Reload the mesh

View file

@ -663,7 +663,7 @@ or updating already created. Publishing will create OTIO file.
variant_name = instance_data["variant"]
# basic unique asset name
clip_name = os.path.splitext(otio_clip.name)[0].lower()
clip_name = os.path.splitext(otio_clip.name)[0]
project_doc = get_project(self.project_name)
shot_name, shot_metadata = self._shot_metadata_solver.generate_data(

View file

@ -140,7 +140,7 @@ def is_running_staging():
latest_version = get_latest_version(local=False, remote=True)
staging_version = latest_version
if current_version == production_version:
if current_version == staging_version:
return True
return is_staging_enabled()

View file

@ -68,11 +68,6 @@ class CollectResourcesPath(pyblish.api.InstancePlugin):
]
def process(self, instance):
# editorial would fail since they might not be in database yet
new_asset_publishing = instance.data.get("newAssetPublishing")
if new_asset_publishing:
self.log.debug("Instance is creating new asset. Skipping.")
return
anatomy = instance.context.data["anatomy"]

View file

@ -319,6 +319,7 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
Returns:
str: temp fpath
"""
name = name.replace("/", "_")
return os.path.normpath(
tempfile.mktemp(
prefix="pyblish_tmp_{}_".format(name),

View file

@ -56,7 +56,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
# Make sure cleanup happens to representations which are having both
# tags `delete` and `need_thumbnail`
for repre in tuple(instance.data["representations"]):
for repre in tuple(instance.data.get("representations", [])):
tags = repre.get("tags") or []
# skip representations which are going to be published on farm
if "publish_on_farm" in tags:

View file

@ -1,6 +1,6 @@
import os
from openpype import AYON_SERVER_ENABLED
from openpype.lib.openpype_version import is_running_staging
from openpype.lib.openpype_version import is_staging_enabled
RESOURCES_DIR = os.path.dirname(os.path.abspath(__file__))
@ -59,7 +59,7 @@ def get_openpype_icon_filepath(staging=None):
return get_resource("icons", "AYON_icon_dev.png")
if staging is None:
staging = is_running_staging()
staging = is_staging_enabled()
if staging:
return get_openpype_staging_icon_filepath()
@ -68,7 +68,7 @@ def get_openpype_icon_filepath(staging=None):
def get_openpype_splash_filepath(staging=None):
if staging is None:
staging = is_running_staging()
staging = is_staging_enabled()
if AYON_SERVER_ENABLED:
if os.getenv("AYON_USE_DEV") == "1":

View file

@ -56,6 +56,31 @@
"enabled": false,
"optional": true,
"family_plugins_mapping": []
},
"ExtractModelObj": {
"enabled": true,
"optional": true,
"active": false
},
"ExtractModelFbx": {
"enabled": true,
"optional": true,
"active": false
},
"ExtractModelUSD": {
"enabled": true,
"optional": true,
"active": false
},
"ExtractModel": {
"enabled": true,
"optional": true,
"active": true
},
"ExtractMaxSceneRaw": {
"enabled": true,
"optional": true,
"active": true
}
}
}

View file

@ -90,6 +90,131 @@
}
}
]
},
{
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"key": "ExtractModelObj",
"label": "Extract Obj",
"is_group": true,
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "boolean",
"key": "optional",
"label": "Optional"
},
{
"type": "boolean",
"key": "active",
"label": "Active"
}
]
},
{
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"key": "ExtractModelFbx",
"label": "Extract FBX",
"is_group": true,
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "boolean",
"key": "optional",
"label": "Optional"
},
{
"type": "boolean",
"key": "active",
"label": "Active"
}
]
},
{
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"key": "ExtractModelUSD",
"label": "Extract Geometry (USD)",
"is_group": true,
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "boolean",
"key": "optional",
"label": "Optional"
},
{
"type": "boolean",
"key": "active",
"label": "Active"
}
]
},
{
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"key": "ExtractModel",
"label": "Extract Geometry (Alembic)",
"is_group": true,
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "boolean",
"key": "optional",
"label": "Optional"
},
{
"type": "boolean",
"key": "active",
"label": "Active"
}
]
},
{
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"key": "ExtractMaxSceneRaw",
"label": "Extract Max Scene (Raw)",
"is_group": true,
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "boolean",
"key": "optional",
"label": "Optional"
},
{
"type": "boolean",
"key": "active",
"label": "Active"
}
]
}
]
}

View file

@ -44,7 +44,7 @@ def version_item_from_entity(version):
# NOTE There is also 'updatedAt', should be used that instead?
# TODO skip conversion - converting to '%Y%m%dT%H%M%SZ' is because
# 'PrettyTimeDelegate' expects it
created_at = arrow.get(version["createdAt"])
created_at = arrow.get(version["createdAt"]).to("local")
published_time = created_at.strftime("%Y%m%dT%H%M%SZ")
author = version["author"]
version_num = version["version"]

View file

@ -606,7 +606,7 @@ class PublishWorkfilesModel:
print("Failed to format workfile path: {}".format(exc))
dirpath, filename = os.path.split(workfile_path)
created_at = arrow.get(repre_entity["createdAt"])
created_at = arrow.get(repre_entity["createdAt"].to("local"))
return FileItem(
dirpath,
filename,

View file

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Package declaring Pype version."""
__version__ = "3.17.7-nightly.6"
__version__ = "3.17.7-nightly.7"

View file

@ -68,6 +68,28 @@ class PublishersModel(BaseSettingsModel):
default_factory=ValidateLoadedPluginModel,
title="Validate Loaded Plugin"
)
ExtractModelObj: BasicValidateModel = Field(
default_factory=BasicValidateModel,
title="Extract OBJ",
section="Extractors"
)
ExtractModelFbx: BasicValidateModel = Field(
default_factory=BasicValidateModel,
title="Extract FBX"
)
ExtractModelUSD: BasicValidateModel = Field(
default_factory=BasicValidateModel,
title="Extract Geometry (USD)"
)
ExtractModel: BasicValidateModel = Field(
default_factory=BasicValidateModel,
title="Extract Geometry (Alembic)"
)
ExtractMaxSceneRaw: BasicValidateModel = Field(
default_factory=BasicValidateModel,
title="Extract Max Scene (Raw)"
)
DEFAULT_PUBLISH_SETTINGS = {
"ValidateFrameRange": {
@ -83,5 +105,30 @@ DEFAULT_PUBLISH_SETTINGS = {
"enabled": False,
"optional": True,
"family_plugins_mapping": []
},
"ExtractModelObj": {
"enabled": True,
"optional": True,
"active": False
},
"ExtractModelFbx": {
"enabled": True,
"optional": True,
"active": False
},
"ExtractModelUSD": {
"enabled": True,
"optional": True,
"active": False
},
"ExtractModel": {
"enabled": True,
"optional": True,
"active": True
},
"ExtractMaxSceneRaw": {
"enabled": True,
"optional": True,
"active": True
}
}

View file

@ -1 +1 @@
__version__ = "0.1.2"
__version__ = "0.1.3"

View file

@ -60,7 +60,7 @@ class TestDeadlinePublishInAfterEffects(AEDeadlinePublishTestClass):
name="renderTest_taskMain"))
failures.append(
DBAssert.count_of_types(dbcon, "representation", 4))
DBAssert.count_of_types(dbcon, "representation", 3))
additional_args = {"context.subset": "workfileTest_task",
"context.ext": "aep"}
@ -77,7 +77,7 @@ class TestDeadlinePublishInAfterEffects(AEDeadlinePublishTestClass):
additional_args = {"context.subset": "renderTest_taskMain",
"name": "thumbnail"}
failures.append(
DBAssert.count_of_types(dbcon, "representation", 1,
DBAssert.count_of_types(dbcon, "representation", 0,
additional_args=additional_args))
additional_args = {"context.subset": "renderTest_taskMain",

View file

@ -71,7 +71,7 @@ class TestDeadlinePublishInAfterEffectsMultiComposition(AEDeadlinePublishTestCla
name="renderTest_taskMain2"))
failures.append(
DBAssert.count_of_types(dbcon, "representation", 5))
DBAssert.count_of_types(dbcon, "representation", 4))
additional_args = {"context.subset": "workfileTest_task",
"context.ext": "aep"}
@ -89,7 +89,7 @@ class TestDeadlinePublishInAfterEffectsMultiComposition(AEDeadlinePublishTestCla
additional_args = {"context.subset": "renderTest_taskMain",
"name": "thumbnail"}
failures.append(
DBAssert.count_of_types(dbcon, "representation", 1,
DBAssert.count_of_types(dbcon, "representation", 0,
additional_args=additional_args))
additional_args = {"context.subset": "renderTest_taskMain",

View file

@ -58,7 +58,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass):
name="renderTest_taskMain"))
failures.append(
DBAssert.count_of_types(dbcon, "representation", 4))
DBAssert.count_of_types(dbcon, "representation", 3))
additional_args = {"context.subset": "workfileTest_task",
"context.ext": "aep"}
@ -75,7 +75,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass):
additional_args = {"context.subset": "renderTest_taskMain",
"name": "thumbnail"}
failures.append(
DBAssert.count_of_types(dbcon, "representation", 1,
DBAssert.count_of_types(dbcon, "representation", 0,
additional_args=additional_args))
additional_args = {"context.subset": "renderTest_taskMain",

View file

@ -60,7 +60,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass):
name="renderTest_taskMain"))
failures.append(
DBAssert.count_of_types(dbcon, "representation", 4))
DBAssert.count_of_types(dbcon, "representation", 2))
additional_args = {"context.subset": "workfileTest_task",
"context.ext": "aep"}
@ -77,7 +77,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass):
additional_args = {"context.subset": "renderTest_taskMain",
"name": "thumbnail"}
failures.append(
DBAssert.count_of_types(dbcon, "representation", 1,
DBAssert.count_of_types(dbcon, "representation", 0,
additional_args=additional_args))
additional_args = {"context.subset": "renderTest_taskMain",
@ -89,7 +89,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass):
additional_args = {"context.subset": "renderTest_taskMain",
"name": "thumbnail"}
failures.append(
DBAssert.count_of_types(dbcon, "representation", 1,
DBAssert.count_of_types(dbcon, "representation", 0,
additional_args=additional_args))
additional_args = {"context.subset": "renderTest_taskMain",

View file

@ -45,7 +45,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass):
name="renderTest_taskMain"))
failures.append(
DBAssert.count_of_types(dbcon, "representation", 4))
DBAssert.count_of_types(dbcon, "representation", 3))
additional_args = {"context.subset": "workfileTest_task",
"context.ext": "aep"}
@ -62,7 +62,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass):
additional_args = {"context.subset": "renderTest_taskMain",
"name": "thumbnail"}
failures.append(
DBAssert.count_of_types(dbcon, "representation", 1,
DBAssert.count_of_types(dbcon, "representation", 0,
additional_args=additional_args))
additional_args = {"context.subset": "renderTest_taskMain",

View file

@ -54,7 +54,7 @@ class TestDeadlinePublishInMaya(MayaDeadlinePublishTestClass):
DBAssert.count_of_types(dbcon, "subset", 1,
name="workfileTest_task"))
failures.append(DBAssert.count_of_types(dbcon, "representation", 8))
failures.append(DBAssert.count_of_types(dbcon, "representation", 7))
# hero included
additional_args = {"context.subset": "modelMain",
@ -85,7 +85,7 @@ class TestDeadlinePublishInMaya(MayaDeadlinePublishTestClass):
additional_args = {"context.subset": "renderTest_taskMain_beauty",
"context.ext": "jpg"}
failures.append(
DBAssert.count_of_types(dbcon, "representation", 1,
DBAssert.count_of_types(dbcon, "representation", 0,
additional_args=additional_args))
additional_args = {"context.subset": "renderTest_taskMain_beauty",

View file

@ -69,7 +69,7 @@ class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass):
name="workfileTest_task"))
failures.append(
DBAssert.count_of_types(dbcon, "representation", 4))
DBAssert.count_of_types(dbcon, "representation", 3))
additional_args = {"context.subset": "workfileTest_task",
"context.ext": "nk"}
@ -86,7 +86,7 @@ class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass):
additional_args = {"context.subset": "renderTest_taskMain",
"name": "thumbnail"}
failures.append(
DBAssert.count_of_types(dbcon, "representation", 1,
DBAssert.count_of_types(dbcon, "representation", 0,
additional_args=additional_args))
additional_args = {"context.subset": "renderTest_taskMain",

View file

@ -481,7 +481,7 @@ class DeadlinePublishTest(PublishTest):
while not valid_date_finished:
time.sleep(0.5)
if time.time() - time_start > timeout:
raise ValueError("Timeout for DL finish reached")
raise ValueError("Timeout for Deadline finish reached")
response = requests.get(url, timeout=10)
if not response.ok:
@ -491,6 +491,61 @@ class DeadlinePublishTest(PublishTest):
if not response.json():
raise ValueError("Couldn't find {}".format(deadline_job_id))
job = response.json()[0]
def recursive_dependencies(job, results=None):
if results is None:
results = []
for dependency in job["Props"]["Dep"]:
dependency = requests.get(
"{}/api/jobs?JobId={}".format(
deadline_url, dependency["JobID"]
),
timeout=10
).json()[0]
results.append(dependency)
grand_dependencies = recursive_dependencies(
dependency, results=results
)
for grand_dependency in grand_dependencies:
if grand_dependency not in results:
results.append(grand_dependency)
return results
job_status = {
0: "Unknown",
1: "Active",
2: "Suspended",
3: "Completed",
4: "Failed",
6: "Pending"
}
jobs_to_validate = [job]
jobs_to_validate.extend(recursive_dependencies(job))
failed_jobs = []
errors = []
for job in jobs_to_validate:
if "Failed" == job_status[job["Stat"]]:
failed_jobs.append(str(job))
resp_error = requests.get(
"{}/api/jobreports?JobID={}&Data=allerrorcontents".format(
deadline_url, job["_id"]
),
timeout=10
)
errors.extend(resp_error.json())
msg = "Errors in Deadline:\n"
msg += "\n".join(errors)
assert not errors, msg
msg = "Failed in Deadline:\n"
msg += "\n".join(failed_jobs)
assert not failed_jobs, msg
# '0001-...' returned until job is finished
valid_date_finished = response.json()[0]["DateComp"][:4] != "0001"