diff --git a/openpype/hosts/houdini/plugins/publish/validate_houdini_license_category.py b/openpype/hosts/houdini/plugins/publish/validate_houdini_license_category.py index f1c52f22c1..5076acda60 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_houdini_license_category.py +++ b/openpype/hosts/houdini/plugins/publish/validate_houdini_license_category.py @@ -1,32 +1,39 @@ # -*- coding: utf-8 -*- import pyblish.api from openpype.pipeline import PublishValidationError +import hou -class ValidateHoudiniCommercialLicense(pyblish.api.InstancePlugin): - """Validate the Houdini instance runs a Commercial license. +class ValidateHoudiniNotApprenticeLicense(pyblish.api.InstancePlugin): + """Validate the Houdini instance runs a non Apprentice license. - When extracting USD files from a non-commercial Houdini license, even with - Houdini Indie license, the resulting files will get "scrambled" with - a license protection and get a special .usdnc or .usdlc suffix. + USD ROPs: + When extracting USD files from an apprentice Houdini license, + the resulting files will get "scrambled" with a license protection + and get a special .usdnc suffix. - This currently breaks the Subset/representation pipeline so we disallow - any publish with those licenses. Only the commercial license is valid. + This currently breaks the Subset/representation pipeline so we disallow + any publish with apprentice license. + Alembic ROPs: + Houdini Apprentice does not export Alembic. """ order = pyblish.api.ValidatorOrder - families = ["usd"] + families = ["usd", "abc"] hosts = ["houdini"] - label = "Houdini Commercial License" + label = "Houdini Apprentice License" def process(self, instance): - import hou + if hou.isApprentice(): + # Find which family was matched with the plug-in + families = {instance.data["family"]} + families.update(instance.data.get("families", [])) + disallowed_families = families.intersection(self.families) + families = " ".join(sorted(disallowed_families)).title() - license = hou.licenseCategory() - if license != hou.licenseCategoryType.Commercial: raise PublishValidationError( - ("USD Publishing requires a full Commercial " - "license. You are on: {}").format(license), + "{} publishing requires a non apprentice license." + .format(families), title=self.label) diff --git a/openpype/hosts/max/plugins/create/create_review.py b/openpype/hosts/max/plugins/create/create_review.py index 331d2f30ea..78d27a722b 100644 --- a/openpype/hosts/max/plugins/create/create_review.py +++ b/openpype/hosts/max/plugins/create/create_review.py @@ -12,6 +12,32 @@ class CreateReview(plugin.MaxCreator): family = "review" icon = "video-camera" + review_width = 1920 + review_height = 1080 + percentSize = 100 + keep_images = False + image_format = "png" + visual_style = "Realistic" + viewport_preset = "Quality" + vp_texture = True + anti_aliasing = "None" + + def apply_settings(self, project_settings): + settings = project_settings["max"]["CreateReview"] # noqa + + # Take some defaults from settings + self.review_width = settings.get("review_width", self.review_width) + self.review_height = settings.get("review_height", self.review_height) + self.percentSize = settings.get("percentSize", self.percentSize) + self.keep_images = settings.get("keep_images", self.keep_images) + self.image_format = settings.get("image_format", self.image_format) + self.visual_style = settings.get("visual_style", self.visual_style) + self.viewport_preset = settings.get( + "viewport_preset", self.viewport_preset) + self.anti_aliasing = settings.get( + "anti_aliasing", self.anti_aliasing) + self.vp_texture = settings.get("vp_texture", self.vp_texture) + def create(self, subset_name, instance_data, pre_create_data): # Transfer settings from pre create to instance creator_attributes = instance_data.setdefault( @@ -53,39 +79,39 @@ class CreateReview(plugin.MaxCreator): label="Review width", decimals=0, minimum=0, - default=1920), + default=self.review_width), NumberDef("review_height", label="Review height", decimals=0, minimum=0, - default=1080), - BoolDef("keepImages", - label="Keep Image Sequences", - default=False), - EnumDef("imageFormat", - image_format_enum, - default="png", - label="Image Format Options"), + default=self.review_height), NumberDef("percentSize", label="Percent of Output", - default=100, + default=self.percentSize, minimum=1, decimals=0), + BoolDef("keepImages", + label="Keep Image Sequences", + default=self.keep_images), + EnumDef("imageFormat", + image_format_enum, + default=self.image_format, + label="Image Format Options"), EnumDef("visualStyleMode", visual_style_preset_enum, - default="Realistic", + default=self.visual_style, label="Preference"), EnumDef("viewportPreset", preview_preset_enum, - default="Quality", - label="Pre-View Preset"), + default=self.viewport_preset, + label="Preview Preset"), EnumDef("antialiasingQuality", anti_aliasing_enum, - default="None", + default=self.anti_aliasing, label="Anti-aliasing Quality"), BoolDef("vpTexture", label="Viewport Texture", - default=False) + default=self.vp_texture) ] def get_pre_create_attr_defs(self): diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index 24a87020bb..fdaa8d2b91 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -16,6 +16,17 @@ "image_format": "exr", "multipass": true }, + "CreateReview": { + "review_width": 1920, + "review_height": 1080, + "percentSize": 100.0, + "keep_images": false, + "image_format": "png", + "visual_style": "Realistic", + "viewport_preset": "Quality", + "anti_aliasing": "None", + "vp_texture": true + }, "PointCloud": { "attribute": { "Age": "age", diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_max.json b/openpype/settings/entities/schemas/projects_schema/schema_project_max.json index e314174dff..78cca357a3 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_max.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_max.json @@ -65,6 +65,104 @@ } ] }, + { + "type": "dict", + "collapsible": true, + "key": "CreateReview", + "label": "Create Review", + "children": [ + { + "type": "number", + "key": "review_width", + "label": "Review Width" + }, + { + "type": "number", + "key": "review_height", + "label": "Review Height" + }, + { + "type": "number", + "key": "percentSize", + "label": "Percent of Output" + }, + { + "type": "boolean", + "key": "keep_images", + "label": "Keep Image Sequences" + }, + { + "key": "image_format", + "label": "Image Format Options", + "type": "enum", + "multiselection": false, + "defaults": "exr", + "enum_items": [ + {"exr": "exr"}, + {"jpg": "jpg"}, + {"png": "png"}, + {"tga": "tga"} + ] + }, + { + "key": "visual_style", + "label": "Preference", + "type": "enum", + "multiselection": false, + "defaults": "Realistic", + "enum_items": [ + {"Realistic": "Realistic"}, + {"Shaded": "Shaded"}, + {"Facets": "Facets"}, + {"ConsistentColors": "ConsistentColors"}, + {"HiddenLine": "HiddenLine"}, + {"Wireframe": "Wireframe"}, + {"BoundingBox": "BoundingBox"}, + {"Ink": "Ink"}, + {"ColorInk": "ColorInk"}, + {"Acrylic": "Acrylic"}, + {"Tech": "Tech"}, + {"Graphite": "Graphite"}, + {"ColorPencil": "ColorPencil"}, + {"Pastel": "Pastel"}, + {"Clay": "Clay"}, + {"ModelAssist": "ModelAssist"} + ] + }, + { + "key": "viewport_preset", + "label": "Pre-View Preset", + "type": "enum", + "multiselection": false, + "defaults": "Quality", + "enum_items": [ + {"Quality": "Quality"}, + {"Standard": "Standard"}, + {"Performance": "Performance"}, + {"DXMode": "DXMode"}, + {"Customize": "Customize"} + ] + }, + { + "key": "anti_aliasing", + "label": "Anti-aliasing Quality", + "type": "enum", + "multiselection": false, + "defaults": "None", + "enum_items": [ + {"None": "None"}, + {"2X": "2X"}, + {"4X": "4X"}, + {"8X": "8X"} + ] + }, + { + "type": "boolean", + "key": "vp_texture", + "label": "Viewport Texture" + } + ] + }, { "type": "dict", "collapsible": true, diff --git a/server_addon/max/server/settings/create_review_settings.py b/server_addon/max/server/settings/create_review_settings.py new file mode 100644 index 0000000000..43dac0730a --- /dev/null +++ b/server_addon/max/server/settings/create_review_settings.py @@ -0,0 +1,93 @@ +from pydantic import Field + +from ayon_server.settings import BaseSettingsModel + + +def image_format_enum(): + """Return enumerator for image output formats.""" + return [ + {"label": "exr", "value": "exr"}, + {"label": "jpg", "value": "jpg"}, + {"label": "png", "value": "png"}, + {"label": "tga", "value": "tga"} + ] + + +def visual_style_enum(): + """Return enumerator for viewport visual style.""" + return [ + {"label": "Realistic", "value": "Realistic"}, + {"label": "Shaded", "value": "Shaded"}, + {"label": "Facets", "value": "Facets"}, + {"label": "ConsistentColors", + "value": "ConsistentColors"}, + {"label": "Wireframe", "value": "Wireframe"}, + {"label": "BoundingBox", "value": "BoundingBox"}, + {"label": "Ink", "value": "Ink"}, + {"label": "ColorInk", "value": "ColorInk"}, + {"label": "Acrylic", "value": "Acrylic"}, + {"label": "Tech", "value": "Tech"}, + {"label": "Graphite", "value": "Graphite"}, + {"label": "ColorPencil", "value": "ColorPencil"}, + {"label": "Pastel", "value": "Pastel"}, + {"label": "Clay", "value": "Clay"}, + {"label": "ModelAssist", "value": "ModelAssist"} + ] + + +def preview_preset_enum(): + """Return enumerator for viewport visual preset.""" + return [ + {"label": "Quality", "value": "Quality"}, + {"label": "Standard", "value": "Standard"}, + {"label": "Performance", "value": "Performance"}, + {"label": "DXMode", "value": "DXMode"}, + {"label": "Customize", "value": "Customize"}, + ] + + +def anti_aliasing_enum(): + """Return enumerator for viewport anti-aliasing.""" + return [ + {"label": "None", "value": "None"}, + {"label": "2X", "value": "2X"}, + {"label": "4X", "value": "4X"}, + {"label": "8X", "value": "8X"} + ] + + +class CreateReviewModel(BaseSettingsModel): + review_width: int = Field(1920, title="Review Width") + review_height: int = Field(1080, title="Review Height") + percentSize: float = Field(100.0, title="Percent of Output") + keep_images: bool = Field(False, title="Keep Image Sequences") + image_format: str = Field( + enum_resolver=image_format_enum, + title="Image Format Options" + ) + visual_style: str = Field( + enum_resolver=visual_style_enum, + title="Preference" + ) + viewport_preset: str = Field( + enum_resolver=preview_preset_enum, + title="Preview Preset" + ) + anti_aliasing: str = Field( + enum_resolver=anti_aliasing_enum, + title="Anti-aliasing Quality" + ) + vp_texture: bool = Field(True, title="Viewport Texture") + + +DEFAULT_CREATE_REVIEW_SETTINGS = { + "review_width": 1920, + "review_height": 1080, + "percentSize": 100.0, + "keep_images": False, + "image_format": "png", + "visual_style": "Realistic", + "viewport_preset": "Quality", + "anti_aliasing": "None", + "vp_texture": True +} diff --git a/server_addon/max/server/settings/main.py b/server_addon/max/server/settings/main.py index 7f4561cbb1..ea6a11915a 100644 --- a/server_addon/max/server/settings/main.py +++ b/server_addon/max/server/settings/main.py @@ -4,6 +4,9 @@ from .imageio import ImageIOSettings from .render_settings import ( RenderSettingsModel, DEFAULT_RENDER_SETTINGS ) +from .create_review_settings import ( + CreateReviewModel, DEFAULT_CREATE_REVIEW_SETTINGS +) from .publishers import ( PublishersModel, DEFAULT_PUBLISH_SETTINGS ) @@ -29,6 +32,10 @@ class MaxSettings(BaseSettingsModel): default_factory=RenderSettingsModel, title="Render Settings" ) + CreateReview: CreateReviewModel = Field( + default_factory=CreateReviewModel, + title="Create Review" + ) PointCloud: PointCloudSettings = Field( default_factory=PointCloudSettings, title="Point Cloud" @@ -40,6 +47,7 @@ class MaxSettings(BaseSettingsModel): DEFAULT_VALUES = { "RenderSettings": DEFAULT_RENDER_SETTINGS, + "CreateReview": DEFAULT_CREATE_REVIEW_SETTINGS, "PointCloud": { "attribute": [ {"name": "Age", "value": "age"}, diff --git a/server_addon/max/server/version.py b/server_addon/max/server/version.py index 485f44ac21..b3f4756216 100644 --- a/server_addon/max/server/version.py +++ b/server_addon/max/server/version.py @@ -1 +1 @@ -__version__ = "0.1.1" +__version__ = "0.1.2"